⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gen86.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	    ap2 = g_expr (ep->v.p[1], F_DREG);	    validate (ap1);	/* in case push occurred */	    g_code (op, (ILEN) ep->etp->size, ap2, NIL_ADDRESS);	    freeop (ap2);	    freeop (ap1);	    ap2 = data_register ();	    g_code (op_mov, IL2, mk_low (ap1), ap2);	    return mk_legal (ap2, flags, ep->etp);	}    default:	return g_bin (ep, flags, op_imul);    }}/* * generate code for *= node */static ADDRESS *g_asmul P2 (const EXPR *, ep, FLAGS, flags){    OPCODE  op;    ILEN    size = IL0;    FLAGS   f = (FLAGS) (F_MEM | F_DREG);    ADDRESS *ap1, *ap2, *ap3;    switch (ep->etp->type) {    case bt_charu:    case bt_uchar:	op = op_movzbl;	f = (FLAGS) (f | F_NOEDI);	goto common;    case bt_char:    case bt_schar:	op = op_movsbl;	f = (FLAGS) (f | F_NOEDI);	goto common;    case bt_ushort:    case bt_uint16:    case bt_pointer16:    case bt_short:    case bt_int16:	op = op_mov;	size = IL2;      common:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op_imul, FALSE);	}	ap1 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_VOL));	if (size == IL0) {	    g_code (op, size, ap1, ap1);	}	ap2 = g_expr (ep->v.p[0], f);	ap3 = data_register ();	validate (ap1);	g_code (op, size, ap2, ap3);	g_code (op_imul, IL2, ap3, ap1);	g_code (op_mov, (ILEN) ep->etp->size, ap1, ap2);	freeop (ap3);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);    default:	return g_asbin (ep, flags, op_imul);    }}/* * generate code to evaluate a condition operator node (?:) */static ADDRESS *g_hook P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2;    LABEL   false_label, end_label;    TYP    *tp = ep->etp;    SIZE    offset;    FLAGS   flagx;#ifndef NDEBUG    BOOL    result_is_void = FALSE;#endif /* NDEBUG */    switch (ep->etp->type) {#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	flagx = F_FREG;	break;#endif /* FLOAT_IEEE */    case bt_void:#ifndef NDEBUG	result_is_void = TRUE;#endif /* NDEBUG */	flagx = (FLAGS) (F_ALL | F_NOVALUE);	break;    case bt_struct:    case bt_union:	tp = tp_pointer;	/*FALLTHROUGH */    default:	flagx = (FLAGS) (F_DREG | F_VOL);    }    false_label = nextlabel++;    end_label = nextlabel++;    temp_inv ();		/* I do not think I can avoid that */    offset = stack_offset;    stack_offset = 0L;    /* all registers are void */    g_falsejp (ep->v.p[0], false_label);    ep = ep->v.p[1];    /* all registers are void */    ap1 = g_expr (ep->v.p[0], flagx);#ifdef FLOAT_IEEE    if (flagx == F_MEM) {	ADDRESS *ap;	freeop (ap1);	ap = address_register ();	g_code (op_lea, IL2, ap1, ap);	ap1 = copy_addr (ap, am_ind);    }#endif /* FLOAT_IEEE */    freeop (ap1);    /* all registers are void */    g_branch (end_label);    g_label (false_label);    ap2 = g_expr (ep->v.p[1], flagx);#ifdef FLOAT_IEEE    if (flagx == F_MEM) {	ADDRESS *ap;	freeop (ap2);	ap = address_register ();	g_code (op_lea, IL2, ap2, ap);	ap1 = copy_addr (ap, am_ind);    }#endif /* FLOAT_IEEE */    assert (result_is_void || is_equal_address (ap1, ap2));    g_label (end_label);    g_stack (stack_offset);    stack_offset = offset;    return mk_legal (ap2, flags, tp);}/* * Generate the code for assign operators in bitfields */static ADDRESS *g_asbitfield P4 (const EXPR *, ep, FLAGS, flags, OPCODE, op,				 BOOL, mod){    ADDRESS *ap1, *ap2, *ap3;    EXPR   *lnode = ep->v.p[0];    int     width = (int) lnode->v.bit.width;    int     offset = (int) lnode->v.bit.offset;    ILEN    ilen = (ILEN) ep->etp->size;    UVAL    mask;    /* Evaluate the address of the LHS */    ap2 = g_expr (lnode->v.p[0], (FLAGS) (F_DREG | F_NOECX));    ap2 = copy_addr (ap2, am_indx);    /* Now get the value of the LHS, rotate and mask out unwanted bits */    ap1 = data_register ();    g_code (op_mov, ilen, ap2, ap1);    g_rotate (ap1, ilen, offset, lnode->etp, width);    /* now do the operation, masking the result back into the required size */    switch (op) {    case op_div:    case op_idiv:	/* evaluate the RHS */	ap3 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_ECX));	validate (ap1);	if (uses_temp (ap3) || ap3->mode == am_immed) {/*KDW */	    g_code (op_mov, IL2, ap3, &ecx_reg);	    freeop (ap3);	    ap3 = &ecx_reg;	}	g_code (op_mov, IL2, ap1, &eax_reg);	g_code (op, IL2, ap3, NIL_ADDRESS);	if (mod) {	    g_code (op_mov, IL2, &edx_reg, ap1);	} else {	    g_code (op_mov, IL2, &eax_reg, ap1);	}	break;    case op_asr:    case op_shr:    case op_shl:	/* evaluate the RHS */	ap3 = g_expr (ep->v.p[1], (FLAGS) (F_ALL | F_ECX));	validate (ap1);	if (ap3->mode != am_immed) {	    g_code (op_mov, ilen, ap3, &ecx_reg);	    g_code (op, ilen, &ecx_reg, ap1);	    freeop (ap3);	    break;	}	/*FALLTHRU */    default:	/* evaluate the RHS */	ap3 = g_expr (ep->v.p[1], F_ALL);	validate (ap1);	g_code (op, ilen, ap3, ap1);	freeop (ap3);    }    mask = (UVAL) bitmask ((BITSIZE) width);    g_code (op_and, ilen, mk_immed ((IVAL) mask), ap1);    /* rotate result back into position, and store */    g_rotate (ap1, ilen, -offset, tp_void, 0);    validate (ap2);    g_code (op_and, ilen, mk_immed ((IVAL) ~(mask << offset)), ap2);    g_code (op_or, ilen, ap1, ap2);    freeop (ap1);    freeop (ap2);    /* return a result */    ap2 = data_register ();    g_code (op_mov, ilen, ap1, ap2);    ap1 = ap2;    if (!(flags & F_NOVALUE)) {	/* result value needed */	g_rotate (ap1, ilen, offset, tp_void, 0);	if (mod) {	    /* post increment/decrement restore original value */	    switch (op) {	    case op_add:		g_code (op_sub, ilen, mk_immed (1L), ap1);		g_code (op_and, ilen, mk_immed ((IVAL) mask), ap1);		break;	    case op_sub:		g_code (op_add, ilen, mk_immed (1L), ap1);		g_code (op_and, ilen, mk_immed ((IVAL) mask), ap1);		break;	    default:		break;	    }	}    }    return mk_legal (ap1, flags, ep->etp);}/* * assign structures: ap1=dest, ap2=source */static void structassign P3 (ADDRESS *, ap1, ADDRESS *, ap2, SIZE, size){    ADDRESS *ap3;    if (size == 2l) {	if (ap1->mode == am_dreg) {	    ap1 = mk_indirect (ap1->preg, NIL_EXPR);	} else {	    g_code (op_mov, IL2, ap1, &edi_reg);	    ap1 = mk_indirect (EDI, NIL_EXPR);	}	if (ap2->mode == am_dreg) {	    ap1 = mk_indirect (ap2->preg, NIL_EXPR);	} else {	    g_code (op_mov, IL2, ap2, &esi_reg);	    ap2 = mk_indirect (ESI, NIL_EXPR);	}	ap3 = data_register ();	g_code (op_mov, IL2, ap2, ap3);	g_code (op_mov, IL2, ap3, ap1);	freeop (ap3);    } else {	g_code (op_lea, IL2, ap1, &edi_reg);	g_code (op_lea, IL2, ap2, &esi_reg);	if (size % 2l) {	    ap3 = mk_immed (size);	    ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_ECX), tp_char);	    g_code (op_rep, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_smov, IL1, NIL_ADDRESS, NIL_ADDRESS);	} else {	    ap3 = mk_immed ((IVAL) ((USIZE) size >> 1));	    ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_ECX), tp_int);	    g_code (op_rep, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_smov, IL2, NIL_ADDRESS, NIL_ADDRESS);	}	freeop (ap3);    }}/* * generate code for an assignment node. */static ADDRESS *g_assign P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2, *ap3;    TYP    *tp = ep->etp;    SIZE    size = tp->size;    UVAL    mask;    FLAGS   flagx = (flags & F_NOVALUE) ? F_ALL : F_ALL;    switch (tp->type) {    case bt_float:    case bt_double:    case bt_longdouble:#ifdef FLOAT_IEEE	if (fpu_option) {	    ap1 = g_expr (ep->v.p[0], F_MEM);	    ap2 = g_expr (ep->v.p[1], F_FREG);	    validate (ap1);	    g_fcode ((flags & F_NOVALUE ? op_fstp : op_fst), (ILEN) size, ap1,		     NIL_ADDRESS);	    freeop (ap2);	    freeop (ap1);	    ap1 = flags & F_NOVALUE ? NIL_ADDRESS : float_register ();	    return mk_legal (ap1, flags, tp);	}	/*FALLTHRU */#endif /* FLOAT_IEEE */    case bt_struct:    case bt_union:	ap2 = g_expr (ep->v.p[1], F_MEM);	ap1 = g_expr (ep->v.p[0], F_MEM);	validate (ap2);	structassign (ap1, ap2, size);	freeop (ap1);	return mk_legal (ap2, flags, tp_pointer);#if 0    case bt_int32:    case bt_long:    case bt_uint32:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep->v.p[1], flagx);	ap2 = g_expr (ep->v.p[0], F_ALL);	validate (ap1);	g_code (op_mov, IL2, mk_low (ap1), mk_low (ap2));	g_code (op_mov, IL2, mk_high (ap1), mk_high (ap2));	freeop (ap2);	return mk_legal (ap1, flags, tp);#endif    default:	switch (ep->v.p[0]->nodetype) {	case en_fieldref:	    /*	     * Field assignment	     */	    /* get the value */	    mask = bitmask (ep->v.p[0]->v.bit.width);	    ap1 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_VOL));	    if (ap1->mode == am_immed) {		ap1->u.offset->v.i &= (IVAL) mask;		ap3 = mk_immed ((IVAL)				(ap1->u.offset->v.u << (int) ep->v.p[0]->v.bit.offset));	    } else {		if (flags & F_NOVALUE) {		    ap3 = ap1;		    g_code (op_and, (ILEN) size, mk_immed ((IVAL) mask), ap3);		} else {		    if (is_signed_type (tp)) {			SIZE    i = tp_int->size * 8L -			    (SIZE) ep->v.p[0]->v.bit.width -			    (SIZE) ep->v.p[0]->v.bit.offset;			g_code (op_asl, (ILEN) size, mk_immed (i), ap1);			g_code (op_asr, (ILEN) size, mk_immed (i), ap1);			ap3 = data_register ();			g_code (op_mov, IL4, ap1, ap3);			g_code (op_and, (ILEN) size, mk_immed ((IVAL) mask),				ap3);		    } else {			g_code (op_and, (ILEN) size, mk_immed ((IVAL) mask),				ap1);			ap3 = data_register ();			g_code (op_mov, IL4, ap1, ap3);		    }		}		g_rotate (ap3, (ILEN) size, -(int) ep->v.p[0]->v.bit.offset,			  tp_void, 0);	    }	    mask <<= (int) ep->v.p[0]->v.bit.offset;	    ap2 = g_deref (ep->v.p[0]->v.p[0], ep->v.p[0]->etp);	    validate (ap3);	    g_code (op_and, (ILEN) size, mk_immed ((IVAL) ~mask), ap2);	    g_code (op_or, (ILEN) size, ap3, ap2);	    freeop (ap2);	    if (!(flags & F_NOVALUE)) {		freeop (ap3);		validate (ap1);	    }	    break;	    /*	     * (uns.) char, (uns.) short, (uns.) long, float	     *	     * we want to pass the right hand side as the expression value.	     * This can''t be done if the left side is a register variable on	     * which the right hand side addressing mode depends. But if the	     * left side IS a register variable, it is desirable to pass the	     * left side, so no problem.	     */	case en_register:	    /* pass the left side as expr. value */	    ap1 = g_expr (ep->v.p[0], F_ALL);	    ap2 = g_expr (ep->v.p[1], F_ALL);	    validate (ap1);	    g_code (op_mov, (ILEN) size, ap2, ap1);	    freeop (ap2);	    break;	default:	    /* pass the right side as expr. value */	    /* normally, this is more efficient */	    ap1 = g_expr (ep->v.p[1], flagx);	    ap2 = g_expr (ep->v.p[0], F_ALL);	    validate (ap1);	    if (is_register_mode (ap1->mode) || is_register_mode (ap2->mode)		|| (ap1->mode == am_immed)) {		if (size == 4L) {		    g_code (op_mov, IL2, mk_low (ap1), mk_low (ap2));		    g_code (op_mov, IL2, mk_high (ap1), mk_high (ap2));		} else {		    g_code (op_mov, (ILEN) size, mk_low (ap1), ap2);		}		freeop (ap2);	    } else {		if (flags & F_NOVALUE) {		    ap3 = data_register ();		    g_code (op_mov, IL2, mk_low (ap1), ap3);		    g_code (op_mov, IL2, ap3, mk_low (ap2));		    if (size == 4L) {			g_code (op_mov, IL2, mk_high (ap1), ap3);			g_code (op_mov, IL2, ap3, mk_high (ap2));		    }		    freeop (ap3);		    freeop (ap2);		    freeop (ap1);		    ap1 = NIL_ADDRESS;		} else {		    if (size == 4L) {			ap3 = mdata_register ();			g_code (op_mov, IL2, mk_low (ap1), mk_low (ap3));			g_code (op_mov, IL2, mk_low (ap3), mk_low (ap2));			g_code (op_mov, IL2, mk_high (ap1), mk_high (ap3));			g_code (op_mov, IL2, mk_high (ap3), mk_high (ap2));			freeop (ap3);			freeop (ap2);			freeop (ap1);			ap1 = mdata_register ();			g_code (op_mov, (ILEN) size, mk_low (ap3),				mk_low (ap1));			g_code (op_mov, (ILEN) size, mk_high (ap3),				mk_high (ap1));		    } else {			ap3 = data_register ();			g_code (op_mov, IL2, ap1, ap3);			g_code (op_mov, IL2, ap3, ap2);			freeop (ap3);			freeop (ap2);			freeop (ap1);			ap1 = data_register ();			g_code (op_mov, (ILEN) size, ap3, ap1);		    }		}	    }	    break;	}	return mk_legal (ap1, flags, tp);    }}/* * push the operand expression onto the stack. return the number of bytes * pushed */static SIZE push_param P1 (const EXPR *, ep){    ADDRESS *ap;    FLAGS   flagx;#ifdef FLOAT_IEEE    ADDRESS *ap1;#endif /* FLOAT_IEEE */    SIZE    size = ep->etp->size;    switch (ep->etp->type) {    case bt_float:    case bt_double:    case bt_longdouble:#ifdef FLOAT_IEEE	ap = g_expr (ep, F_FREG);	g_code (op_sub, IL2, mk_immed (size), &esp_reg);	ap1 = mk_indirect (ESP, NIL_EXPR);	g_fcode (op_fstp, (ILEN) size, ap1, NIL_ADDRESS);	freeop (ap);	break;#endif /* FLOAT_IEEE */    case bt_struct:    case bt_union:	/* pushing of structures and unions */	ap = g_expr (ep, F_ALL);	g_code (op_sub, IL2, mk_immed (size), &esp_reg);	structassign (&esp_reg, ap, size);	freeop (ap);	break;    default:	flagx =	    (target_option <	     target_80186) ? (FLAGS) (F_DREG | F_AREG | F_MEM) : F_ALL;	switch (size) {	case 1L:	case 2L:	    ap = g_expr (ep, flagx);	    g_code (op_push, IL2, ap, NIL_ADDRESS);	    freeop (ap);	    break;	case 4L:	    ap = g_expr (ep, flagx);	    g_code (op_push, IL2, mk_high (ap), NIL_ADDRESS);	    g_code (op_push, IL2, mk_low (ap), NIL_ADDRESS);	    freeop (ap);	    break;	default:	    FATAL (		   (__FILE__, "push_param",		    "size(%ld) != 2, ep->etp->type=%d", size, ep->etp->type));	    break;	}	break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -