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