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

📄 gen386.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	case bt_uint16:	    ap = g_cast (ap, tp1, tp_long, F_ALL);	    return g_cast (ap, tp_long, tp2, flags);	case bt_int32:	case bt_long:	    /*	     * For the conversion signed long --> float/double, there is	     * a 387 instruction	     */	    if (fpu_option) {		switch (ap->mode) {		case am_direct:		case am_ind:		case am_indx:		case am_indx2:		    /*		     * FPU-code for a signed long that is in memory		     */		    g_code (op_fild, IL4, ap, NIL_ADDRESS);		    break;		default:		    /*		     * FPU-code for a signed long that is in a register:		     * the value is written to the stack and loaded from there		     * since there is no direct path between CPU and FPU registers.		     */		    ap1 = mk_scratch (4L);		    g_code (op_mov, IL4, ap, ap1);		    g_code (op_fild, IL4, ap1, NIL_ADDRESS);		}		freeop (ap);		ap = float_register ();		return mk_legal (ap, flags, tp2);	    }	    /*FALLTHRU */	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    ap1 = data_register ();	    g_code (op_xor, IL4, ap1, ap1);	    g_code (op_push, IL4, ap1, NIL_ADDRESS);	    g_code (op_push, IL4, ap, NIL_ADDRESS);	    g_code (op_fildl, IL4, mk_indirect (ESP, NIL_EXPR), NIL_ADDRESS);	    g_code (op_add, IL4, mk_immed (8L), mk_reg (ESP));	    freeop (ap1);	    freeop (ap);	    ap = float_register ();	    return mk_legal (ap, flags, tp2);	default:	    break;	}	break;#endif /* FLOAT_IEEE */    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:	flags = (FLAGS) (flags | F_NOEDI);	switch (tp1->type) {#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    g_code (op_sub, IL4, mk_immed (4L), mk_reg (ESP));	    g_fcode (op_fistp, IL8, mk_indirect (ESP, NIL_EXPR), NIL_ADDRESS);	    freeop (ap);	    ap = data_register ();	    g_code (op_pop, IL4, ap, NIL_ADDRESS);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	case bt_uchar:	case bt_schar:	case bt_char:	case bt_charu:	case bt_ushort:	case bt_short:	case bt_int16:	case bt_uint16:	case bt_int32:	case bt_uint32:	case bt_ulong:	case bt_long:	case bt_pointer32:	    return mk_legal (ap, flags, tp2);	default:	    break;	}	break;    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:	switch (tp1->type) {#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    g_code (op_sub, IL4, mk_immed (4L), mk_reg (ESP));	    g_fcode (op_fistp, IL8, mk_indirect (ESP, NIL_EXPR), NIL_ADDRESS);	    freeop (ap);	    ap = data_register ();	    g_code (op_pop, IL4, ap, NIL_ADDRESS);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_short:	case bt_ushort:	case bt_int16:	case bt_uint16:	case bt_int32:	case bt_uint32:	case bt_long:	case bt_pointer32:	case bt_ulong:	    return mk_legal (ap, flags, tp2);	default:	    break;	}	break;    case bt_int32:    case bt_long:	switch (tp1->type) {#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    g_code (op_sub, IL4, mk_immed (4L), mk_reg (ESP));	    g_fcode (op_fistp, IL8, mk_indirect (ESP, NIL_EXPR), NIL_ADDRESS);	    freeop (ap);	    ap = data_register ();	    g_code (op_pop, IL4, ap, NIL_ADDRESS);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	case bt_short:	case bt_int16:	case bt_ushort:	case bt_uint16:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_uint32:	case bt_ulong:	case bt_long:	case bt_pointer32:	case bt_func:	    return mk_legal (ap, flags, tp1);	default:	    break;	}	break;    case bt_uint32:    case bt_ulong:    case bt_pointer32:	switch (tp1->type) {#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    g_code (op_sub, IL4, mk_immed (8L), mk_reg (ESP));	    g_fcode (op_fistpl, IL8, mk_indirect (ESP, NIL_EXPR),		     NIL_ADDRESS);	    freeop (ap);	    ap = data_register ();	    ap1 = data_register ();	    g_code (op_pop, IL4, ap, NIL_ADDRESS);	    g_code (op_pop, IL4, ap1, NIL_ADDRESS);	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	case bt_short:	case bt_int16:	case bt_ushort:	case bt_uint16:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_uint32:	case bt_ulong:	case bt_long:	case bt_pointer32:	case bt_func:	    return mk_legal (ap, flags, tp1);	default:	    break;	}	break;    default:	break;    }    FATAL ((__FILE__, "g_cast", ""));    return NIL_ADDRESS;}#ifdef ASMstatic ADDRESS *g_asm P1 (const EXPR *, ep){    ADDRESS *ap = mk_expr (am_str, copynode (ep));    g_code (op_asm, IL0, ap, NIL_ADDRESS);    return NIL_ADDRESS;}#endif /* ASM *//* * generate code to do a comparison of the two operands of node. * returns the op code for the branch to perform after the compare. */static OPCODE g_compare P3 (const EXPR *, ep, OPCODE, op1, OPCODE, op2){    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    ADDRESS *ap1, *ap2;    FLAGS   flagx;    TYP    *tp = ep0->etp;    switch (tp->type) {    case bt_schar:    case bt_char:    case bt_short:    case bt_int16:    case bt_int32:    case bt_long:	op1 = op2;	/*FALLTHRU */    case bt_uchar:    case bt_charu:    case bt_ushort:    case bt_uint16:    case bt_uint32:    case bt_pointer32:    case bt_ulong:	ap1 = g_expr (ep0, F_ALL);	flagx = (ap1->mode == am_immed) ? (FLAGS) (F_MEM | F_DREG) : F_DREG;	ap2 = g_expr (ep1, flagx);	validate (ap1);	sync_stack ();	g_code (op_cmp, (ILEN) tp->size, ap1, ap2);	freeop (ap2);	freeop (ap1);	break;#ifdef FLOAT_IEEE    case bt_longdouble:    case bt_double:    case bt_float:	if (fpu_option) {	    ap1 = g_expr (ep0, F_MEM);	    ap2 = g_expr (ep1, F_FREG);	    validate (ap1);	    g_fcode (op_fcomp, (ILEN) tp->size, ap1, NIL_ADDRESS);	    if (is_register_used (EAX)) {		g_code (op_push, IL4, &eax_reg, NIL_ADDRESS);		g_code (op_fnstsw, IL0, &ax_reg, NIL_ADDRESS);		g_code (op_sahf, IL0, NIL_ADDRESS, NIL_ADDRESS);		g_code (op_pop, IL4, &eax_reg, NIL_ADDRESS);	    } else {		g_code (op_fnstsw, IL0, &ax_reg, NIL_ADDRESS);		g_code (op_sahf, IL0, NIL_ADDRESS, NIL_ADDRESS);	    }	    freeop (ap2);	    freeop (ap1);	} else {	    push_rtl_params (ep0, ep1);	    switch (tp->type) {	    case bt_float:		call_library (SUP_FPCMP);		break;	    case bt_double:		call_library (SUP_FPCMP);		break;	    case bt_longdouble:		call_library (SUP_FPCMP);		break;	    default:		CANNOT_REACH_HERE ();	    }	}	break;#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_compare", "illegal type %d", tp->type));	break;    }    return op1;}static OPCODE g_test P2 (const EXPR *, ep, OPCODE, op1){    ADDRESS *ap;    switch (ep->etp->type) {    case bt_uchar:    case bt_char:    case bt_schar:    case bt_charu:    case bt_ushort:    case bt_short:    case bt_int16:    case bt_uint16:    case bt_int32:    case bt_uint32:    case bt_ulong:    case bt_long:    case bt_pointer32:	ap = g_expr (ep, F_DREG);	sync_stack ();	g_code (op_test, (ILEN) ep->etp->size, ap, ap);	freeop (ap);	break;#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	ap = g_expr (ep, F_FREG);	g_fcode (op_ftst, IL0, NIL_ADDRESS, NIL_ADDRESS);	g_fcode (op_fstp, IL10, mk_reg (ST0), NIL_ADDRESS);	if (is_register_used (EAX)) {	    g_code (op_push, IL4, &eax_reg, NIL_ADDRESS);	    g_code (op_fnstsw, IL0, &ax_reg, NIL_ADDRESS);	    g_code (op_sahf, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_pop, IL4, &eax_reg, NIL_ADDRESS);	} else {	    g_code (op_fnstsw, IL0, &ax_reg, NIL_ADDRESS);	    g_code (op_sahf, IL0, NIL_ADDRESS, NIL_ADDRESS);	}	freeop (ap);	break;#endif /* FLOAT_IEEE */    default:	CANNOT_REACH_HERE ();	break;    }    return op1;}/* * general expression evaluation. returns the addressing mode of the result. */static ADDRESS *g_expr P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2;    LABEL   lab0, lab1;    OPCODE  op;    if (ep == NIL_EXPR) {	FATAL ((__FILE__, "g_expr", "ep == 0"));    }    if (tst_const (ep)) {	ap1 = mk_expr (am_immed, copynode (ep));	return mk_legal (ap1, flags, ep->etp);    }    switch (ep->nodetype) {    case en_autocon:	ap1 = data_register ();	ap2 = mk_indirect (regframe, copynode (ep));	g_code (op_lea, IL4, ap2, ap1);	return mk_legal (ap1, flags, ep->etp);    case en_register:	ap1 = mk_reg (ep->v.r);	return mk_legal (ap1, flags, ep->etp);    case en_ref:	ap1 = g_deref (ep->v.p[0], ep->etp);	if (is_structure_type (ep->etp) || is_array_type (ep->etp)) {	    return mk_legal (ap1, flags, tp_pointer);	} else {	    return mk_legal (ap1, flags, ep->etp);	}    case en_fieldref:	return g_fderef (ep, flags);    case en_uminus:	return g_unary (ep, flags, op_neg);    case en_compl:	return g_unary (ep, flags, op_not);    case en_add:	return g_bin (ep, flags, op_add);    case en_sub:	return g_bin (ep, flags, op_sub);    case en_and:	return g_bin (ep, flags, op_and);    case en_or:	return g_bin (ep, flags, op_or);    case en_xor:	return g_bin (ep, flags, op_xor);    case en_assign:	return g_assign (ep, flags);    case en_asadd:	return g_asbin (ep, flags, op_add);    case en_assub:	return g_asbin (ep, flags, op_sub);    case en_asand:	return g_asbin (ep, flags, op_and);    case en_asor:	return g_asbin (ep, flags, op_or);    case en_asxor:	return g_asbin (ep, flags, op_xor);    case en_asmul:	return g_asmul (ep, flags);    case en_asdiv:	return g_asdiv (ep, flags, FALSE);    case en_asmod:	return g_asdiv (ep, flags, TRUE);    case en_aslsh:	return g_asshift (ep, flags, op_shl);    case en_asrsh:	return g_asshift (ep, flags, op_shr);    case en_ainc:	return g_aincdec (ep, flags, op_add);    case en_adec:	return g_aincdec (ep, flags, op_sub);    case en_mul:	return g_mul (ep, flags);    case en_div:	return g_div (ep, flags, FALSE);    case en_mod:	return g_div (ep, flags, TRUE);    case en_lsh:	return g_shift (ep, flags, op_shl);    case en_rsh:	return g_shift (ep, flags, op_shr);    case en_cond:	return g_hook (ep, flags);    case en_eq:	op = g_compare (ep, op_sete, op_sete);	goto cont1;    case en_ne:	op = g_compare (ep, op_setne, op_setne);	goto cont1;    case en_lt:	op = g_compare (ep, op_seta, op_setg);	goto cont1;    case en_le:	op = g_compare (ep, op_setae, op_setge);	goto cont1;    case en_gt:	op = g_compare (ep, op_setb, op_setl);	goto cont1;    case en_ge:	op = g_compare (ep, op_setbe, op_setle);	goto cont1;    case en_test:	op = g_test (ep->v.p[0], op_setne);	goto cont1;    case en_not:	op = g_test (ep->v.p[0], op_sete);      cont1:	ap1 = data_register ();	g_code (op, IL1, ap1, NIL_ADDRESS);	g_code (op_and, IL4, mk_immed (1L), ap1);	return mk_legal (ap1, flags, ep->etp);    case en_land:    case en_lor:	lab0 = nextlabel++;	lab1 = nextlabel++;	g_falsejp (ep, lab0);	ap1 = data_register ();	g_code (op_mov, IL4, mk_immed (1l), ap1);	g_branch (lab1);	g_label (lab0);	g_code (op_mov, IL4, mk_immed (0l), ap1);	g_label (lab1);	return mk_legal (ap1, flags, ep->etp);    case en_comma:	freeop (g_expr (ep->v.p[0], (FLAGS) (F_ALL | F_NOVALUE)));	return g_expr (ep->v.p[1], flags);    case en_fcall:    case en_call:
    case en_usercall:	return g_fcall (ep, flags);    case en_cast:	return g_cast (g_expr (ep->v.p[0], F_ALL),		       ep->v.p[0]->etp, ep->etp, flags);    case en_deref:	/*	 * The cases where this node occurs are handled automatically:	 * g_assign and g_fcall return a pointer to a structure rather than a	 * structure.	 */	return g_expr (ep->v.p[0], flags);#ifdef ASM    case en_str:	return g_asm (ep);#endif /* ASM */#ifdef FLOAT_SUPPORT#ifndef FLOAT_BOOTSTRAP    case en_fcon:	if ((FLAGS) (flags & (F_MEM | F_FREG)) == F_NONE) {	    FATAL ((__FILE__, "g_expr", "EN_FCON"));	}	ap1 = mk_label (mk_flabel (&ep->v.f, ep->etp));	return mk_legal (ap1, flags, ep->etp);#endif /* FLOAT_BOOTSTRAP */#endif /* FLOAT_SUPPORT */    default:	FATAL ((__FILE__, "g_expr", "uncoded nodetype %d", ep->nodetype));	return NIL_ADDRESS;    }}PRIVATE void g_expression P1 (const EXPR *, ep){    initstack ();    if (ep != NIL_EXPR) {	VOIDCAST g_expr (ep, (FLAGS) (F_ALL | F_NOVALUE));    }    checkstack ();}/* * generate a jump to label if the node passed evaluates to a true condition. */static void g_truejp P2 (const EXPR *, ep, LABEL, label){    LABEL   lab0;    OPCODE  op;    if (ep == NIL_EXPR) {	FATAL ((__FILE__, "g_truejp", "ep == 0"));    }    switch (ep->nodetype) {    case en_icon:	if (ep->v.i) {	    g_branch (label);	}	break;    case en_eq:	op = g_compare (ep, op_je, op_je);	g_cbranch (op, label);	break;    case en_ne:	op = g_compare (ep, op_

⌨️ 快捷键说明

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