📄 v850.c
字号:
}/* Return true if OP is a valid short EP memory reference */intep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load){ rtx addr, op0, op1; int max_offset; int mask; if (GET_CODE (op) != MEM) return FALSE; max_offset = ep_memory_offset (mode, unsigned_load); mask = GET_MODE_SIZE (mode) - 1; addr = XEXP (op, 0); if (GET_CODE (addr) == CONST) addr = XEXP (addr, 0); switch (GET_CODE (addr)) { default: break; case SYMBOL_REF: return SYMBOL_REF_TDA_P (addr); case REG: return REGNO (addr) == EP_REGNUM; case PLUS: op0 = XEXP (addr, 0); op1 = XEXP (addr, 1); if (GET_CODE (op1) == CONST_INT && INTVAL (op1) < max_offset && INTVAL (op1) >= 0 && (INTVAL (op1) & mask) == 0) { if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM) return TRUE; if (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_TDA_P (op0)) return TRUE; } break; } return FALSE;}/* Return true if OP is either a register or 0 */intreg_or_0_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT) return INTVAL (op) == 0; else if (GET_CODE (op) == CONST_DOUBLE) return CONST_DOUBLE_OK_FOR_G (op); else return register_operand (op, mode);}/* Return true if OP is either a register or a signed five bit integer */intreg_or_int5_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT) return CONST_OK_FOR_J (INTVAL (op)); else return register_operand (op, mode);}/* Return true if OP is either a register or a signed nine bit integer. */intreg_or_int9_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT) return CONST_OK_FOR_O (INTVAL (op)); return register_operand (op, mode);}/* Return true if OP is either a register or a const integer. */intreg_or_const_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT) return TRUE; return register_operand (op, mode);}/* Return true if OP is a valid call operand. */intcall_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ /* Only registers are valid call operands if TARGET_LONG_CALLS. */ if (TARGET_LONG_CALLS) return GET_CODE (op) == REG; return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);}intspecial_symbolref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1)))) op = XEXP (XEXP (op, 0), 0); if (GET_CODE (op) == SYMBOL_REF) return (SYMBOL_REF_FLAGS (op) & (SYMBOL_FLAG_ZDA | SYMBOL_FLAG_TDA | SYMBOL_FLAG_SDA)) != 0; return FALSE;}intmovsi_source_operand (rtx op, enum machine_mode mode){ /* Some constants, as well as symbolic operands must be done with HIGH & LO_SUM patterns. */ if (CONSTANT_P (op) && GET_CODE (op) != HIGH && !(GET_CODE (op) == CONST_INT && (CONST_OK_FOR_J (INTVAL (op)) || CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_L (INTVAL (op))))) return special_symbolref_operand (op, mode); else return general_operand (op, mode);}intpower_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ if (GET_CODE (op) != CONST_INT) return 0; if (exact_log2 (INTVAL (op)) == -1) return 0; return 1;}intnot_power_of_two_operand (rtx op, enum machine_mode mode){ unsigned int mask; if (mode == QImode) mask = 0xff; else if (mode == HImode) mask = 0xffff; else if (mode == SImode) mask = 0xffffffff; else return 0; if (GET_CODE (op) != CONST_INT) return 0; if (exact_log2 (~INTVAL (op) & mask) == -1) return 0; return 1;}/* Substitute memory references involving a pointer, to use the ep pointer, taking care to save and preserve the ep. */static voidsubstitute_ep_register (rtx first_insn, rtx last_insn, int uses, int regno, rtx * p_r1, rtx * p_ep){ rtx reg = gen_rtx_REG (Pmode, regno); rtx insn; if (!*p_r1) { regs_ever_live[1] = 1; *p_r1 = gen_rtx_REG (Pmode, 1); *p_ep = gen_rtx_REG (Pmode, 30); } if (TARGET_DEBUG) fprintf (stderr, "\Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n", 2 * (uses - 3), uses, reg_names[regno], IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), INSN_UID (first_insn), INSN_UID (last_insn)); if (GET_CODE (first_insn) == NOTE) first_insn = next_nonnote_insn (first_insn); last_insn = next_nonnote_insn (last_insn); for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == INSN) { rtx pattern = single_set (insn); /* Replace the memory references. */ if (pattern) { rtx *p_mem; /* Memory operands are signed by default. */ int unsignedp = FALSE; if (GET_CODE (SET_DEST (pattern)) == MEM && GET_CODE (SET_SRC (pattern)) == MEM) p_mem = (rtx *)0; else if (GET_CODE (SET_DEST (pattern)) == MEM) p_mem = &SET_DEST (pattern); else if (GET_CODE (SET_SRC (pattern)) == MEM) p_mem = &SET_SRC (pattern); else if (GET_CODE (SET_SRC (pattern)) == SIGN_EXTEND && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM) p_mem = &XEXP (SET_SRC (pattern), 0); else if (GET_CODE (SET_SRC (pattern)) == ZERO_EXTEND && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM) { p_mem = &XEXP (SET_SRC (pattern), 0); unsignedp = TRUE; } else p_mem = (rtx *)0; if (p_mem) { rtx addr = XEXP (*p_mem, 0); if (GET_CODE (addr) == REG && REGNO (addr) == (unsigned) regno) *p_mem = change_address (*p_mem, VOIDmode, *p_ep); else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 0)) == REG && REGNO (XEXP (addr, 0)) == (unsigned) regno && GET_CODE (XEXP (addr, 1)) == CONST_INT && ((INTVAL (XEXP (addr, 1))) < ep_memory_offset (GET_MODE (*p_mem), unsignedp)) && ((INTVAL (XEXP (addr, 1))) >= 0)) *p_mem = change_address (*p_mem, VOIDmode, gen_rtx_PLUS (Pmode, *p_ep, XEXP (addr, 1))); } } } } /* Optimize back to back cases of ep <- r1 & r1 <- ep. */ insn = prev_nonnote_insn (first_insn); if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET && SET_DEST (PATTERN (insn)) == *p_ep && SET_SRC (PATTERN (insn)) == *p_r1) delete_insn (insn); else emit_insn_before (gen_rtx_SET (Pmode, *p_r1, *p_ep), first_insn); emit_insn_before (gen_rtx_SET (Pmode, *p_ep, reg), first_insn); emit_insn_before (gen_rtx_SET (Pmode, *p_ep, *p_r1), last_insn);}/* TARGET_MACHINE_DEPENDENT_REORG. On the 850, we use it to implement the -mep mode to copy heavily used pointers to ep to use the implicit addressing. */static voidv850_reorg (void){ struct { int uses; rtx first_insn; rtx last_insn; } regs[FIRST_PSEUDO_REGISTER]; int i; int use_ep = FALSE; rtx r1 = NULL_RTX; rtx ep = NULL_RTX; rtx insn; rtx pattern; /* If not ep mode, just return now. */ if (!TARGET_EP) return; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { regs[i].uses = 0; regs[i].first_insn = NULL_RTX; regs[i].last_insn = NULL_RTX; } for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) { switch (GET_CODE (insn)) { /* End of basic block */ default: if (!use_ep) { int max_uses = -1; int max_regno = -1; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { if (max_uses < regs[i].uses) { max_uses = regs[i].uses; max_regno = i; } } if (max_uses > 3) substitute_ep_register (regs[max_regno].first_insn, regs[max_regno].last_insn, max_uses, max_regno, &r1, &ep); } use_ep = FALSE; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { regs[i].uses = 0; regs[i].first_insn = NULL_RTX; regs[i].last_insn = NULL_RTX; } break; case NOTE: break; case INSN: pattern = single_set (insn); /* See if there are any memory references we can shorten */ if (pattern) { rtx src = SET_SRC (pattern); rtx dest = SET_DEST (pattern); rtx mem; /* Memory operands are signed by default. */ int unsignedp = FALSE; /* We might have (SUBREG (MEM)) here, so just get rid of the subregs to make this code simpler. */ if (GET_CODE (dest) == SUBREG && (GET_CODE (SUBREG_REG (dest)) == MEM || GET_CODE (SUBREG_REG (dest)) == REG)) alter_subreg (&dest); if (GET_CODE (src) == SUBREG && (GET_CODE (SUBREG_REG (src)) == MEM || GET_CODE (SUBREG_REG (src)) == REG)) alter_subreg (&src); if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM) mem = NULL_RTX; else if (GET_CODE (dest) == MEM) mem = dest; else if (GET_CODE (src) == MEM) mem = src; else if (GET_CODE (src) == SIGN_EXTEND && GET_CODE (XEXP (src, 0)) == MEM) mem = XEXP (src, 0); else if (GET_CODE (src) == ZERO_EXTEND && GET_CODE (XEXP (src, 0)) == MEM) { mem = XEXP (src, 0); unsignedp = TRUE; } else mem = NULL_RTX; if (mem && ep_memory_operand (mem, GET_MODE (mem), unsignedp)) use_ep = TRUE; else if (!use_ep && mem && GET_MODE_SIZE (GET_MODE (mem)) <= UNITS_PER_WORD) { rtx addr = XEXP (mem, 0); int regno = -1; int short_p; if (GET_CODE (addr) == REG) { short_p = TRUE; regno = REGNO (addr); } else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 0)) == REG && GET_CODE (XEXP (addr, 1)) == CONST_INT && ((INTVAL (XEXP (addr, 1))) < ep_memory_offset (GET_MODE (mem), unsignedp)) && ((INTVAL (XEXP (addr, 1))) >= 0)) { short_p = TRUE; regno = REGNO (XEXP (addr, 0)); } else short_p = FALSE; if (short_p) { regs[regno].uses++; regs[regno].last_insn = insn; if (!regs[regno].first_insn) regs[regno].first_insn = insn; } } /* Loading up a register in the basic block zaps any savings for the register */ if (GET_CODE (dest) == REG) { enum machine_mode mode = GET_MODE (dest); int regno; int endregno; regno = REGNO (dest); endregno = regno + HARD_REGNO_NREGS (regno, mode); if (!use_ep) { /* See if we can use the pointer before this modification. */ int max_uses = -1; int max_regno = -1; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { if (max_uses < regs[i].uses) { max_uses = regs[i].uses; max_regno = i; } } if (max_uses > 3 && max_regno >= regno && max_regno < endregno) { substitute_ep_register (regs[max_regno].first_insn, regs[max_regno].last_insn, max_uses, max_regno, &r1, &ep); /* Since we made a substitution, zap all remembered registers. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { regs[i].uses = 0; regs[i].first_insn = NULL_RTX; regs[i].last_insn = NULL_RTX; } } } for (i = regno; i < endregno; i++) { regs[i].uses = 0; regs[i].first_insn = NULL_RTX; regs[i].last_insn = NULL_RTX; } } } } }}/* # of registers saved by the interrupt handler. */#define INTERRUPT_FIXED_NUM 4/* # of bytes for registers saved by the interrupt handler. */#define INTERRUPT_FIXED_SAVE_SIZE (4 * INTERRUPT_FIXED_NUM)/* # of registers saved in register parameter area. */#define INTERRUPT_REGPARM_NUM 4/* # of words saved for other registers. */#define INTERRUPT_ALL_SAVE_NUM \ (30 - INTERRUPT_FIXED_NUM + INTERRUPT_REGPARM_NUM)#define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -