📄 genc30.c
字号:
if (flags & F_NOVALUE) { freeop (ap); return NIL_ADDRESS; } if (ap == NIL_ADDRESS) { FATAL ((__FILE__, "mk_legal", "ap = 0")); return NIL_ADDRESS; } switch (size) { case OP_INT: OpSto = op_sti; OpLd = op_ldi; if (flags & F_FREG) { FATAL ((__FILE__, "mk_legal", "op_int float mixed with integer")); } break; case OP_FLOAT: OpSto = op_stf; OpLd = op_ldf; if (flags & F_XREG) { FATAL ( (__FILE__, "mk_legal", "op_float float mixed with integer")); } break; default: FATAL ((__FILE__, "mk_legal", "illegal size0")); break; } switch (ap->mode) { case am_immed: if (flags & F_IMMED) { return ap; /* mode ok */ } break; case am_areg: if (flags & F_AREG && (!(flags & F_VOL) || is_temporary_register (ap->preg))) { return ap; } if (flags & F_FREG) { FATAL ( (__FILE__, "mk_legal", "am_areg float mixed with integer")); } break; case am_ireg: if (flags & F_IREG && (!(flags & F_VOL) || is_temporary_register (ap->preg))) { return ap; } if (flags & F_FREG) { FATAL ( (__FILE__, "mk_legal", "am_ireg float mixed with integer")); } break; case am_dreg: if (flags & F_DREG && (!(flags & F_VOL) || is_temporary_register (ap->preg))) { return ap; } if (flags & F_FREG) { FATAL ( (__FILE__, "mk_legal", "am_dreg float mixed with integer")); } break; case am_freg: if (flags & F_FREG && (!(flags & F_VOL) || is_temporary_register (ap->preg))) { return ap; } if (flags & F_XREG) { FATAL ( (__FILE__, "mk_legal", "am_freg float mixed with integer")); } break; case am_ind: case am_const_ind: case am_indx: case am_indx2: case am_indxs: case am_direct: case am_const_direct: case am_adec: case am_ainc: case am_preinc: case am_predec: if (flags & F_MEM) return ap; break; default: break; } if ((flags & F_XREG) != 0) { /* decide, which mode is better */ if (is_free_data () && (flags & F_DREG)) { freeop (ap); /* maybe we can use it... */ ap2 = data_register (F_DREG); /* allocate to dreg */ g_code (op_ldi, OP_INT, ap, ap2); return ap2; } if (is_free_addr () && (flags & F_AREG)) { freeop (ap); /* maybe we can use it... */ ap2 = address_register (); /* allocate to dreg */ g_code (op_ldi, OP_INT, ap, ap2); return ap2; } if (is_free_ireg () && (flags & F_IREG)) { freeop (ap); ap2 = index_register (); g_code (op_ldi, OP_INT, ap, ap2); return ap2; } } if (flags & F_DREG) { freeop (ap); /* maybe we can use it... */ ap2 = data_register (F_DREG); /* allocate to dreg */ g_code (op_ldi, OP_INT, ap, ap2); return ap2; } if (flags & F_FREG) { freeop (ap); /* maybe we can use it... */ ap2 = data_register (F_FREG); /* allocate to dreg */ g_code (op_ldf, OP_FLOAT, ap, ap2); return ap2; } if (flags & F_AREG) { freeop (ap); ap2 = address_register (); g_code (op_ldi, OP_INT, ap, ap2); return ap2; } if (flags & F_IREG) { freeop (ap); ap2 = index_register (); g_code (op_ldi, OP_INT, ap, ap2); return ap2; } if (flags & F_MEM) { if (ap->mode == am_immed) { /* we can not store immediates directly in memory */ freeop (ap); ap3 = data_register ((size == OP_INT) ? F_DREG : F_FREG); g_code (OpLd, size, ap, ap3); ap = ap3; } freeop (ap); ap2 = mk_scratch (1L); /* copy value into memory */ g_code (OpSto, size, ap, ap2); return ap2; } FATAL ((__FILE__, "mk_legal", "")); return NIL_ADDRESS;}/*****************************************************************************//* * add a compiler generated label to the peep list. */PRIVATE void g_label P1 (LABEL, labno){ sync_stack (); g_code (op_label, OP_INT, mk_label (labno), NIL_ADDRESS);}#ifdef DEBUGOPT/* * add a source line number to the peep list. */PRIVATE void g_line P2 (LINE, line, const CHAR *, linetxt){ g_code3 (op_line, OP_INT, mk_line (line), mk_linetxt (linetxt), NIL_ADDRESS);}#endif /*DEBUGOPT *//* * add a conditional branch instruction to the peep list. */static void g_cbranch P2 (OPCODE, op, LABEL, labno){ sync_stack (); g_code (op, OP_INT, mk_Jumplabel (labno), NIL_ADDRESS);}/* * add a branch instruction to the peep list. */PRIVATE void g_branch P1 (LABEL, labno){ g_cbranch (op_br, labno);}/* * adjust the stack by "bytes" bytes. */PRIVATE void g_stack P1 (SIZE, bytes){ if (bytes != 0L) { /* adjust stack pointer */ g_immed (op_subi, bytes, mk_reg (STACKPTR)); stack_offset -= bytes; if (max_stack_adjust < bytes) max_stack_adjust = bytes; }}/* * Generate an instruction which takes an immediate option with optimal * (for space) instruction(s). */static void g_immed P3 (OPCODE, op, IVAL, i, ADDRESS *, ap){ if (ap != NIL_ADDRESS) { if (!isanyreg (ap)) FATAL ((__FILE__, "g_immed", "immed-to-memory")); } if ((i >= -32768L && i <= 32767L) || (opt_const_in_ram != OPT_NO)) { g_code (op, OP_INT, mk_immed (i), ap); } else { /* bigger constants we must build by hand */ /* in future it could be solved through storing constants */ /* in datasegment and fetching them from there */ ADDRESS *ap1; IVAL low = (IVAL) ((UVAL) i & 0xFFFFL); IVAL high = (IVAL) ((UVAL) i >> 16); if (op == op_ldi) { ap1 = ap; } else { ap1 = temporary_register (F_XREG); } g_code (op_ldi, OP_INT, mk_immed (high), ap1); if (high != 0) { g_code (op_lsh, OP_INT, mk_immed (16), ap1); } if (low != 0) { g_code (op_or, OP_INT, mk_uimmed (low), ap1); } if (op != op_ldi) { g_code (op, OP_INT, ap1, ap); freeop (ap1); } }}/* * Generate an instruction which takes an unsigned immediate option with * optimal (for space) instruction(s). */static void g_uimmed P3 (OPCODE, op, IVAL, i, ADDRESS *, ap){ if (ap != NIL_ADDRESS) { if (!isanyreg (ap)) FATAL ((__FILE__, "g_uimmed", "immed-to-memory")); } if ((i >= 0 && i <= 0xFFFFL) || (opt_const_in_ram != OPT_NO)) { g_code (op, OP_INT, mk_uimmed (i), ap); } else { /* bigger constants we must build by hand */ /* in future it could be solved through storing constants */ /* in datasegment and fetching them from there */ ADDRESS *ap1 = temporary_register (F_XREG); IVAL low = (IVAL) ((UVAL) i & 0xFFFFL); IVAL high = (IVAL) ((UVAL) i >> 16); g_code (op_ldi, OP_INT, mk_immed (high), ap1); if (high != 0) { g_code (op_lsh, OP_INT, mk_immed (16), ap1); } if (low != 0) { g_code (op_or, OP_INT, mk_uimmed (low), ap1); } g_code (op, OP_INT, ap1, ap); freeop (ap1); }}/*----------------------------------------------------------------------------*//* * generate code to evaluate an index node and return the addressing * mode of the result. */static ADDRESS *g_index P1 (const EXPR *, ep){ ADDRESS *ap1, *ap2; EXPR *ep0 = ep->v.p[0]; EXPR *ep1 = ep->v.p[1]; AMODE mode; /* * Try and ensure that we evaluate address registers first .... * this leads to better code. */ switch (ep->nodetype) { case en_add: if (ep1->nodetype == en_register && is_address_register (ep1->v.r)) { ep0 = ep->v.p[1]; ep1 = ep->v.p[0]; } mode = am_indx2; break; case en_sub: mode = am_indxs; break; default: FATAL ((__FILE__, "g_index", "illegal nodetype %d ", ep->nodetype)); } if (ep1->nodetype == en_register && ep0->nodetype == en_register) { if (is_address_register (ep0->v.r) || (ep->nodetype == en_sub)) { /* first node is address register */ ap1 = g_expr (ep0, F_AREG); ap1 = copy_addr (ap1, mode); ap2 = g_expr (ep1, F_IREG); ap1->sreg = ap2->preg; ap1->deep = ap2->deep; ap1->u.offset = mk_const (0L); return ap1; } else if (is_address_register (ep1->v.r) && (ep->nodetype == en_add)) { /* second node is address register */ ap1 = g_expr (ep1, F_AREG); ap1 = copy_addr (ap1, am_indx2); /* (ARx,IRx) */ ap2 = g_expr (ep0, F_IREG); ap1->sreg = ap2->preg; ap1->deep = ap2->deep; ap1->u.offset = mk_const (0L); return ap1; } } /* * The general case (no register) */ ap1 = g_expr (ep0, (ep->nodetype == en_add) ? (FLAGS) (F_AREG | F_IMMED) : F_AREG); switch (ap1->mode) { case am_areg: ap2 = g_expr (ep1, (FLAGS) (F_IREG | F_IMMED)); validate (ap1); break; case am_immed: if (ep->nodetype == en_sub) { FATAL ((__FILE__, "g_index", "illegal adressmodee")); } ap2 = ap1; ap1 = g_expr (ep1, (FLAGS) (F_AREG | F_IMMED)); validate (ap2); break; default: CANNOT_REACH_HERE (); } /* * possible combinations: * * F_IMMED +/- F_IMMED * F_AREG +/- F_IMMED * F_AREG +/- F_IREG */ if (ap1->mode == am_areg) { /* * watch out for: * register(addr) + index_register * register(addr) + data_register */ if (!is_temporary_register (ap1->preg)) { /* ap1 = tempref address register */ ap1 = copy_addr (ap1, ap1->mode); switch (ap2->mode) { case am_ireg: /* 0(ARx,IRy) */ ap1->mode = mode; ap1->sreg = ap2->preg; ap1->deep = ap2->deep; ap1->u.offset = mk_const (0L); return ap1; case am_immed: if (!is_offset (ap2->u.offset)) /* we want to add to ap1 later... */ /* so copy it in scratchregister */ ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), OP_INT); break; default: break; }/* needs some changes in the registermanagement before this can be done *//* we cannot correctly restore second temp if it has been pushed *//* (we have only one depth-information per ap and so can only keep *//* of one tempregister */#if 0 error, not suported now} else { /* ap1 is temporaryregister */ switch (ap2->mode) { case am_ireg: /* 0(ARx,IRy) */ ap1 = copy_addr (ap1, ap1->mode); ap1->mode = am_indx2; ap1->sreg = ap2->preg; ap1->u.offset = mk_const (0L); return ap1; default: break; }#endif } } if (ap2->mode == am_immed) { if (ap1->mode == am_immed) { ap1 = copy_addr (ap1, am_direct); if (ep->nodetype == en_add) { ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset); } else { ap1->u.offset = mk_node (en_sub, ap1->u.offset, ap2->u.offset, tp_void); } return ap1; } if (is_offset (ap2->u.offset)) { ap1 = mk_legal (ap1, F_AREG, OP_INT); ap1 = copy_addr (ap1, am_indx); if (ep->nodetype == en_add) { ap1->u.offset = ap2->u.offset; } else { ap1->u.offset = mk_const (-ap2->u.offset->v.i); } return ap1; } } /* just to be sure, ap1 should allready be volatile here... */ if (!is_temporary_register (ap1->preg)) { /* ap1 is not volatile ... */ ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), OP_INT); } if (ep->nodetype == en_add) { g_code (op_addi, OP_INT, ap2, ap1); /* add left to address reg */ } else { g_code (op_subi, OP_INT, ap2, ap1); /* sub left to address reg */ } ap1 = copy_addr (ap1, am_ind); freeop (ap2); /* release any temps in ap2 */ return ap1; /* return indirect */}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P3 (const EXPR *, ep, TYP *, tp, FLAGS, flags){ ADDRESS *ap1; /* * If a reference to a struct/union is required, return a pointer to the * struct instead */ if (is_structure_type (tp) || is_array_assignment (tp)) { return g_expr (ep, F_IALL); } switch (ep->nodetype) {#ifdef DEBUG case en_sub:#endif case en_add: return g_index (ep); case en_autocon: if (ep->v.i >= -255L && ep->v.i < 255L) { ap1 = mk_indirect (frameptr, mk_const (ep->v.i)); } else { ap1 = address_register (); g_immed (op_ldi, ep->v.i, ap1); g_code (op_addi, OP_INT, mk_reg (frameptr), ap1); ap1 = copy_addr (ap1, am_ind); } return ap1; case en_ainc: /* 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -