📄 gen86.c
字号:
#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_pointer16: if (ep->v.p[0]->nodetype == en_fieldref) { return g_asbitfield (ep, flags, op, FALSE); } if (flags & F_NOVALUE) { ap2 = g_expr (ep->v.p[0], F_ALL); ap1 = NIL_ADDRESS; } 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); case bt_int32: case bt_uint32: case bt_long: case bt_ulong: case bt_pointer32: if (flags & F_NOVALUE) { ap1 = g_expr (ep->v.p[0], F_ALL); g_code (op, IL2, mk_immed (1L), mk_low (ap1)); op = ((op == op_add) ? op_adc : op_sbb); g_code (op, IL2, mk_immed (0L), mk_high (ap1)); } else { ap1 = mdata_register (); ap2 = g_expr (ep->v.p[0], (FLAGS) (F_MEM | F_DREG)); validate (ap1); g_code (op_mov, IL2, mk_low (ap2), mk_low (ap1)); g_code (op_mov, IL2, mk_high (ap2), mk_high (ap1)); g_code (op, IL2, mk_immed (1L), mk_low (ap2)); op = ((op == op_add) ? op_adc : op_sbb); g_code (op, IL2, mk_immed (0L), mk_high (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); } ap1 = g_expr (ep->v.p[0], F_MEM); validate (ap1); ilen = (ILEN) ep->etp->size; g_fcode (op_fld, ilen, ap1, NIL_ADDRESS); 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; OPCODE op2; FLAGS f = F_ALL; switch (tp->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar: f = (FLAGS) (f | F_NOEDI); /*FALLTHRU */ case bt_short: case bt_ushort: case bt_int16: case bt_uint16: case bt_pointer16: 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); case bt_int32: case bt_long: case bt_uint32: case bt_ulong: case bt_pointer32: switch (op) { case op_add: op2 = op_adc; goto common; case op_sub: op2 = op_sbb; goto common; case op_and: case op_or: case op_xor: op2 = op; common: 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, IL2, mk_low (ap2), mk_low (ap1)); g_code (op2, IL2, mk_high (ap2), mk_high (ap1)); freeop (ap2); return mk_legal (ap1, flags, tp); default: CANNOT_REACH_HERE (); break; } break;#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_pointer16: 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 */ ap1 = 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, IL2, ap3, ap1); ap1 = mk_legal (ap1, flags, ep->etp); } return ap1; case bt_int32: case bt_long: case bt_uint32: case bt_ulong: case bt_pointer32: 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); switch (op) { case op_add: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op_adc, IL2, mk_high (ap2), mk_high (ap1)); break; case op_sub: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op_sbb, IL2, mk_high (ap2), mk_high (ap1)); break; case op_or: case op_xor: case op_and: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op, IL2, mk_high (ap2), mk_high (ap1)); break; default: CANNOT_REACH_HERE (); break; } freeop (ap2); freeop (ap1); /* void result */ ap1 = NIL_ADDRESS; } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (flagx | F_DREG)); ap2 = g_expr (ep->v.p[1], (FLAGS) (flagx | F_ALL)); validate (ap1); switch (op) { case op_add: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op_adc, IL2, mk_high (ap2), mk_high (ap1)); break; case op_sub: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op_sbb, IL2, mk_high (ap2), mk_high (ap1)); break; case op_or: case op_xor: case op_and: g_code (op, IL2, mk_low (ap2), mk_low (ap1)); g_code (op, IL2, mk_high (ap2), mk_high (ap1)); break; default: CANNOT_REACH_HERE (); break; } freeop (ap2); ap1 = mk_legal (ap1, flags, ep->etp); } return ap1;#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){ EXPR *ep1; ADDRESS *ap1, *ap2; FLAGS flgs; switch (ep->etp->type) { case bt_int16: case bt_char: case bt_schar: case bt_short: if (op == op_shr) { op = op_asr; } /*FALLTHRU */ case bt_pointer16: case bt_uint16: case bt_uchar: case bt_charu: case bt_ushort: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL | F_NOECX)); ep1 = ep->v.p[1]; if (target_option == target_8086 && (ep1->nodetype == en_icon && ep1->v.i == 2)) { ap2 = mk_immed (1L); g_code (op, (ILEN) ep->etp->size, ap2, ap1); } else { if (target_option >= target_80186 || (ep1->nodetype == en_icon && ep1->v.i == 1)) { flgs = (FLAGS) (F_DREG | F_IMMED | F_ECX); } else { flgs = (FLAGS) (F_DREG | F_ECX); } ap2 = g_expr (ep->v.p[1], flgs); } 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_int16: case bt_short: case bt_char: case bt_schar: if (op == op_shr) { op = op_asr; } /*FALLTHRU */ case bt_pointer16: 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_uint16: case bt_ushort: case bt_pointer16: op = op_div; /*FALLTHRU */ case bt_short: case bt_int16: temp_inv (); 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_cwd, IL0, NIL_ADDRESS, NIL_ADDRESS); } else { g_code (op_xor, IL2, mk_high (ap1), mk_high (ap1)); } g_code (op, IL2, ap2, NIL_ADDRESS); freeop (ap2); freeop (ap1); ap1 = data_register (); if (mod) { g_code (op_mov, IL2, &edx_reg, ap1); } else { g_code (op_mov, IL2, &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_pointer16: op = op_div; /*FALLTHRU */ case bt_char: case bt_schar: case bt_int16: case bt_short: 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_cwd, IL0, NIL_ADDRESS, NIL_ADDRESS); } else { g_code (op_xor, IL2, mk_high (ap1), mk_high (ap1)); } g_code (op, (ILEN) ep->etp->size, 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_uint16: case bt_ushort: case bt_pointer16: /* * unless the result is extended to 32 bit, there should * be no difference between imul and mul. * NB. There is no mul instruction unless 32-bit extension * is desired. */ /* op = op_mul; >>>This instruction does not exist<<< */ /*FALLTHRU */ case bt_int16: case bt_short: if (target_option >= target_80186 && is_icon (ep->v.p[1])) { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL)); ap2 = g_expr (ep->v.p[1], F_IMMED); g_code (op, (ILEN) ep->etp->size, ap2, mk_low (ap1)); freeop (ap2); return mk_legal (ap1, flags, ep->etp); } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_EAXEDX | F_VOL));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -