📄 gen386.c
字号:
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 + -