📄 dsp16xx.c
字号:
if (to == Y_REG || to == P_REG) return 4; else return 2; } if (to == A0H_REG || to == A0L_REG || to == A0_REG || to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG || to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS) { return 2; }#if 0 if (from == YBASE_VIRT_REGS) { if (to == X_REG || to == YH_REG || to == YL_REG || to == Y_REG || to == PL_REG || to == PH_REG || to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS || to == Y_OR_P_REGS) { return 2; } else return 4; } if (to == YBASE_VIRT_REGS) { if (from == X_REG || from == YH_REG || from == YL_REG || from == Y_REG || from == PL_REG || from == PH_REG || from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS || from == Y_OR_P_REGS) { return 2; } else return 4; }#endif return 4;}/* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines in some cases it is preferable to use a more restrictive class. Also, we must ensure that a PLUS is reloaded either into an accumulator or an address register. */enum reg_classpreferred_reload_class (x, class) rtx x; enum reg_class class;{ /* The ybase registers cannot have constants copied directly to them. */ if (CONSTANT_P (x)) { if (class == ALL_REGS) return NON_YBASE_REGS; } if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW (REGNO(x))) return YBASE_ELIGIBLE_REGS; if (GET_CODE (x) == PLUS) { if (GET_MODE (x) == QImode && REG_P (XEXP (x,0)) && (XEXP (x,0) == frame_pointer_rtx || XEXP (x,0) == stack_pointer_rtx) && (GET_CODE (XEXP (x,1)) == CONST_INT)) { if (class == ACCUM_HIGH_REGS) return class; if (reg_class_subset_p (ACCUM_HIGH_REGS, class)) return ACCUM_HIGH_REGS; /* We will use accumulator 'a1l' for reloading a PLUS. We can only use one accumulator because 'reload_inqi' only allows one alternative to be used. */ else if (class == ACCUM_LOW_REGS) return A1L_REG; else if (class == A0L_REG) return NO_REGS; else return class; } if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS) return Y_ADDR_REGS; else return class; } else if (GET_CODE (x) == MEM) { if (class == ALL_REGS) {#if 0 if (GET_MODE(x) == HImode) return NO_ACCUM_NON_YBASE_REGS; else#endif return NON_YBASE_REGS; } else return class; } else return class;} /* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */enum reg_classsecondary_reload_class (class, mode, in) enum reg_class class; enum machine_mode mode; rtx in;{ int regno = -1; if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) regno = true_regnum (in); if (class == ACCUM_HIGH_REGS || class == ACCUM_LOW_REGS || class == A1L_REG || class == A0L_REG || class == A1H_REG || class == A0H_REG) { if (GET_CODE (in) == PLUS && mode == QImode) { rtx addr0 = XEXP (in, 0); rtx addr1 = XEXP (in, 1); /* If we are reloading a plus (reg:QI) (reg:QI) we need an additional register. */ if (REG_P (addr0) && REG_P (addr1)) return NO_REGS; } } /* We can place anything into ACCUM_REGS and can put ACCUM_REGS into anything. */ if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS || class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG || class == A1H_REG || class == A1_REG) || (regno >= REG_A0 && regno < REG_A1L + 1)) return NO_REGS; /* We can copy the ybase registers into: r0-r3, a0-a1, y, p, & x or the union of any of these. */ if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno)) { switch ((int) class) { case (int) X_REG: case (int) X_OR_ACCUM_LOW_REGS: case (int) X_OR_ACCUM_REGS: case (int) YH_REG: case (int) YH_OR_ACCUM_HIGH_REGS: case (int) X_OR_YH_REGS: case (int) YL_REG: case (int) YL_OR_ACCUM_LOW_REGS: case (int) X_OR_Y_REGS: case (int) X_OR_YL_REGS: case (int) Y_REG: case (int) ACCUM_OR_Y_REGS: case (int) PH_REG: case (int) X_OR_PH_REGS: case (int) PL_REG: case (int) PL_OR_ACCUM_LOW_REGS: case (int) X_OR_PL_REGS: case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: case (int) P_REG: case (int) ACCUM_OR_P_REGS: case (int) YL_OR_P_REGS: case (int) ACCUM_LOW_OR_YL_OR_P_REGS: case (int) Y_OR_P_REGS: case (int) ACCUM_Y_OR_P_REGS: case (int) Y_ADDR_REGS: case (int) ACCUM_LOW_OR_Y_ADDR_REGS: case (int) ACCUM_OR_Y_ADDR_REGS: case (int) X_OR_Y_ADDR_REGS: case (int) Y_OR_Y_ADDR_REGS: case (int) P_OR_Y_ADDR_REGS: case (int) YBASE_ELIGIBLE_REGS: return NO_REGS; default: return ACCUM_HIGH_REGS; } } /* We can copy r0-r3, a0-a1, y, & p directly to the ybase registers. In addition we can use any of the ybase virtual registers as the secondary reload registers when copying between any of these registers. */ if (!TARGET_RESERVE_YBASE && regno != -1) { switch (regno) { case REG_A0: case REG_A0L: case REG_A1: case REG_A1L: case REG_X: case REG_Y: case REG_YL: case REG_PROD: case REG_PRODL: case REG_R0: case REG_R1: case REG_R2: case REG_R3: if (class == YBASE_VIRT_REGS) return NO_REGS; else { switch ((int) class) { case (int) X_REG: case (int) X_OR_ACCUM_LOW_REGS: case (int) X_OR_ACCUM_REGS: case (int) YH_REG: case (int) YH_OR_ACCUM_HIGH_REGS: case (int) X_OR_YH_REGS: case (int) YL_REG: case (int) YL_OR_ACCUM_LOW_REGS: case (int) X_OR_Y_REGS: case (int) X_OR_YL_REGS: case (int) Y_REG: case (int) ACCUM_OR_Y_REGS: case (int) PH_REG: case (int) X_OR_PH_REGS: case (int) PL_REG: case (int) PL_OR_ACCUM_LOW_REGS: case (int) X_OR_PL_REGS: case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: case (int) P_REG: case (int) ACCUM_OR_P_REGS: case (int) YL_OR_P_REGS: case (int) ACCUM_LOW_OR_YL_OR_P_REGS: case (int) Y_OR_P_REGS: case (int) ACCUM_Y_OR_P_REGS: case (int) Y_ADDR_REGS: case (int) ACCUM_LOW_OR_Y_ADDR_REGS: case (int) ACCUM_OR_Y_ADDR_REGS: case (int) X_OR_Y_ADDR_REGS: case (int) Y_OR_Y_ADDR_REGS: case (int) P_OR_Y_ADDR_REGS: case (int) YBASE_ELIGIBLE_REGS: return YBASE_VIRT_REGS; default: break; } } } } /* Memory or constants can be moved from or to any register except the ybase virtual registers */ if (regno == -1 && GET_CODE(in) != PLUS) { if (class == YBASE_VIRT_REGS) return NON_YBASE_REGS; else return NO_REGS; } if (GET_CODE (in) == PLUS && mode == QImode) { rtx addr0 = XEXP (in, 0); rtx addr1 = XEXP (in, 1); /* If we are reloading a plus (reg:QI) (reg:QI) we need a low accumulator, not a high one. */ if (REG_P (addr0) && REG_P (addr1)) return ACCUM_LOW_REGS; }#if 0 if (REG_P(in)) return ACCUM_REGS;#endif /* Otherwise, we need a high accumulator(s). */ return ACCUM_HIGH_REGS;}intsymbolic_address_operand (op, mode)rtx op;enum machine_mode mode;{ return (symbolic_address_p (op));}int symbolic_address_p (op)rtx op;{ switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: return 1; case CONST: op = XEXP (op, 0); return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT && INTVAL (XEXP (op,1)) < 0x20); default: return 0; }}/* For a Y address space operand we allow only *rn, *rn++, *rn--. This routine only recognizes *rn, the '<>' constraints recognize *rn++, *rn-- */intY_address_operand (op, mode)rtx op;enum machine_mode mode;{ return (memory_address_p (mode, op) && !symbolic_address_p (op));} intsp_operand (op, mode)rtx op;enum machine_mode mode;{ return (GET_CODE (op) == PLUS && (XEXP (op, 0) == stack_pointer_rtx || XEXP (op, 0) == frame_pointer_rtx) && GET_CODE (XEXP (op,1)) == CONST_INT);}intsp_operand2 (op, mode)rtx op;enum machine_mode mode;{ if ((GET_CODE (op) == PLUS && (XEXP (op, 0) == stack_pointer_rtx || XEXP (op, 0) == frame_pointer_rtx) && (REG_P (XEXP (op,1)) && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) return 1; else if ((GET_CODE (op) == PLUS && (XEXP (op, 1) == stack_pointer_rtx || XEXP (op, 1) == frame_pointer_rtx) && (REG_P (XEXP (op,0)) && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) return 1; else return 0;}intnonmemory_arith_operand (op, mode)rtx op;enum machine_mode mode;{ return (immediate_operand (op, mode) || arith_reg_operand (op, mode));}intarith_reg_operand (op, mode)rtx op;enum machine_mode mode;{ return (register_operand (op, mode) && (GET_CODE (op) != REG || REGNO (op) >= FIRST_PSEUDO_REGISTER || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op))) && REGNO (op) != FRAME_POINTER_REGNUM)));}intcall_address_operand (op, mode)rtx op;enum machine_mode mode;{ if (symbolic_address_p (op) || REG_P(op)) { return 1; } return 0;}intdsp16xx_comparison_operator (op, mode) register rtx op; enum machine_mode mode;{ return ((mode == VOIDmode || GET_MODE (op) == mode) && GET_RTX_CLASS (GET_CODE (op)) == '<' && (GET_CODE(op) != GE && GET_CODE (op) != LT && GET_CODE (op) != GEU && GET_CODE (op) != LTU));}voidnotice_update_cc(exp)rtx exp;{ if (GET_CODE (exp) == SET) { /* Jumps do not alter the cc's. */ if (SET_DEST (exp) == pc_rtx) return; /* Moving register or memory into a register: it doesn't alter the cc's, but it might invalidate the RTX's which we remember the cc's came from. (Note that moving a constant 0 or 1 MAY set the cc's). */ if (REG_P (SET_DEST (exp)) && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM)) { if (cc_status.value1 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) cc_status.value1 = 0; if (cc_status.value2 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; return; } /* Moving register into memory doesn't alter the cc's. It may invalidate the RTX's which we remember the cc's came from. */ if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp))) { if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) cc_status.value1 = 0; if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) cc_status.value2 = 0; return; } /* Function calls clobber the cc's. */ else if (GET_CODE (SET_SRC (exp)) == CALL) { CC_STATUS_INIT; return; } /* Tests and compares set the cc's in predictable ways. */ else if (SET_DEST (exp) == cc0_rtx) { CC_STATUS_INIT; cc_status.value1 = SET_SRC (exp); return; } /* Certain instructions effect the condition codes. */ else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT) switch( GET_CODE (SET_SRC (exp)) ) { case PLUS: case MINUS: if (REG_P (SET_DEST (exp))) { /* Address registers don't set the condition codes */ if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp)))) { CC_STATUS_INIT; break; } } case ASHIFTRT: case LSHIFTRT: case ASHIFT: case AND: case IOR: case XOR: case MULT: case NEG: case NOT: cc_status.value1 = SET_SRC (exp); cc_status.value2 = SET_DEST (exp); break; default: CC_STATUS_INIT; } else { CC_STATUS_INIT; } } else if (GET_CODE (exp) == PARALLEL && GET_CODE (XVECEXP (exp, 0, 0)) == SET) { if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) return; if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) { CC_STATUS_INIT; cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); return; } CC_STATUS_INIT; } else { CC_STATUS_INIT; }}intdsp16xx_makes_calls (){ rtx insn; for (insn = get_insns (); insn; insn = next_insn (insn)) if (GET_CODE (insn) == CALL_INSN) return (1); return 0;}long compute_frame_size (size)int size;{ long total_size; long var_size; long args_size; long extra_size; long reg_size; reg_size = 0; extra_size = 0; var_size = size; args_size = current_function_outgoing_args_size; reg_size = reg_save_size (); total_size = var_size + args_size + extra_size + reg_size; /* Save other computed information. */ current_frame_info.total_size = total_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -