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

📄 gen386.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	f = (FLAGS) (f | F_NOEDI);	/*FALLTHRU */    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL));	ap2 = g_expr (ep->v.p[1], f);	validate (ap1);	g_code (op, (ILEN) tp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, tp);#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	ap1 = g_expr (ep->v.p[0], F_MEM);	ap2 = g_expr (ep->v.p[1], F_FREG);	validate (ap1);	switch (op) {	case op_add:	    op = op_fadd;	    break;	case op_sub:	    op = op_fsubr;	    break;	case op_imul:	    op = op_fmul;	    break;	case op_idiv:	    op = op_fdivr;	    break;	default:	    FATAL ((__FILE__, "g_bin", "illegal op %d", op));	}	g_fcode (op, (ILEN) tp->size, ap1, NIL_ADDRESS);	freeop (ap2);	freeop (ap1);	ap1 = float_register ();	return mk_legal (ap1, flags, ep->etp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_bin", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/* * generate code to evaluate a binary as-node * the result. */static ADDRESS *g_asbin P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2, *ap3;    FLAGS   flagx = F_NONE;#ifdef FLOAT_IEEE    ILEN    ilen;#endif /* FLOAT_IEEE */    switch (ep->etp->type) {    case bt_char:    case bt_charu:    case bt_uchar:    case bt_schar:	flagx = (FLAGS) (flagx | F_NOEDI);	/*FALLTHRU */    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, FALSE);	}	if (flags & F_NOVALUE) {	    ap1 = g_expr (ep->v.p[0], (FLAGS) (flagx | F_ALL));	    ap2 = g_expr (ep->v.p[1], (FLAGS) (flagx | F_DREG | F_IMMED));	    validate (ap1);	    g_code (op, (ILEN) ep->etp->size, ap2, ap1);	    freeop (ap2);	    freeop (ap1);	    /* void result */	    return NIL_ADDRESS;	} else {	    ap1 = g_expr (ep->v.p[0], (FLAGS) (flagx | F_MEM | F_DREG));	    ap2 = g_expr (ep->v.p[1], (FLAGS) (flagx | F_ALL));	    validate (ap1);	    ap3 = data_register ();	    g_code (op_mov, (ILEN) ep->etp->size, ap1, ap3);	    g_code (op, (ILEN) ep->etp->size, ap2, ap3);	    g_code (op_mov, (ILEN) ep->etp->size, ap3, ap1);	    freeop (ap3);	    freeop (ap2);	    freeop (ap1);	    /* need result */	    ap1 = data_register ();	    g_code (op_mov, IL4, ap3, ap1);	    return mk_legal (ap1, flags, ep->etp);	}#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	ap1 = g_expr (ep->v.p[0], F_MEM);	ap2 = g_expr (ep->v.p[1], F_FREG);	validate (ap1);	ilen = (ILEN) ep->etp->size;	switch (op) {	case op_add:	    op = op_fadd;	    break;	case op_sub:	    op = op_fsubr;	    break;	case op_imul:	    op = op_fmul;	    break;	case op_idiv:	    op = op_fdivr;	    break;	default:	    FATAL ((__FILE__, "g_asbin", "illegal op %d", op));	}	g_fcode (op, ilen, ap1, NIL_ADDRESS);	freeop (ap2);	freeop (ap1);	if (flags & F_NOVALUE) {	    g_fcode (op_fstp, ilen, ap1, NIL_ADDRESS);	    ap1 = NIL_ADDRESS;	} else {	    g_fcode (op_fst, ilen, ap1, NIL_ADDRESS);	    ap1 = float_register ();	}	return mk_legal (ap1, flags, ep->etp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_asbin", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/*============================================================================*//* * generate code to evaluate a shift node */static ADDRESS *g_shift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_long:    case bt_int32:    case bt_int16:    case bt_char:    case bt_schar:    case bt_short:	if (op == op_shr) {	    op = op_asr;	}	/*FALLTHRU */    case bt_pointer32:    case bt_ulong:    case bt_uint32:    case bt_uint16:    case bt_charu:    case bt_uchar:    case bt_ushort:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL | F_NOECX));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_ECX));	validate (ap1);	g_code (op, (ILEN) ep->etp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);    default:	FATAL ((__FILE__, "g_shift", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/* * generate code to evaluate an assign shift node */static ADDRESS *g_asshift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_long:    case bt_int32:    case bt_int16:    case bt_short:    case bt_char:    case bt_schar:	if (op == op_shr) {	    op = op_asr;	}	/*FALLTHRU */    case bt_pointer32:    case bt_ulong:    case bt_uint32:    case bt_uint16:    case bt_uchar:    case bt_charu:    case bt_ushort:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, FALSE);	}	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_MEM | F_DREG | F_NOECX));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_ECX));	validate (ap1);	g_code (op, (ILEN) ep->etp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);    default:	FATAL ((__FILE__, "g_asshift", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/*============================================================================*//* * generate code to evaluate a divide node (mod==0) or mod node (mod==1) */static ADDRESS *g_div P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){    ADDRESS *ap1, *ap2;    OPCODE  op = op_idiv;    switch (ep->etp->type) {    case bt_uint32:    case bt_ulong:    case bt_pointer32:	op = op_div;	/*FALLTHRU */    case bt_long:    case bt_int32:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_EAXEDX));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_MEM));	validate (ap1);	if (op == op_idiv) {	    g_code (op_cdq, IL0, NIL_ADDRESS, NIL_ADDRESS);	} else {	    g_code (op_xor, IL4, &edx_reg, &edx_reg);	}	g_code (op, IL4, ap2, NIL_ADDRESS);	freeop (ap2);	freeop (ap1);	ap1 = data_register ();	if (mod) {	    g_code (op_mov, IL4, &edx_reg, ap1);	} else {	    g_code (op_mov, IL4, &eax_reg, ap1);	}	return mk_legal (ap1, flags, ep->etp);    default:	return g_bin (ep, flags, op_idiv);    }}/* * generate code for /= node */static ADDRESS *g_asdiv P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){    ADDRESS *ap1, *ap2;    OPCODE  op = op_idiv;    switch (ep->etp->type) {    case bt_charu:    case bt_uchar:    case bt_ushort:    case bt_uint16:    case bt_uint32:    case bt_ulong:    case bt_pointer32:	op = op_div;	/*FALLTHRU */    case bt_char:    case bt_schar:    case bt_short:    case bt_int16:    case bt_int32:    case bt_long:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, mod);	}	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_MEM | F_DREG | F_EAXEDX));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_MEM));	validate (ap1);	if (op == op_idiv) {	    g_code (op_cdq, IL0, NIL_ADDRESS, NIL_ADDRESS);	} else {	    g_code (op_xor, IL4, mk_high (ap1), mk_high (ap1));	}	g_code (op, IL4, ap2, NIL_ADDRESS);	freeop (ap2);	freeop (ap1);	ap2 = data_register ();	if (mod) {	    g_code (op_mov, (ILEN) ep->etp->size, mk_high (ap1), ap2);	} else {	    g_code (op_mov, (ILEN) ep->etp->size, mk_low (ap1), ap2);	}	return mk_legal (ap2, flags, ep->etp);    default:	return g_asbin (ep, flags, op_idiv);    }}/*============================================================================*//* * generate code to evaluate a multiply node */static ADDRESS *g_mul P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2;    OPCODE  op = op_imul;    switch (ep->etp->type) {    case bt_uint32:    case bt_ulong:    case bt_pointer32:	/*	 * unless the result is extended to 64 bit, there should	 * be no difference between imul and mul.	 * NB. There is no mul instruction unless 64-bit extension	 * is desired.	 */	/* op = op_mul; >>>This instruction does not exist<<< */	/*FALLTHRU */    case bt_int32:    case bt_long:	ap1 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_VOL));	ap2 = g_expr (ep->v.p[0], F_ALL);	validate (ap1);		/* in case push occurred */	g_code (op, (ILEN) ep->etp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, 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    ilen = 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:	op = op_movzwl;	goto common;    case bt_short:    case bt_int16:	op = op_movswl;	goto common;    case bt_uint32:    case bt_int32:    case bt_ulong:    case bt_long:    case bt_pointer32:	op = op_mov;	ilen = IL4;      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 (ilen == IL0) {	    g_code (op, ilen, ap1, ap1);	}	ap2 = g_expr (ep->v.p[0], f);	ap3 = data_register ();	validate (ap1);	g_code (op, ilen, ap2, ap3);	g_code (op_imul, IL4, 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;    BOOL    result_is_void = FALSE;    switch (ep->etp->type) {#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	flagx = F_MEM;	break;#endif /* FLOAT_IEEE */    case bt_void:	result_is_void = TRUE;	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 scratch 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 = data_register ();	g_code (op_lea, IL4, ap1, ap);	ap1 = copy_addr (ap, am_ind);    }#endif /* FLOAT_IEEE */    freeop (ap1);    /* all scratch 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 = data_register ();	g_code (op_lea, IL4, ap2, ap);	ap2 = copy_addr (ap, am_ind);    }#endif /* FLOAT_IEEE */    if (!result_is_void && !is_equal_address (ap1, ap2)) {	FATAL ((__FILE__, "g_hook", "INCONSISTENCY"));    }    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], F_DREG);    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));	validate (ap1);	if (uses_temp (ap3) || ap3->mode == am_immed) {/*KDW */	    g_code (op_mov, IL4, ap3, &ecx_reg);	    freeop (ap3);	    ap3 = &ecx_reg;	}	g_code (op_mov, IL4, ap1, &eax_reg);	switch (ep->etp->type) {	case bt_long:	case bt_int32:	    g_code (op_cdq, IL0, NIL_ADDRESS, NIL_ADDRESS);	    break;

⌨️ 快捷键说明

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