📄 gen386.c
字号:
static ADDRESS *mk_legal P3 (ADDRESS *, ap, FLAGS, flags, TYP *, tp){ ADDRESS *ap2; ILEN ilen = (ILEN) tp->size; if (flags & F_NOVALUE) { if (ap != NIL_ADDRESS) {#ifdef FLOAT_IEEE if (ap->mode == am_freg) { g_fcode (op_fstp, IL10, mk_reg (ST0), NIL_ADDRESS); }#endif /* FLOAT_IEEE */ freeop (ap); } return NIL_ADDRESS; } if (ap == NIL_ADDRESS) { FATAL ((__FILE__, "mk_legal", "ap == 0")); } switch (ap->mode) { case am_immed: if (flags & F_IMMED) { return ap; /* mode ok */ } break; case am_dreg: if (flags & F_DREG) { if ((flags & F_VOL) && !is_temporary_register (ap->preg)) { break; } if ((flags & F_NOEDI) && (ap->preg == EDI || ap->preg == ESI)) { break; } if ((flags & F_NOECX) && (ap->preg == ECX)) { break; } if (flags & F_EAXEDX) { break; } return ap; }#ifdef FLOAT_IEEE if (flags & F_FREG) { ADDRESS *ap1; ap1 = mk_indirect (ESP, mk_const (-4L)); g_code (op_mov, IL4, ap, ap1); g_code (op_fild, IL4, ap1, NIL_ADDRESS); freeop (ap); ap = float_register (); return ap; } break; case am_freg: if (flags & F_FREG) { return ap; }#endif /* FLOAT_IEEE */ break; case am_mreg: if (flags & F_DREG) { if ((flags & F_NOEDI) && ((ap->preg == EDI || ap->preg == ESI) || (ap->sreg == EDI || ap->sreg == EDI))) break; if ((flags & F_VOL) && !is_temporary_register (ap->preg) && !is_temporary_register (ap->sreg)) break; if ((flags & F_EAXEDX) && ((ap->preg != EAX) || (ap->sreg != EDX))) { break; } return ap; } break; case am_ind: case am_indx: case am_indx2: case am_direct: if (flags & F_MEM) { return ap; } break; default: FATAL ( (__FILE__, "mk_legal", "mode == %d, flags = 0x%x", ap->mode, flags)); } if (flags & F_DREG) { freeop (ap); /* maybe we can use it */ if (flags & F_ECX) { ap2 = cx_register (); g_code (op_mov, IL2, ap, ap2); return ap2; } if (flags & F_EAXEDX) { ap2 = axdx_register (); g_code (op_mov, IL4, ap, mk_low (ap2)); } else { ap2 = data_register (); /* * byte transfers from %edi/%esi to a scratch register come up here */ if (ap->mode == am_dreg && (ap->preg == ESI || ap->preg == EDI) && ilen == IL1) { ilen = IL2; } g_code (op_mov, ilen, ap, ap2); } return ap2; }#ifdef FLOAT_IEEE if (flags & F_FREG) { freeop (ap); switch (tp->type) { case bt_float: case bt_double: case bt_longdouble: ap2 = float_register (); g_fcode (op_fld, ilen, ap, NIL_ADDRESS); return ap2; case bt_char: case bt_schar:/*KDW */ case bt_short: case bt_int16: case bt_long: case bt_int32: ap2 = float_register (); g_code (op_fild, ilen, ap, NIL_ADDRESS); return ap2; default: break; } }#endif /* FLOAT_IEEE */ if (flags & F_MEM) { freeop (ap); ap2 = mk_scratch (tp->size); switch (tp->size) { case 1L: case 2L: case 4L: switch (ap->mode) {#ifdef FLOAT_IEEE case am_freg: g_fcode (op_fstp, ilen, ap2, NIL_ADDRESS); break;#endif /* FLOAT_IEEE */ default: g_code (op_mov, ilen, ap, ap2); break; } break; case 8L: switch (ap->mode) {#ifdef FLOAT_IEEE case am_freg: g_fcode (op_fstp, ilen, ap2, NIL_ADDRESS); break;#endif /* FLOAT_IEEE */ case am_mreg: g_code (op_mov, IL4, mk_high (ap), mk_high (ap2)); g_code (op_mov, IL4, mk_low (ap), mk_low (ap2)); break; default: g_code (op_mov, ilen, ap, ap2); break; } break; default: CANNOT_REACH_HERE (); break; } return ap2; } FATAL ( (__FILE__, "mk_legal", "mode = %d, flags = 0x%x", ap->mode, flags)); return NIL_ADDRESS;}/* * generate code to evaluate an index node and return the addressing * mode of the result. */static ADDRESS *g_index P1 (const EXPR *, ep){ ADDRESS *ap1, *ap2; ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_IMMED | F_VOL)); switch (ap1->mode) { case am_dreg: ap2 = g_expr (ep->v.p[1], F_ALL); validate (ap1); break; case am_immed: ap2 = ap1; ap1 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_VOL)); break; default: CANNOT_REACH_HERE (); } switch (ap1->mode) { case am_dreg: if (!is_temporary_register (ap1->preg)) { ap1 = copy_addr (ap1, ap1->mode); switch (ap2->mode) { case am_dreg: /* 0(Rn,Rm) */ ap1->mode = am_indx2; ap1->sreg = ap2->preg; ap1->deep = ap2->deep; ap1->u.offset = mk_const (0L); return ap1; default: break; } } break; case am_immed: switch (ap2->mode) { case am_immed: ap1 = copy_addr (ap1, am_direct); ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset); return ap1; case am_dreg: g_code (op_add, IL4, ap1, ap2); ap2 = copy_addr (ap2, am_ind); return ap2; default: CANNOT_REACH_HERE (); } break; default: CANNOT_REACH_HERE (); } freeop (ap2); if (!is_temporary_register (ap1->preg)) { ap1 = mk_legal (ap1, (FLAGS) (F_DREG | F_VOL), tp_pointer); } g_code (op_add, IL4, ap2, ap1); ap1 = copy_addr (ap1, am_ind); return ap1;}/* * rotate a bitfield into the required position (assumes ap is a register) */static void g_rotate P5 (ADDRESS *, ap, ILEN, ilen, int, offset, TYP *, tp, int, width){ OPCODE op; switch (tp->type) { case bt_int16: case bt_int32: /* sign bitfield */ g_code (op_asl, ilen, mk_immed (32L - (IVAL) offset - (IVAL) width), ap); g_code (op_asr, ilen, mk_immed (32L - (IVAL) width), ap); break; default: /* offset is in range -31 .. 31 */ if (offset < 0) { offset += ilen * 8; } /* offset in range 0..31 */ if (offset != 0) { if (offset > 15) { op = op_rol; offset = 32 - offset; } else { op = op_ror; } g_code (op, ilen, mk_immed ((IVAL) offset), ap); } if (!is_void (tp)) { g_code (op_and, ilen, mk_immed ((IVAL) bitmask ((BITSIZE) width)), ap); } }}static ADDRESS *g_extend P3 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2){ OPCODE op; ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), tp1); switch (tp2->type) { case bt_int16: case bt_uint16: case bt_short: case bt_ushort: switch (tp1->type) { case bt_char: case bt_schar: op = op_movsbw; g_code (op, IL0, ap, ap); break; case bt_uchar: case bt_charu: op = op_movzbw; g_code (op, IL0, ap, ap); break; default: CANNOT_REACH_HERE (); break; } break; case bt_int32: case bt_uint32: case bt_long: case bt_ulong: case bt_pointer32: switch (tp1->type) { case bt_char: case bt_schar: op = op_movsbl; g_code (op, IL0, ap, ap); break; case bt_int16: case bt_short: op = op_movswl; g_code (op, IL0, ap, ap); break; case bt_uchar: case bt_charu: op = op_movzbl; g_code (op, IL0, ap, ap); break; case bt_uint16: case bt_ushort: op = op_movzwl; g_code (op, IL0, ap, ap); break; case bt_int32: case bt_uint32: case bt_long: case bt_ulong: case bt_pointer32: break; default: CANNOT_REACH_HERE (); break; } default: break; } return ap;}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P2 (const EXPR *, ep, TYP *, tp){ ADDRESS *ap1; if (is_structure_type (tp) || is_array_assignment (tp)) { return g_expr (ep, F_ALL); } switch (ep->nodetype) { case en_add: return g_index (ep); case en_autocon: ap1 = mk_indirect (regframe, mk_const (ep->v.i)); return ap1; default: ap1 = g_expr (ep, (FLAGS) (F_DREG | F_IMMED)); if (ap1->mode == am_immed) { return copy_addr (ap1, am_direct); } else { return copy_addr (ap1, am_ind); } }}/* * get a bitfield value */static ADDRESS *g_fderef P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap; ap = g_deref (ep->v.p[0], ep->etp); ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), ep->etp); g_rotate (ap, (ILEN) ep->etp->size, (int) ep->v.bit.offset, ep->etp, (int) ep->v.bit.width); return mk_legal (ap, flags, ep->etp);}/*============================================================================*/#ifdef FLOAT_IEEEstatic void push_rtl_params P2 (const EXPR *, ep1, const EXPR *, ep2){ ADDRESS *ap, *ap2; is_parameter++; temp_inv (); ap = g_expr (ep1, F_MEM); ap2 = data_register (); g_code (op_lea, IL4, ap, ap2); g_code (op_push, IL4, ap2, NIL_ADDRESS); freeop (ap2); freeop (ap); if (ep2) { ap = g_expr (ep2, F_MEM); ap2 = data_register (); g_code (op_lea, IL0, ap, ap2); g_code (op_push, IL4, ap2, NIL_ADDRESS); freeop (ap2); freeop (ap); }}#endif /* FLOAT_IEEE *//*============================================================================*//* * generate code to evaluate a unary minus or complement. */static ADDRESS *g_unary P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap; switch (ep->etp->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar: 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: ap = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL)); g_code (op, (ILEN) ep->etp->size, ap, NIL_ADDRESS); return mk_legal (ap, flags, ep->etp);#ifdef FLOAT_IEEE case bt_float: case bt_double: case bt_longdouble: ap = g_expr (ep->v.p[0], F_FREG); g_code (op_fchs, IL0, NIL_ADDRESS, NIL_ADDRESS); return mk_legal (ap, flags, ep->etp);#endif /* FLOAT_IEEE */ default: FATAL ((__FILE__, "g_unary", "illegal type or operation")); break; } return NIL_ADDRESS;}/* * generate code to evaluate a autoincrement/autodecrement node */static ADDRESS *g_aincdec P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2;#ifdef FLOAT_IEEE ILEN ilen;#endif /* FLOAT_IEEE */ switch (ep->etp->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar: 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 = NIL_ADDRESS; ap2 = g_expr (ep->v.p[0], F_ALL); } else { ap1 = data_register (); ap2 = g_expr (ep->v.p[0], (FLAGS) (F_MEM | F_DREG)); validate (ap1); g_code (op_mov, (ILEN) ep->etp->size, ap2, ap1); } g_code (op, (ILEN) ep->etp->size, mk_immed (ep->v.p[1]->v.i), ap2); freeop (ap2); return mk_legal (ap1, flags, ep->etp);#ifdef FLOAT_IEEE case bt_float: case bt_double: case bt_longdouble: if (flags & F_NOVALUE) { return g_asbin (ep, flags, op); } ilen = (ILEN) ep->etp->size; ap1 = g_expr (ep->v.p[0], F_MEM); g_fcode (op_fld, ilen, ap1, NIL_ADDRESS); /* save result */ ap2 = g_expr (ep->v.p[1], F_FREG); validate (ap1); switch (op) { case op_add: g_fcode (op_fadd, ilen, ap1, NIL_ADDRESS); break; case op_sub: g_fcode (op_fsubr, ilen, ap1, NIL_ADDRESS); break; default: FATAL ((__FILE__, "g_aincdec", "illegal op %d", op)); } freeop (ap2); freeop (ap1); g_fcode (op_fstp, ilen, ap1, NIL_ADDRESS); ap1 = float_register (); return mk_legal (ap1, flags, ep->etp);#endif /* FLOAT_IEEE */ default: FATAL ((__FILE__, "g_aincdec", "illegal type %d", ep->etp->type)); break; } return NIL_ADDRESS;}/*============================================================================*//* * generate code to evaluate a binary node and return the addressing mode of * the result. */static ADDRESS *g_bin P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2; TYP *tp = ep->etp; FLAGS f = F_ALL; switch (tp->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -