📄 genc30.c
字号:
if (isanyreg (ap1)) { ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL | F_UNSIGNED)); } else { ap2 = g_expr (ep->v.p[1], F_XREG); } validate (ap1); if (isanyreg (ap1)) { g_code (op, OP_INT, ap2, ap1); } else { ap2 = mk_legal (ap2, (FLAGS) (F_VOL | F_XREG), OP_INT); g_code (op, OP_INT, ap1, ap2); g_code (op_sti, OP_INT, ap2, ap1); } freeop (ap2); return mk_legal (ap1, flags, OP_INT);}/*============================================================================*//* * generate code to evaluate a shift node and return the address mode of the * result. * Note: right shifts will have already been converted to negative left * shifts. */static ADDRESS *g_shift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2, *ap3; if (is_op3_possible (ep->v.p[0]) && is_op3_possible (ep->v.p[1])) { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_XREG | F_MEM)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_XREG | F_MEM)); validate (ap1); /* Just to be sure... check again for correct op3-operands */ if (is_op3_violated (ap1) || is_op3_violated (ap2)) { FATAL ((__FILE__, "g_shift", "inconsistency int ")); } switch (op) { case op_lsh: op = op_lsh3; break; case op_ash: op = op_ash3; break; default: FATAL ((__FILE__, "g_shift", "illegal opcode %d", op)); break; } freeop (ap2); freeop (ap1); ap3 = temporary_register (best_flags (flags, F_XREG)); g_code3 (op, OP_INT, ap2, ap1, ap3); ap1 = ap3; } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | best_flags (flags, F_XREG))); ap2 = g_expr (ep->v.p[1], F_IALL); validate (ap1); g_code (op, OP_INT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_INT);}/* * generate shift equals operators. */static ADDRESS *g_asshift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx; ADDRESS *ap1, *ap2, *ap3; switch (ep->etp->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: case bt_int32: case bt_uint32: case bt_ulong: case bt_long: case bt_pointer32: if (ep->v.p[0]->nodetype == en_fieldref) return g_asbitfield (ep, flags, op, FALSE); flagx = (flags & F_NOVALUE) ? F_IALL : (FLAGS) (F_IALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL)); validate (ap1); if (isanyreg (ap1)) { g_code (op, OP_INT, ap2, ap1); } else { ap3 = temporary_register (F_XREG); g_code (op_ldi, OP_INT, ap1, ap3); g_code (op, OP_INT, ap2, ap3); g_code (op_sti, OP_INT, ap3, ap1); freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, OP_INT); default: FATAL ((__FILE__, "g_asshift", "illegal type %d", ep->etp->type)); break; } return NIL_ADDRESS;}/*============================================================================*//* * generate code to evaluate a divide operator */static ADDRESS *g_div P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){ BOOL is_signed = FALSE; ADDRESS *ap1, *ap2; switch (ep->etp->type) { case bt_char: case bt_schar: case bt_short: case bt_int16: case bt_int32: case bt_long: is_signed = TRUE; /*FALLTHRU */ case bt_uchar: case bt_charu: case bt_ushort: case bt_uint16: case bt_uint32: case bt_ulong: case bt_pointer32: temp_inv (); ap1 = g_expr (ep->v.p[0], F_IALL); ap2 = g_expr (ep->v.p[1], F_IALL); validate (ap1); freeop (ap2); freeop (ap1); if (ap2->preg == REG_R0) { /* bad luck, parameter is using space for ap1 */ if (ap1->preg == REG_R1) { /* its worse, a2 is in r0 and a1 is in r1 */ g_code (op_ldi, OP_INT, ap2, mk_reg (REG_AR0)); g_code (op_ldi, OP_INT, ap1, mk_reg (REG_R0)); g_code (op_ldi, OP_INT, mk_reg (REG_AR0), mk_reg (REG_R1)); } else { g_code (op_ldi, OP_INT, ap2, mk_reg (REG_R1)); g_code (op_ldi, OP_INT, ap1, mk_reg (REG_R0)); } } else { g_code (op_ldi, OP_INT, ap1, mk_reg (REG_R0)); g_code (op_ldi, OP_INT, ap2, mk_reg (REG_R1)); } if (is_signed == FALSE) { call_library_r0_r1 (mod ? psup_ulrem : psup_uldiv); } else { call_library_r0_r1 (mod ? psup_lrem : psup_ldiv); } return func_result (flags, 0L, ep->etp); case bt_float: case bt_double: case bt_longdouble: temp_inv (); ap1 = g_expr (ep->v.p[0], F_FALL); ap2 = g_expr (ep->v.p[1], F_FALL); validate (ap1); freeop (ap2); freeop (ap1); if (ap2->preg == REG_R0) { /* bad luck, parameter is using space for ap1 */ if (ap1->preg == REG_R1) { /* its worse, a2 is in r0 and a1 is in r1 */ /* could be solved with parallel addressing */ g_code (op_ldf, OP_INT, ap2, mk_freg (REG_R2)); g_code (op_ldf, OP_INT, ap1, mk_freg (REG_R0)); g_code (op_ldf, OP_INT, mk_freg (REG_R2), mk_freg (REG_R1)); } else { g_code (op_ldf, OP_INT, ap2, mk_freg (REG_R1)); g_code (op_ldf, OP_INT, ap1, mk_freg (REG_R0)); } } else { g_code (op_ldf, OP_INT, ap1, mk_freg (REG_R0)); g_code (op_ldf, OP_INT, ap2, mk_freg (REG_R1)); } call_library_r0_r1 (mod ? psup_lrem : psup_fpdiv); return func_result (flags, 0L, ep->etp); default: FATAL ( (__FILE__, "g_div", "%d: illegal type %d", mod, ep->etp->type)); break; } return NIL_ADDRESS;}/* * generate /= and %= nodes. */static ADDRESS *g_asdiv P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){ switch (ep->etp->type) { case bt_char: case bt_schar: case bt_short: case bt_int16: case bt_int32: case bt_long: if (mod) { return as_fcall (ep, flags, psup_lrem, OP_INT); } else { return as_fcall (ep, flags, psup_ldiv, OP_INT); } case bt_charu: case bt_uchar: case bt_ushort: case bt_uint16: case bt_uint32: case bt_ulong: case bt_pointer32: if (mod) { return as_fcall (ep, flags, psup_ulrem, OP_INT); } else { return as_fcall (ep, flags, psup_uldiv, OP_INT); } case bt_float: case bt_double: case bt_longdouble: if (mod) { return as_fcall (ep, flags, psup_fprem, OP_FLOAT); } else { return as_fcall (ep, flags, psup_fpdiv, OP_FLOAT); } default: FATAL ( (__FILE__, "asdiv", "%d: illegal type %d", mod, ep->etp->type)); break; } return NIL_ADDRESS;}/*============================================================================*/static void g_inline_multiply P3 (ADDRESS *, ap1, ADDRESS *, ap2, int, is_signed){ ADDRESS *ap3, *ap4, *ap5; ap3 = temporary_register (F_XREG); ap4 = temporary_register (F_XREG); if (is_signed == FALSE) { /* get signum */ ap5 = temporary_register (F_XREG); /* * validates are not nescessary, since there must be enough * registers availlable, if not, this is a compilererror * and the validates will catch it and produce a fatal-error */ validate (ap2); validate (ap1); g_code3 (op_xor3, OP_INT, ap2, ap1, ap5); g_code (op_absi, OP_INT, ap1, ap1); g_code (op_absi, OP_INT, ap2, ap2); } g_code (op_ldi, OP_INT, mk_immed (-16), ap4); g_code3 (op_lsh3, OP_INT, ap4, ap1, ap3); g_code3 (op_lsh3, OP_INT, ap4, ap2, ap4); g_code (op_and, OP_INT, mk_uimmed (0xFFFFL), ap1); g_code (op_and, OP_INT, mk_uimmed (0XFFFFL), ap2); g_code (op_mpyi, OP_INT, ap1, ap4); g_code (op_mpyi, OP_INT, ap2, ap3); g_code (op_mpyi, OP_INT, ap1, ap2); g_code (op_addi, OP_INT, ap4, ap3); g_code (op_lsh, OP_INT, mk_immed (16), ap3); g_code3 (op_addi3, OP_INT, ap3, ap2, ap1); if (is_signed == FALSE) { /* get signum */ g_code (op_negi, OP_INT, ap1, ap2); g_code3 (op_tstb3, OP_INT, ap5, ap5, NIL_ADDRESS); g_code (op_ldin, OP_INT, ap2, ap1); freeop (ap5); } freeop (ap4); freeop (ap3);}static ADDRESS *g_mul P2 (const EXPR *, ep, FLAGS, flags){ int is_signed = TRUE; ADDRESS *ap1, *ap2, *ap3; switch (ep->etp->type) { case bt_uint32: case bt_ulong: case bt_pointer32: is_signed = FALSE; /*FALLTHRU */ case bt_long: case bt_int32: if (opt_true_long != OPT_NO) { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | best_flags (flags, F_XREG))); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_VOL | F_XREG)); validate (ap1); g_inline_multiply (ap1, ap2, is_signed); freeop (ap2); return mk_legal (ap1, flags, OP_INT); } /*FALLTHRU */ case bt_char: case bt_schar: case bt_charu: case bt_uchar: case bt_short: case bt_int16: case bt_ushort: case bt_uint16: if (is_op3_possible (ep->v.p[0]) && is_op3_possible (ep->v.p[1])) { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_XREG | F_MEM)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_XREG | F_MEM)); validate (ap1); /* Just to be sure... check again for correct op3-operands */ if (is_op3_violated (ap1) || is_op3_violated (ap2)) { FATAL ((__FILE__, "g_mul", "inconsistency int ")); } freeop (ap2); freeop (ap1); ap3 = temporary_register (best_flags (flags, F_XREG)); g_code3 (op_mpyi3, OP_INT, ap2, ap1, ap3); ap1 = ap3; } else { if (tst_iconst (ep->v.p[0])) { ap1 = g_expr (ep->v.p[1], (FLAGS) (F_VOL | best_flags (flags, F_XREG))); ap2 = g_expr (ep->v.p[0], F_IALL); } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | best_flags (flags, F_XREG))); ap2 = g_expr (ep->v.p[1], F_IALL); } validate (ap1); /* in case push occurred */ g_code (op_mpyi, OP_INT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_INT); case bt_float: case bt_double: case bt_longdouble: if (is_op3_possible (ep->v.p[0]) && is_op3_possible (ep->v.p[1])) { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_FREG | F_MEM)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM)); validate (ap1); /* Just to be sure... check again for correct op3-operands */ if (is_op3_violated (ap1) || is_op3_violated (ap2)) { FATAL ((__FILE__, "g_mul", "inconsistency float ")); } freeop (ap2); freeop (ap1); ap3 = temporary_register (F_FREG); g_code3 (op_mpyf3, OP_FLOAT, ap2, ap1, ap3); ap1 = ap3; } else { if (ep->v.p[0]->nodetype == en_fcon) { ap1 = g_expr (ep->v.p[1], (FLAGS) (F_VOL | F_FREG)); ap2 = g_expr (ep->v.p[0], F_FALL); } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_FREG)); ap2 = g_expr (ep->v.p[1], F_FALL); } validate (ap1); /* in case push occurred */ g_code (op_mpyf, OP_FLOAT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_FLOAT); default: FATAL ((__FILE__, "g_mul", "illegal type %d", ep->etp->type)); break; } return NIL_ADDRESS;}/* * generate a *= node. */static ADDRESS *g_asmul P2 (const EXPR *, ep, FLAGS, flags){ int is_signed = TRUE; ADDRESS *ap1, *ap2, *ap3, *ap6; switch (ep->etp->type) { case bt_int32: case bt_long: is_signed = FALSE; /*FALLTHRU */ case bt_uint32: case bt_ulong: case bt_pointer32: if (opt_true_long != OPT_NO) { if (ep->v.p[0]->nodetype == en_fieldref) return g_asbitfield (ep, flags, op_mpyi, FALSE); ap1 = g_expr (ep->v.p[0], (FLAGS) (F_IALL | F_USES)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_XREG | F_VOL)); if (isanyreg (ap1)) { validate (ap1); ap6 = NULL; } else { ap6 = ap1; ap1 = temporary_register (F_XREG); validate (ap6); g_code (op_ldi, OP_INT, ap6, ap1); } validate (ap2); g_inline_multiply (ap1, ap2, is_signed); if (ap6 != NULL) { freeop (ap1); validate (ap6); g_code (op_sti, OP_INT, ap1, ap6); ap1 = ap6; } freeop (ap2); return mk_legal (ap1, flags, OP_INT); } /*FALLTHRU */ case bt_char: case bt_schar: case bt_charu: case bt_uchar: case bt_short: case bt_int16: case bt_ushort: case bt_uint16: if (ep->v.p[0]->nodetype == en_fieldref) return g_asbitfield (ep, flags, op_mpyi, FALSE); ap1 = g_expr (ep->v.p[0], (FLAGS) (F_IALL | F_USES)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL)); if (isanyreg (ap1)) { validate (ap1); g_code (op_mpyi, OP_INT, ap2, ap1); freeop (ap2); } else { ap3 = temporary_register (F_XREG); validate (ap1); g_code (op_ldi, OP_INT, ap1, ap3); g_code (op_mpyi, OP_INT, ap2, ap3); g_code (op_sti, OP_INT, ap3, ap1); freeop (ap3); freeop (ap2); } return mk_legal (ap1, flags, OP_INT); case bt_float: case bt_double: case bt_longdouble: ap1 = g_expr (ep->v.p[0], (FLAGS) (F_FREG | F_MEM | F_IMMED | F_USES)); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM | F_IMMED)); if ((ap1->mode != am_freg)) { ap3 = data_register (F_FREG); validate (ap1); g_code (op_ldf, OP_FLOAT, ap1, ap3); g_code (op_mpyf, OP_FLOAT, ap2, ap3); g_code (op_stf, OP_FLOAT, ap3, ap1); freeop (ap3); freeop (ap2); } else { validate (ap1); g_code (op_mpyf, OP_FLOAT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_FLOAT); default: FATAL ((__FILE__, "asmul", "illegal type %d", ep->etp->typ
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -