📄 genc30.c
字号:
&& 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; ap1->u.offset = mk_const (ep->v.p[1]->v.i); return ap1; } break; case en_adec: /* special TMS320C30 instructions */ if (ep->v.p[1]->v.i <= 255L /* if size less than max autoincrement */ && ep->v.p[1]->v.i >= 0L /* and if size positive */ && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r) && !(flags & F_USES)) { /* (An)- */ ap1 = mk_amode (am_adec); ap1->preg = ep->v.p[0]->v.r; ap1->u.offset = mk_const (ep->v.p[1]->v.i); return ap1; } break; case en_asadd: /* special TMS320C30 instructions */ if (is_icon (ep->v.p[1]) && ep->v.p[1]->v.i <= 255L /* if size less than max autoincrement */ && ep->v.p[1]->v.i >= 0L /* and if size positive */ && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r) && !(flags & F_USES)) { /* ++(An) */ ap1 = mk_amode (am_preinc); ap1->preg = ep->v.p[0]->v.r; ap1->u.offset = mk_const (ep->v.p[1]->v.i); return ap1; } break; case en_assub: /* special TMS320C30 instructions */ if (is_icon (ep->v.p[1]) && ep->v.p[1]->v.i <= 255L /* if size less than max autoincrement */ && ep->v.p[1]->v.i >= 0L /* and if size positive */ && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r) && !(flags & F_USES)) { /* --(An) */ ap1 = mk_amode (am_predec); ap1->preg = ep->v.p[0]->v.r; ap1->u.offset = mk_const (ep->v.p[1]->v.i); return ap1; } break; default: break; } /* * F_DIRECT Supresses to make a doubleindirection for * immediates, sinc it will be converted in an direct-reference */ ap1 = g_expr (ep, (FLAGS) (F_AREG | F_IMMED | F_DIRECT)); /* generate address */ if (ap1->mode == am_areg) { return copy_addr (ap1, am_ind); } return copy_addr (ap1, am_direct);}/* * get a bitfield value */static ADDRESS *g_fderef P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap; ap = g_deref (ep->v.p[0], ep->etp, (FLAGS) (F_IALL)); ap = mk_legal (ap, (FLAGS) (F_XREG | F_VOL), OP_INT); g_rotate (ap, (int) ep->v.bit.offset, ep->etp, (int) ep->v.bit.width); return mk_legal (ap, flags, OP_INT);}/*============================================================================*//* * 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, *ap2; switch (ep->etp->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) (op == op_not ? F_IALL | F_UNSIGNED : F_IALL)); /* maybe we can use ap... */ freeop (ap); ap2 = temporary_register (best_flags (flags, F_XREG)); g_code (op, OP_INT, ap, ap2); return mk_legal (ap2, flags, OP_INT); case bt_float: case bt_double: case bt_longdouble: if (op == op_negi) { ap = g_expr (ep->v.p[0], (FLAGS) (F_FALL)); /* maybe we can use ap... */ freeop (ap); ap2 = temporary_register (F_FREG); g_code (op_negf, OP_FLOAT, ap, ap2); return mk_legal (ap2, flags, OP_FLOAT); } /* Fall through */ default: FATAL ( (__FILE__, "g_unary", "illegal type %d or operation %d", ep->etp->type, op)); break; } return NIL_ADDRESS;}/*============================================================================*//* * 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; switch (ep->etp->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: if (ep->v.p[0]->nodetype == en_fieldref) return g_asbitfield (ep, flags, op, TRUE); if (flags & F_NOVALUE) { /* dont need result */ ap1 = g_expr (ep->v.p[0], (FLAGS) (F_IALL)); /* if ap1 is in register we can modify it directly */ if (isanyreg (ap1)) { g_immed (op, ep->v.p[1]->v.i, ap1); } else { /* else we must get ap1 in a register, modify it and store it again */ ap2 = temporary_register (F_XREG); g_code (op_ldi, OP_INT, ap1, ap2); g_immed (op, ep->v.p[1]->v.i, ap2); g_code (op_sti, OP_INT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_INT); } ap1 = temporary_register (best_flags (flags, F_XREG)); ap2 = g_expr (ep->v.p[0], (FLAGS) (F_IALL | F_USES)); validate (ap1); g_code (op_ldi, OP_INT, ap2, ap1); /* if ap2 is in register we can modify it directly */ if (isanyreg (ap2)) { g_immed (op, ep->v.p[1]->v.i, ap2); } else { /* else we must get ap2 in a register, modify it and store it again */ ap3 = temporary_register (F_XREG); g_code (op_ldi, OP_INT, ap1, ap3); g_immed (op, ep->v.p[1]->v.i, ap3); g_code (op_sti, OP_INT, ap3, ap2); freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, OP_INT);#ifdef FLOAT_SUPPORT case bt_float: case bt_double: case bt_longdouble: if (flags & F_NOVALUE) { /* dont need result */ ap1 = g_expr (ep->v.p[0], F_FALL); /* if ap1 is in register we can modify it directly */ if (ap1->mode == am_freg) { g_code (op, OP_FLOAT, mk_immedfloat ((double) ep->v.p[1]->v.f), ap1); } else { /* else we must get ap1 in a register, modify it and store it again */ ap2 = temporary_register (F_FREG); g_code (op_ldf, OP_FLOAT, ap1, ap2); g_code (op, OP_FLOAT, mk_immedfloat ((double) ep->v.p[1]->v.f), ap2); g_code (op_stf, OP_FLOAT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_FLOAT); } ap1 = temporary_register (F_FREG); ap2 = g_expr (ep->v.p[0], (FLAGS) (F_FALL | F_USES)); validate (ap1); g_code (op_ldf, OP_FLOAT, ap2, ap1); /* if ap2 is in register we can modify it directly */ if (ap2->mode == am_freg) { g_code (op, OP_FLOAT, mk_immedfloat ((double) ep->v.p[1]->v.f), ap2); } else { /* else we must get ap2 in a register, modify it and store it again */ ap3 = temporary_register (F_FREG); g_code (op_ldf, OP_FLOAT, ap1, ap3); g_code (op, OP_FLOAT, mk_immedfloat ((double) ep->v.p[1]->v.f), ap3); g_code (op_stf, OP_FLOAT, ap3, ap2); freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, OP_FLOAT);#endif /* FLOAT_SUPPORT */ default: FATAL ( (__FILE__, "g_aincdec", "illegal type %d or float", 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_addsub P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ ADDRESS *ap1, *ap2, *ap3; switch (ep->etp->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: 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)); /* Just to be sure... check again for correct op3-operands */ if (is_op3_violated (ap1) || is_op3_violated (ap2)) { FATAL ((__FILE__, "g_addsub", "inconsistency int ")); } validate (ap1); freeop (ap2); freeop (ap1); ap3 = temporary_register (best_flags (flags, F_XREG)); g_code3 ((op == op_addi ? op_addi3 : op_subi3), 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); if (op == op_subi) op = op_subri; } 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, OP_INT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_INT); case bt_longdouble: case bt_double: case bt_float: op = (op == op_addi) ? op_addf : op_subf; 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)); /* Just to be sure... check again for correct op3-operands */ if (is_op3_violated (ap1) || is_op3_violated (ap2)) { FATAL ((__FILE__, "g_addsub", "inconsistency float ")); } validate (ap1); freeop (ap2); freeop (ap1); ap3 = temporary_register (F_FREG); g_code3 ((op == op_addf ? op_addf3 : op_subf3), 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); if (op == op_subf) op = op_subrf; } 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, OP_FLOAT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_FLOAT); default: FATAL ((__FILE__, "g_addsub", "illegal type %d", ep->etp->type)); break; } return NIL_ADDRESS;}/* * generate a plus equal or a minus equal node. */static ADDRESS *g_asadd P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx; ADDRESS *ap1, *ap2, *ap3; switch (ep->etp->type) { case bt_char: case bt_charu: case bt_schar: case bt_uchar: 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) flagx = F_IALL; else flagx = (FLAGS) (F_IALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); if (isanyreg (ap1)) { ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL)); validate (ap1); g_code (op, OP_INT, ap2, ap1); } else { ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL)); validate (ap1); 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); case bt_float: case bt_double: case bt_longdouble: op = (op == op_addi) ? op_addf : op_subf; flagx = (flags & F_NOVALUE) ? F_FALL : (FLAGS) (F_FALL | F_USES); ap1 = g_expr (ep->v.p[0], flagx); if (ap1->mode == am_freg) { ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM | F_IMMED)); validate (ap1); g_code (op, OP_FLOAT, ap2, ap1); } else { ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM | F_IMMED)); validate (ap1); ap3 = temporary_register (F_FREG); g_code (op_ldf, OP_FLOAT, ap1, ap3); g_code (op, OP_FLOAT, ap2, ap3); g_code (op_stf, OP_FLOAT, ap3, ap1); freeop (ap3); } freeop (ap2); return mk_legal (ap1, flags, OP_FLOAT); default: FATAL ((__FILE__, "asadd", "illegal type %d", ep->etp->type)); break; } return NIL_ADDRESS;}/*============================================================================*//* * 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; 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_logic", "inconsistency int ")); } switch (op) { case op_and: op = op_and3; break; case op_andn: op = op_andn3; break; case op_or: op = op_or3; break; case op_xor: op = op_xor3; break; default: FATAL ((__FILE__, "g_logic", "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 { 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], (FLAGS) (F_IALL | F_UNSIGNED)); } else { ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | best_flags (flags, F_XREG))); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IALL | F_UNSIGNED)); } validate (ap1); /* in case push occurred */ g_code (op, OP_INT, ap2, ap1); freeop (ap2); } return mk_legal (ap1, flags, OP_INT);}/* * generate a &= or a |= node. */static ADDRESS *g_aslogic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){ FLAGS flagx; ADDRESS *ap1, *ap2; 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -