📄 genc30.c
字号:
} if ((floatmask & MEMBER (reg)) != 0) { g_code (op_pushfnopeep, OP_FLOAT, mk_reg (reg), NIL_ADDRESS); } }}/* * pop all registers in the masks from the stack. */static void pop_registers P2 (REGMASK, mask, REGMASK, floatmask){ REG reg; for (reg = REG_R0; reg <= MAX_REG; reg++) { /* Check which registers are set in mask */ if ((floatmask & MEMBER (reg)) != 0) { g_code (op_popf, OP_FLOAT, NIL_ADDRESS, mk_reg (reg)); } if ((mask & MEMBER (reg)) != 0) { g_code (op_pop, OP_INT, NIL_ADDRESS, mk_reg (reg)); } }}/* * reads all register in the mask from the stack * this version does not use pop, but indeed address based on framepointer * and offset of the pushed registers from framepointer * generates in some cases faster code than poped version * since sp must not be set correctly as in the pop-variant */static void pop_fast_registers P3 (REGMASK, mask, REGMASK, floatmask, IVAL, offset){ REG reg; ADDRESS *ap; for (reg = REG_R0; reg <= MAX_REG; reg++) { /* Check which registers are set in mask */ if ((floatmask & MEMBER (reg)) != 0) { ap = mk_amode (am_indx); ap->preg = frameptr; /* frame pointer */ ap->u.offset = mk_const (offset--); g_code (op_popldf, OP_FLOAT, ap, mk_reg (reg)); } if ((mask & MEMBER (reg)) != 0) { ap = mk_amode (am_indx); ap->preg = frameptr; /* frame pointer */ ap->u.offset = mk_const (offset--); g_code (op_popldi, OP_INT, ap, mk_reg (reg)); } }}/* * make a direct reference to a node. */static ADDRESS *mk_immediatelabel P1 (EXPR *, ep){ return mk_expr (am_immed, ep);}/* * make an indirect reference to a node */static ADDRESS *mk_indirect P2 (REG, reg, EXPR *, ep){ ADDRESS *ap; ap = mk_expr (am_indx, ep); ap->preg = reg; return ap;}#ifdef FLOAT_SUPPORT/* * make a node to reference an immediate value f. */static ADDRESS *mk_immedfloat P1 (RVAL, f){ ADDRESS *ap; ap = mk_amode (am_immed); ap->u.offset = mk_fcon (&f, tp_double); return ap;}#endif /* FLOAT_SUPPORT */static void allocate_blockrepeat_registers (void){ interrupt_restore_mask |= MEMBER (REG_RC) | MEMBER (REG_RS) | MEMBER (REG_RE);}/* * Generate a label which points to an integer constant. This routine * ensures that only one copy of the constant is generated. */static ADDRESS *mk_ilabel P1 (const EXPR *, ep){ ITREE *p, *q; int local_global = global_flag; LABEL lab; EXPRTYPE type; static ITREE *iitree = NULL; /* Tree for integer constants */ static ITREE *ilabtree = NULL; /* Tree for label constants */ static ITREE *inatree = NULL; /* Tree for na constants */ static ITREE *iexprtree = NULL; /* Tree for expr constants */ lab = nextlabel++; type = ep->nodetype; if (tst_iconst (ep)) { type = en_icon; /* *FATAL((__FILE__,"mk_ilabel", "icon not supportet now")); */ } switch (type) { case en_icon: p = iitree; break; case en_nacon: p = inatree; break; case en_labcon: p = ilabtree; break; case en_add: case en_sub: case en_cast: case en_uminus: p = iexprtree; break; default: FATAL ((__FILE__, "mk_ilabel", "illegal nodetype %d", type)); } /* in the moment we do not try to build a tree */ for (q = p; p; p = p->more) { if (is_equalnode (p->value, ep)) { return mk_label (p->label); } q = p; } global_flag = 1; p = (ITREE *) xalloc ((int) sizeof (ITREE)); p->label = lab; p->value = copy_iexpr (ep); p->less = p->more = NULL; global_flag = local_global; if (q == NULL) { switch (type) { case en_icon: iitree = p; break; case en_nacon: inatree = p; break; case en_labcon: ilabtree = p; break; case en_add: case en_sub: case en_cast: case en_uminus: iexprtree = p; break; default: break; } } /*else if (q->value < val) */ /* q->less = p; */ else q->more = p; put_kseg (alignment_of_type (tp_double)); put_label (lab); put_pointer (ep); return mk_label (lab);}/*****************************************************************************/static EXPR *copy_iexpr P1 (const EXPR *, ep){ EXPR *newep; if (ep == NIL_EXPR) return NIL_EXPR; newep = copynode (ep); switch (ep->nodetype) { case en_icon: case en_autocon: case en_labcon: case en_nacon: return newep; case en_add: case en_sub: newep->v.p[0] = copy_iexpr (ep->v.p[0]); newep->v.p[1] = copy_iexpr (ep->v.p[1]); return newep; case en_cast: case en_uminus: newep->v.p[0] = copy_iexpr (ep->v.p[0]); return newep; default: FATAL ((__FILE__, "copy_iexpr", "illegal nodetype %d", ep->nodetype)); return NIL_EXPR; }}/**************************************************************************************//* * return true if the node passed can be used as offset in addressgeneration. */static BOOL is_offset P1 (const EXPR *, ep){ return is_icon (ep) && (ep->v.i >= -255L && ep->v.i <= 255L);}/* * return true if the node passed can be generated as a short offset. */static BOOL is_short P1 (const EXPR *, ep){ return is_icon (ep) && (ep->v.i >= -32768L && ep->v.i <= 32767L);}/* * return true if the node passed can be generated as a unsigned short * offset. */static BOOL is_ushort P1 (const EXPR *, ep){ return is_icon (ep) && (ep->v.i >= 0L && ep->v.i <= 0xFFFFL);}/* * delivers true, if node can ba evaluated to an addressingmode * suitable for an 3-operand instruction * (register, *an, *+an(1), *-an(1), *-an(irm), *+an(irm)) * ^^^^^^^^^^^^^^^^^^^^-not included yet * * Autoincrements are currently not accepted for 3-op-instructions * ->could give troubles when both operands are the same address- * registers (*arn++(1), *arm++(1), r) arn == arm * * * Attention!! do not forget to change makro is_op3_violated() * if you add the auto-/pre-incre-/decre-ments */static BOOL is_op3_possible (EXPR *node){ /* Look for register */ if (node->nodetype == en_register) { return TRUE; } /* look for autocons *ar7+(1) or *ar7-(1) */ if ((node->nodetype == en_autocon) && (node->v.i >= -1) && (node->v.i <= 1)) { return TRUE; } if (node->nodetype == en_ref) { switch (node->v.p[0]->nodetype) { /* Look for *arn */ case en_register: if (is_address_register (node->v.p[0]->v.r)) { return TRUE; } break; /* look for indexnode *arn+(1) or *arn-(1) */ case en_add: if ((node->v.p[0]->v.p[0]->nodetype == en_register) && (is_address_register (node->v.p[0]->v.p[0]->v.r)) && is_icon (node->v.p[0]->v.p[1]) && (node->v.p[0]->v.p[1]->v.i >= -1) && (node->v.p[0]->v.p[1]->v.i <= 1)) { return TRUE; } /* look for indexnode *arn+(1) or *arn-(1), nodes of add swapped */ if ((node->v.p[0]->v.p[1]->nodetype == en_register) && (is_address_register (node->v.p[0]->v.p[1]->v.r)) && is_icon (node->v.p[0]->v.p[0]) && (node->v.p[0]->v.p[0]->v.i >= -1) && (node->v.p[0]->v.p[0]->v.i <= 1)) { return TRUE; } break;#if 0 /* currently not supported */ case en_ainc: case en_adec: /* look for autoincre/decrement *arn++(1) / *arn--(1) */ if (ep->v.p[1]->v.i == 1 && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r)) { return TRUE; } break; case en_asadd: case en_assub: /* look for preincre/decrement *++arn(1) / *--arn(1) */ if (is_icon (ep->v.p[1]) && ep->v.p[1]->v.i == 1 && ep->v.p[0]->nodetype == en_register && is_address_register (ep->v.p[0]->v.r)) { /* *++An(1) */ return TRUE; } break;#endif default: break; } } return FALSE;}#ifdef FLOAT_SUPPORTBOOL is_short_float (const RVAL f, BTYPE tp){ int i; RVAL intpart; if ((f > MAX_POS_SHORT_FLOAT) || (f < MIN_NEG_SHORT_FLOAT)) return (FALSE); if (f == 0.0) return (TRUE); if ((f > MAX_NEG_SHORT_FLOAT) && (f < MIN_POS_SHORT_FLOAT)) return (FALSE); /* * perhaps here should follow a check for the precision * sinc shortfloats only offers a precision of 11 Mantissabits * and sometimes we dont want to loose precision of constants * but in the moment I dont know how to do this check * */ /* We differ now in precission between float and (long-)double */ /* we have 3 options (opt_shortfloat): * 0 we use shortfloats only if we are absolutely sure they * wont bring any loss in precision * * 1 floats are allways represented in shortform if they are in * range, double and longdouble only if there is no loss in * precision * * 3 floats, doubles ans longdoubles are allways represented * in shortform if they are in range, there may be a loss in * precision */ if ((tp == bt_float) && (opt_shortfloat > 0)) return (TRUE); if (opt_shortfloat > 1) return (TRUE); /* cut away the fractional part */ i = (int) f; intpart = (RVAL) i; /* we use immediates for long and double only for * floats with no fractional part, then we can * be sure we dont loss any precission * It's not the best solution, but for now it has to do * it would be better to lock if the number has not more than * 12 significant mantissabit and if the exponent is between * +7 and -7 (base 2, of course), then the number can be represented * in the short form without any losses */ if (intpart == f) return (TRUE);#if 0 /* New way to find out if a number can be represented with 11 * mantissabits, needs still to be tested */ /* shift mantissa, until first mantissabit has reached position * of bit 11 in an integer */ if (f > 0.0) { while (f < ((double) (1UL << 11))) { f = f + f; } } else { while (f > ((double) (-(1UL << 11)))) { f = f + f; } } /* cut away the fractional part */ i = (int) f; intpart = i; /* if there are no bits used in the fractionalpart we * may use the short integerformat */ if (intpart == f) return (TRUE);#endif return (FALSE);}#endif /* FLOAT_SUPPORT *//* * tests if it is a labelfree constant node, that means either en_icon, * or sums or differences of such nodes */static BOOL tst_iconst P1 (const EXPR *, ep){ switch (ep->nodetype) { case en_icon: return TRUE; case en_add: case en_sub: return tst_iconst (ep->v.p[0]) && tst_iconst (ep->v.p[1]);#ifndef RELOC_BUG case en_cast:#endif case en_uminus: return tst_iconst (ep->v.p[0]); default: break; } return FALSE;}/* * Checks, if the given nacon-name is a valid * trapname, eg is __trap_00 to __trap_31. * also valid names are __trap_nn_xxxx, where * xxx is any valid sequence of identifiercharacters. * if so, returns an address containing the immediatevalue * of the trapnumber, otherwise returns NIL_ADDRESS * is used to convert functionscalls named __trap_nn to * trapu-opcodes, simplifies interface to operating- * systems. */static ADDRESS *check_trap P1 (const EXPR *, ep){ static const CHAR *trapname = (const CHAR *) "__trap_nn"; const CHAR *p, *q; IVAL i; /* * Check if trapp option was enabled */ if (opt_traps == OPT_NO) { return NIL_ADDRESS; } if (ep->nodetype == en_nacon) { p = ep->v.str; q = trapname; while (*q != 'n') { if (*q++ != *p++) { return NIL_ADDRESS; } } if ((*p > '3') || (*p < '0')) { return NIL_ADDRESS; } i = (IVAL) (10 * ((int) *p++ - '0')); if ((*p > '9') || (*p < '0')) { return NIL_ADDRESS; } i += (IVAL) ((int) *p++ - '0'); /* Check if number is in range and for end of string */ if ((i > 31) || ((*p != 0) && (*p != '_'))) { return NIL_ADDRESS; } return (mk_immed (i)); } return NIL_ADDRESS;}/* * mk_legal will coerce the addressing mode in ap1 into a mode that is * satisfactory for the flag word. */static ADDRESS *mk_legal P3 (ADDRESS *, ap, FLAGS, flags, ITYPE, size){ ADDRESS *ap2, *ap3; OPCODE OpSto, OpLd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -