📄 gen68k.c
字号:
ap1->u.offset = mk_const ((IVAL) 0L); return ap1; } } if (ap2->mode == am_immed) { if (ap1->mode == am_immed) { ap1 = copy_addr (ap1, am_direct); ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset); return ap1; } if (is_short (ap2->u.offset)) { ap1 = mk_legal (ap1, F_AREG, tp_pointer); ap1 = copy_addr (ap1, am_indx); ap1->u.offset = ap2->u.offset; return ap1; } } freeop (ap2); /* release any temps in ap2 */ if (!is_temporary_register (ap1->preg)) { /* ap1 is not volatile ... */ ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), tp_pointer); } g_add (IL4, ap2, ap1); /* add left to address reg */ ap1 = copy_addr (ap1, am_ind); return ap1; /* return indirect */}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P3 (const EXPR *, ep, const TYP *, tp, FLAGS, flags){ ADDRESS *ap1; SIZE size = tp->size; EXPR *ep2; /* * If a reference to a struct/union is required, return a * pointer to the struct instead */ if (is_structure_type (tp)#ifdef FLOAT_SUPPORT || is_complex_type (tp)#endif /* FLOAT_SUPPORT */ || is_array_assignment (tp)) { return g_expr (ep, F_ALL); } switch (ep->nodetype) { case en_add: return g_index (ep); case en_global: ep2 = mk_global (SUP_DATA, ep); switch (datamodel_option) { case model_small: ap1 = mk_indirect (regdata, ep2); break; case model_large: ap1 = address_register (); g_move (IL4, mk_expr (am_immed, ep2), ap1); ap1 = copy_addr (ap1, am_indx3); ap1->sreg = regdata; ap1->u.offset = mk_const ((IVAL) 0L); break; default: CANNOT_REACH_HERE (); } return ap1; case en_autocon: if (ep->v.i >= -32768L && ep->v.i <= 32767L) { ap1 = mk_indirect (regframe, mk_const (ep->v.i)); } else { ap1 = address_register (); g_move (IL4, mk_immed (ep->v.i), ap1); g_add (IL4, mk_reg (regframe), ap1); ap1 = copy_addr (ap1, am_ind); } return ap1; case en_ainc: /* special 68000 instructions */ if ((size == 1L || size == 2L || size == 4L) && ep->v.p[1]->v.i == (IVAL) size && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r) && !(flags & F_USES)) { /* (An)+ */ ap1 = mk_amode (am_ainc); ap1->preg = ep->v.p[0]->v.r; return ap1; } /*lint -fallthrough */ default: ap1 = g_expr (ep, (FLAGS) (F_AREG | F_IMMED)); /* generate address */ 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; TYP *tp = ep->etp; ap = g_deref (ep->v.p[0], tp, F_ALL); ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), tp); g_rotate (ap, tp, (int) ep->v.bit.offset, tp, (int) ep->v.bit.width); return mk_legal (ap, flags, tp);}/*============================================================================*/#ifdef FLOAT_SUPPORTstatic void push_rtl_params P2 (const EXPR *, ep1, const EXPR *, ep2){#ifdef FLOAT_IEEE ADDRESS *ap; is_parameter++; temp_inv (NIL_REGUSAGE); ap = g_expr (ep1, F_MEM); g_code (op_pea, IL0, ap, NIL_ADDRESS); freeop (ap); if (ep2) { ap = g_expr (ep2, F_MEM); g_code (op_pea, IL0, ap, NIL_ADDRESS); freeop (ap); }#endif /* FLOAT_IEEE */#ifdef FLOAT_MFFP is_parameter++; temp_inv (NIL_REGUSAGE); VOIDCAST push_param (ep1); if (ep2) { VOIDCAST push_param (ep2); }#endif /* FLOAT_MFFP */ is_parameter--;}#endif /* FLOAT_SUPPORT *//*============================================================================*//* * generate code to evaluate a unary minus or complement. float: unary minus * calls a library function */static ADDRESS *g_unary P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap; TYP *tp = ep->etp; switch (tp->type) { case bt_uchar: case bt_schar: case bt_char: case bt_charu: 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) tp->size, ap, NIL_ADDRESS); return mk_legal (ap, flags, tp);#ifdef LONGLONG_SUPPORT case bt_ulonglong: case bt_longlong: ap = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL)); g_code (op, IL4, mk_high (ap), NIL_ADDRESS); switch (op) { case op_neg: g_code (op_negx, IL4, mk_low (ap), NIL_ADDRESS); break; case op_not: g_code (op, IL4, mk_low (ap), NIL_ADDRESS); break; default: CANNOT_REACH_HERE (); } return mk_legal (ap, flags, tp);#endif /* LONGLONG_SUPPORT */ default: FATAL ( (__FILE__, "g_unary", "illegal type %d or operation %d", tp->type, op)); }
return NIL_ADDRESS; /*lint !e527*/ /* unreachable */}/*============================================================================*//* * generate an auto increment or decrement node. op should be either op_add * (for increment) or op_sub (for decrement). */static ADDRESS *g_aincdec P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2, *ap3; TYP *tp = ep->etp; FLAGS flagx; switch (tp->type) { case bt_bool: ap1 = g_expr (ep->v.p[0], F_ALL); switch (op) { case op_add: g_move ((ILEN) tp->size, mk_immed ((IVAL) 1L), ap1); break; default: g_move ((ILEN) tp->size, mk_immed ((IVAL) 0L), ap1); break; } return mk_legal (ap1, flags, tp); case bt_uchar: case bt_schar: case bt_char: case bt_charu: case bt_short: case bt_ushort: 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, TRUE); } ap1 = temp_reg (flags); ap2 = g_expr (ep->v.p[0], F_ALL); validate (ap1); g_move ((ILEN) tp->size, ap2, ap1); ap1 = g_extend (ap1, tp, is_signed_type (tp) ? tp_long : tp_ulong); ap3 = g_expr (ep->v.p[1], F_IMMED); validate (ap1); switch (op) { case op_add: g_add (IL4, ap3, ap1); break; default: g_sub (IL4, ap3, ap1); break; } g_move ((ILEN) tp->size, ap1, ap2); if (!(flags & F_NOVALUE)) { switch (op) { case op_add: g_sub (IL4, ap3, ap1); break; default: g_add (IL4, ap3, ap1); break; } } 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, TRUE); } flagx = is_coldfire ()? F_DREG : F_IMMED; if (flags & F_NOVALUE) { /* don''t need result */ ap1 = g_expr (ep->v.p[0], F_ALL); ap2 = g_expr (ep->v.p[1], flagx); switch (op) { case op_add: g_add ((ILEN) tp->size, ap2, ap1); break; default: g_sub ((ILEN) tp->size, ap2, ap1); break; } } else { ap1 = temp_reg (flags); ap2 = g_expr (ep->v.p[0], (FLAGS) (F_ALL | F_USES)); validate (ap1); g_move ((ILEN) tp->size, ap2, ap1); ap3 = g_expr (ep->v.p[1], flagx); validate (ap2); switch (op) { case op_add: g_add ((ILEN) tp->size, ap3, ap2); break; default: g_sub ((ILEN) tp->size, ap3, ap2); break; } freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, tp);#ifdef LONGLONG_SUPPORT case bt_longlong: case bt_ulonglong: flagx = F_DREG | F_IMMED; if (flags & F_NOVALUE) { /* don''t need result */ ADDRESS *ap4; ap1 = g_expr (ep->v.p[0], F_ALL); ap2 = g_expr (ep->v.p[1], flagx); validate (ap1); ap3 = data_register (); g_code (op_move, IL4, mk_low (ap2), ap3); ap4 = data_register (); g_code (op_move, IL4, mk_low (ap1), ap4); switch (op) { case op_add: g_add (IL4, mk_high (ap2), mk_high (ap1)); g_code (op_addx, IL4, ap3, ap4); break; default: g_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); freeop (ap2); } else { ADDRESS *ap4; ap1 = g_expr (ep->v.p[0], F_ALL); g_move8 (ap1, &push); ap2 = g_expr (ep->v.p[1], flagx); validate (ap1); ap3 = data_register (); g_code (op_move, IL4, mk_low (ap2), ap3); ap4 = data_register (); g_code (op_move, IL4, mk_low (ap1), ap4); switch (op) { case op_add: g_add (IL4, mk_high (ap2), mk_high (ap1)); g_code (op_addx, IL4, ap3, ap4); break; default: g_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); freeop (ap2); freeop (ap1); ap1 = mdata_register (); g_move8 (&pop, ap1); } validate (ap1); return mk_legal (ap1, flags, tp);#endif /* LONGLONG_SUPPORT */ default: FATAL ((__FILE__, "g_aincdec", "illegal type %d or float", tp->type)); }
return NIL_ADDRESS; /*lint !e527*/ /* unreachable */}/*============================================================================*//* * generate code to evaluate a binary node and return the addressing mode of * the result. */static ADDRESS *g_addsub P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2; TYP *tp = ep->etp; switch (tp->type) { case bt_uchar: case bt_schar: case bt_char: case bt_charu: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_COLD | (flags & F_DREG))); ap2 = g_expr (ep->v.p[1], (FLAGS) ((F_ALL & ~F_AREG) | F_COLD)); validate (ap1); /* in case push occurred */ 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); 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_VOL | F_COLD | (flags & (F_DREG | F_AREG)))); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_ALL | F_COLD)); validate (ap1); /* in case push occurred */ 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: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_COLD | F_DREG)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_MEM | F_COLD)); validate (ap1); { ADDRESS *ap3 = data_register (); g_code (op_move, IL4, mk_low (ap2), ap3); validate (ap1); /* in case push occurred */ 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); } freeop (ap2); 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; ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_FREG)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM)); validate (ap1); /* in case push occurred */ g_fcode (op, (ILEN) tp->size, ap2, ap1); freeop (ap2); return mk_legal (ap1, flags, tp);#endif /* FLOAT_IEEE */ default: FATAL ((__FILE__, "g_addsub", "illegal type %d", tp->type)); }
return NIL_ADDRESS; /*lint !e527*/ /* unreachable */}/* * generate a plus equal or a minus equal node. */static ADDRESS *g_asadd P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx, flagx2; ADDRESS *ap1, *ap2; TYP *tp = ep->etp; switch (tp->type) { case bt_bool: ap1 = g_expr (ep->v.p[0], F_ALL); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG)); validate (ap1); switch (ap2->mode) { case am_immed: switch (op) { case op_add: ap2->u.offset->v.i = (IVAL) (ap2->u.offset->v.i != 0L); break; default: ap2->u.offset->v.i = (IVAL) (ap2->u.offset->v.i == 0L); break; } break; default: break; } g_code (op_or, (ILEN) tp->size, ap2, ap1); freeop (ap2); return mk_legal (ap1, flags, tp); case bt_char: case bt_charu: case bt_schar: case bt_uchar: case bt_short: case bt_ushort: case bt_int16: case bt_uint16:#ifdef COLDFIRE if (is_coldfire ()) { ADDRESS *ap3; if (ep->v.p[0]->nodetype == en_fieldref) { return g_asbitfield (ep, flags, op, TRUE); } ap1 = temp_reg (flags); ap2 = g_expr (ep->v.p[0], F_ALL); validate (ap1); g_move ((ILEN) tp->size, ap2, ap1); ap1 = g_extend (ap1, tp, is_signed_type (tp) ? tp_long : tp_ulong); ap3 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG)); validate (ap1); switch (op) { case op_add: g_add (IL4, ap3, ap1); break; default: g_sub (IL4, ap3, ap1); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -