📄 gen68k.c
字号:
} g_move ((ILEN) tp->size, ap1, ap2); freeop (ap3); freeop (ap2); return mk_legal (ap1, flags, tp); } /*lint -fallthrough */#endif /* COLDFIRE */ 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); } flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES);#ifdef COLDFIRE flagx2 = F_DREG; if (!is_coldfire ()) { flagx2 |= F_IMMED; }#else flagx2 = F_DREG | F_IMMED;#endif /* COLDFIRE */ ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], flagx2); ap2 = mk_quick2 (ap2, tp); validate (ap1); switch (op) { case op_add: g_add ((ILEN) tp->size, ap2, ap1); break; default: g_sub ((ILEN) tp->size, ap2, ap1); break; } freeop (ap2); return mk_legal (ap1, flags, tp);#ifdef LONGLONG_SUPPORT case bt_longlong: case bt_ulonglong: flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_DREG | F_MEM | F_USES);#ifdef COLDFIRE flagx2 = F_DREG; if (!is_coldfire ()) { flagx2 |= F_IMMED; }#else flagx2 = F_DREG | F_IMMED;#endif /* COLDFIRE */ ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], flagx2); validate (ap1); switch (ap1->mode) { ADDRESS *ap3; case am_ind: case am_indx: case am_indx2: case am_indx3: case am_indx4: case am_direct: switch (ap2->mode) { ADDRESS *ap4; case am_mreg: ap4 = data_register (); g_code (op_move, IL4, mk_low (ap1), ap4); g_code (op, IL4, mk_high (ap2), mk_high (ap1)); switch (op) { case op_add: g_code (op_addx, IL4, mk_low (ap2), ap4); break; default: g_code (op_subx, IL4, mk_low (ap2), ap4); break; } g_code (op_move, IL4, ap4, mk_low (ap1)); freeop (ap4); break; default: ap3 = data_register (); validate (ap2); g_code (op_move, IL4, mk_low (ap2), ap3); validate (ap1); ap4 = data_register (); g_code (op_move, IL4, mk_low (ap1), ap4); switch (op) { case op_add: g_code (op_add, IL4, mk_high (ap2), mk_high (ap1)); g_code (op_addx, IL4, ap3, ap4); break; default: g_code (op_sub, IL4, mk_high (ap2), mk_high (ap1)); g_code (op_subx, IL4, ap3, ap4); break; } g_code (op_move, IL4, ap4, mk_low (ap1)); freeop (ap4); freeop (ap3); break; } break; case am_mreg: ap3 = data_register (); g_code (op_move, IL4, mk_low (ap2), ap3); validate (ap1); switch (op) { case op_add: g_code (op_add, IL4, mk_high (ap2), mk_high (ap1)); g_code (op_addx, IL4, ap3, mk_low (ap1)); break; default: g_code (op_sub, IL4, mk_high (ap2), mk_high (ap1)); g_code (op_subx, IL4, ap3, mk_low (ap1)); break; } freeop (ap3); break; default: CANNOT_REACH_HERE (); } freeop (ap2); validate (ap1); return mk_legal (ap1, flags, tp);#endif /* LONGLONG_SUPPORT */#ifdef FLOAT_IEEE case bt_float: case bt_double: case bt_longdouble: op = (op == op_add) ? op_fadd : op_fsub; flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], F_FREG); validate (ap1); g_fcode (op, (ILEN) tp->size, ap2, ap1); freeop (ap2); return mk_legal (ap1, flags, tp);#endif /* FLOAT_IEEE */ default: FATAL ((__FILE__, "asadd", "illegal type %d", tp->type)); }
return NIL_ADDRESS; /*lint !e527*/ /* unreachable */}/*============================================================================*//* * generate code to evaluate a restricted binary node and return the * addressing mode of the result. */static ADDRESS *g_logic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2, *ap3; ILEN ilen = (ILEN) ep->etp->size; FLAGS flagx;#ifdef COLDFIRE if (is_coldfire ()) { ilen = IL4; }#endif /* COLDFIRE */ switch (ep->etp->size) { case IL8: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | D_REG | F_COLD)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_MEM | F_IMMED | F_COLD)); ap3 = data_register (); validate (ap1); /* in case push occurred */ g_code (op_move, IL4, mk_high (ap2), ap3); g_code (op, IL4, ap3, mk_high (ap1)); g_code (op_move, IL4, mk_low (ap2), ap3); g_code (op, IL4, ap3, mk_low (ap1)); freeop (ap3); freeop (ap2); return mk_legal (ap1, flags, ep->etp); default: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_DREG | F_COLD)); if (op == op_eor) { flagx = (FLAGS) (F_DREG | F_IMMED | F_COLD); } else { flagx = (FLAGS) ((F_ALL | F_COLD) & ~F_AREG); } if (ap1->mode == am_mreg) flagx = (FLAGS) (F_MEM | F_IMMED | F_COLD); ap2 = g_expr (ep->v.p[1], flagx); ap2 = mk_quick (ap2, ep->etp); validate (ap1); /* in case push occurred */ g_code (op, ilen, ap2, ap1); freeop (ap2); return mk_legal (ap1, flags, ep->etp); }}/* * generate a &= or a |= ep. */static ADDRESS *g_aslogic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx; ADDRESS *ap1, *ap2; TYP *tp = ep->etp; EXPR *ep0 = ep->v.p[0]; if (ep0->nodetype == en_fieldref) { UVAL mask = (UVAL) bitmask (ep0->v.bit.width); EXPR *ep2; ap1 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG | F_VOL)); if (ap1->mode == am_immed) { if (op == op_or) ap1->u.offset->v.u &= mask; else ap1->u.offset->v.u |= ~mask; ap1->u.offset->v.u <<= (int) ep0->v.bit.offset; } else { if (op == op_or) g_immed (op_and, tp, (IVAL) mask, ap1); else g_immed (op_or, tp, (IVAL) ~mask, ap1); g_rotate (ap1, ep->etp, -(int) ep0->v.bit.offset, tp_void, 0); } ep2 = mk_ref (ep0->v.p[0], tp_pointer); ap2 = g_expr (ep2, F_MEM); validate (ap1); g_code (op, (ILEN) tp->size, ap1, ap2); freeop (ap2); if (!(flags & F_NOVALUE)) { freeop (ap1); ap1 = data_register (); g_code (op_move, (ILEN) tp->size, ap2, ap1); g_rotate (ap1, tp, (int) ep0->v.bit.offset, tp, (int) ep0->v.bit.width); } return mk_legal (ap1, flags, tp); } flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES); ap1 = g_expr (ep0, flagx); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_COLD)); ap2 = mk_quick (ap2, ep->etp); validate (ap1); switch (tp->size) { case IL8: g_code (op, IL4, mk_high (ap2), mk_high (ap1)); g_code (op, IL4, mk_low (ap2), mk_low (ap1)); freeop (ap2); return mk_legal (ap1, flags, tp); default: if (ap1->mode == am_areg || is_coldfire ()) { ADDRESS *ap3 = data_register (); g_move ((ILEN) tp->size, ap1, ap3); ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_COLD), tp); g_code (op, (ILEN) tp->size, ap2, ap3); g_move ((ILEN) tp->size, ap3, ap1); freeop (ap3); } else { g_code (op, (ILEN) tp->size, ap2, ap1); } freeop (ap2); return mk_legal (ap1, flags, tp); }}/*============================================================================*/static ADDRESS *g_shft P4 (OPCODE, op, ILEN, ilen, ADDRESS *, ap1, ADDRESS *, ap2){ LABEL label; switch (ilen) { case IL1: case IL2: case IL4: /* quick constant only legal if 1<=const<=8 */ if (ap1->mode == am_immed && is_icon (ap1->u.offset)) { IVAL i = ap1->u.offset->v.i; if (i == 16L && ilen == IL4) { switch (op) { case op_asl: g_code (op_swap, IL0, ap2, NIL_ADDRESS); g_code (op_clr, IL2, ap2, NIL_ADDRESS); break; case op_asr: g_code (op_swap, IL0, ap2, NIL_ADDRESS); g_code (op_ext, IL4, ap2, NIL_ADDRESS); break; case op_lsr: g_code (op_clr, IL2, ap2, NIL_ADDRESS); g_code (op_swap, IL0, ap2, NIL_ADDRESS); break; default: CANNOT_REACH_HERE (); } return ap1; } if ((i > 8L) || (i < 1L)) { ap1 = mk_legal (ap1, F_DREG, tp_char); } } validate (ap2); g_code (op, ilen, ap1, ap2); break; case IL8: if (ap1->mode == am_immed && is_icon (ap1->u.offset)) { IVAL i = ap1->u.offset->v.i; if (i == 32L) { switch (op) { case op_asl: g_code (op_move, IL4, mk_high (ap2), mk_low (ap2)); g_code (op_clr, IL4, mk_high (ap2), NIL_ADDRESS); break; case op_asr: g_code (op_move, IL4, mk_low (ap2), mk_high (ap2)); g_code (op_slt, IL0, mk_low (ap2), NIL_ADDRESS); break; case op_lsr: g_code (op_move, IL4, mk_low (ap2), mk_high (ap2)); g_code (op_clr, IL4, mk_low (ap2), NIL_ADDRESS); break; default: CANNOT_REACH_HERE (); } return ap1; } } label = nextlabel++; ap1 = mk_legal (ap1, F_DREG, tp_ulong); g_label (label); switch (op) { case op_asl: g_code (op, IL4, mk_high (ap2), NIL_ADDRESS); g_code (op_roxl, IL4, mk_low (ap2), NIL_ADDRESS); break; case op_asr: g_code (op, IL4, mk_low (ap2), NIL_ADDRESS); g_code (op_roxr, IL4, mk_high (ap2), NIL_ADDRESS); break; case op_lsr: g_code (op, IL4, mk_low (ap2), NIL_ADDRESS); g_code (op_roxr, IL4, mk_high (ap2), NIL_ADDRESS); break; default: CANNOT_REACH_HERE (); } g_code (op_dbra, IL0, ap1, mk_label (label)); break; default: CANNOT_REACH_HERE (); } return ap1;}/* * generate code to evaluate a shift node and return the address mode of the * result. */static ADDRESS *g_shift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2; TYP *tp = ep->etp; ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL | F_COLD)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_COLD)); validate (ap1); ap2 = g_shft (op, (ILEN) tp->size, ap2, ap1); freeop (ap2); return mk_legal (ap1, flags, tp);}/* * generate shift equals operators. */static ADDRESS *g_asshift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx; ADDRESS *ap1, *ap2, *ap3; TYP *tp = ep->etp; switch (tp->type) { case bt_uchar: case bt_schar: case bt_char: case bt_charu: case bt_ushort: case bt_short: case bt_int16: case bt_uint16:#ifdef COLDFIRE if (is_coldfire ()) { if (ep->v.p[0]->nodetype == en_fieldref) { return g_asbitfield (ep, flags, op, FALSE); } flagx = (FLAGS) (F_ALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED)); /* quick constant if 1<=const<=8 */ if (ap2->mode == am_immed && is_icon (ap2->u.offset) && (ap2->u.offset->v.i > 8L || ap2->u.offset->v.i < 1L)) { ap2 = mk_legal (ap2, F_DREG, tp_char); } validate (ap1); ap3 = data_register (); g_move ((ILEN) tp->size, ap1, ap3); ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_COLD), tp); g_code (op, IL4, ap2, ap3); g_move ((ILEN) tp->size, ap3, ap1); freeop (ap3); freeop (ap2); return mk_legal (ap1, flags, tp); } /*lint -fallthrough */#endif /* COLDFIRE */ case bt_int32: case bt_uint32: case bt_ulong: case bt_long: if (ep->v.p[0]->nodetype == en_fieldref) { return g_asbitfield (ep, flags, op, FALSE); } flagx = (FLAGS) (F_ALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED)); /* quick constant if 1<=const<=8 */ if (ap2->mode == am_immed && is_icon (ap2->u.offset) && (ap2->u.offset->v.i > 8L || ap2->u.offset->v.i < 1L)) { ap2 = mk_legal (ap2, F_DREG, tp_char); } validate (ap1); if (ap1->mode == am_dreg) { g_code (op, (ILEN) tp->size, ap2, ap1); } else {#if 0 /* * assemblers cannot agree on the operands for this special * version of the shift operator */ if (tp->size == 2L && is_icon (ep->v.p[1]) && ep->v.p[1]->v.i == 1) { g_code (op, 2, ap1, NIL_ADDRESS); return mk_legal (ap1, flags, tp); }#endif ap3 = data_register (); g_move ((ILEN) tp->size, ap1, ap3); g_code (op, (ILEN) tp->size, ap2, ap3); g_move ((ILEN) tp->size, ap3, ap1); freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, tp); default: FATAL ((__FILE__, "g_asshift", "illegal type %d", tp->type)); }
return NIL_ADDRESS; /*lint !e527*/ /* unreachable */}/*============================================================================*//* * generate code to evaluate a divide operator */static ADDRESS *g_div P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){ ADDRESS *ap1, *ap2; OPCODE op = op_divu; TYP *tp = ep->etp; TYP *tp2 = tp_ushort; EXPR *ep0 = ep->v.p[0]; EXPR *ep1 = ep->v.p[1]; switch (tp->type) { case bt_char: case bt_schar: tp = tp_short; op = op_divs; /*lint -fallthrough */ case bt_uchar: case bt_charu: ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL)); ap1 = g_extend (ap1, tp, tp2); ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG)); ap2 = g_extend (ap2, tp, tp2); validate (ap1); ap1 = g_extend (ap1, tp, tp_long); g_code (op, IL0, ap2, ap1); if (mod) { g_code (op_swap, IL0, ap1, NIL_ADDRESS); } freeop (ap2); return mk_legal (ap1, flags, tp); case bt_short: case bt_int16: op = op_divs; /*lint -fallthrough */ case bt_ushort: case bt_uint16: ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL)); ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG)); validate (ap1); ap1 = g_extend (ap1, ep0->etp, tp_long); g_code (op, IL0, ap2, ap1); if (mod) { g_code (op_swap, IL0, ap1, NIL_ADDRESS); } freeop (ap2); return mk_legal (ap1, flags, tp); case bt_int32: case bt_long: op = op_divs; /*lint -fallthrough */ case bt_uint32: case bt_ulong: case bt_pointer32: ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL)); ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG)); validate (ap1); g_code (op, IL4, ap2, ap1); freeop (ap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -