2011-10-11 Georg-Johann Lay <avr@gjlay.de>
+ * config/avr/avr-protos.h (avr_mode_code_base_reg_class): New prototype.
+ (avr_regno_mode_code_ok_for_base_p): New prototype.
+ * config/avr/avr.h (BASE_REG_CLASS): Remove.
+ (REGNO_OK_FOR_BASE_P): Remove.
+ (REG_OK_FOR_BASE_NOSTRICT_P): Remove.
+ (REG_OK_FOR_BASE_STRICT_P): Remove.
+ (MODE_CODE_BASE_REG_CLASS): New define.
+ (REGNO_MODE_CODE_OK_FOR_BASE_P): New define.
+ * config/avr/avr.c (avr_mode_code_base_reg_class): New function.
+ (avr_regno_mode_code_ok_for_base_p): New function.
+ (avr_reg_ok_for_addr_p): New static function.
+ (avr_legitimate_address_p): Use it. Beautify.
+
+2011-10-11 Georg-Johann Lay <avr@gjlay.de>
+
PR target/50447
* config/avr/avr.md (cc): Add out_plus attribute alternative.
(addsi3): Use it. Adapt avr_out_plus to new prototype. Use
extern RTX_CODE avr_normalize_condition (RTX_CODE condition);
extern void out_shift_with_cnt (const char *templ, rtx insn,
rtx operands[], int *len, int t_len);
+extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, RTX_CODE, RTX_CODE);
+extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, RTX_CODE, RTX_CODE);
extern rtx avr_incoming_return_addr_rtx (void);
extern rtx avr_legitimize_reload_address (rtx, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
#endif /* RTX_CODE */
}
+/* Helper function for `avr_legitimate_address_p'. */
+
+static inline bool
+avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED, int strict)
+{
+ return (REG_P (reg)
+ && (avr_regno_mode_code_ok_for_base_p (REGNO (reg),
+ QImode, MEM, UNKNOWN)
+ || (!strict
+ && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
+}
+
+
/* Return nonzero if X (an RTX) is a legitimate memory address on the target
machine for a memory operand of mode MODE. */
-bool
+static bool
avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
reg_class_t r = NO_REGS;
- if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
- : REG_OK_FOR_BASE_NOSTRICT_P (x)))
- r = POINTER_REGS;
+ if (REG_P (x)
+ && avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC, strict))
+ {
+ r = POINTER_REGS;
+ }
else if (CONSTANT_ADDRESS_P (x))
- r = ALL_REGS;
+ {
+ r = ALL_REGS;
+ }
else if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) >= 0)
+ && CONST_INT_P (XEXP (x, 1))
+ && INTVAL (XEXP (x, 1)) >= 0)
{
- int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
+ rtx reg = XEXP (x, 0);
+ bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
+
if (fit)
- {
- if (! strict
- || REGNO (XEXP (x,0)) == REG_X
- || REGNO (XEXP (x,0)) == REG_Y
- || REGNO (XEXP (x,0)) == REG_Z)
- r = BASE_POINTER_REGS;
- if (XEXP (x,0) == frame_pointer_rtx
- || XEXP (x,0) == arg_pointer_rtx)
- r = BASE_POINTER_REGS;
- }
- else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
- r = POINTER_Y_REGS;
+ {
+ if (! strict
+ || REGNO (reg) == REG_X
+ || REGNO (reg) == REG_Y
+ || REGNO (reg) == REG_Z)
+ {
+ r = BASE_POINTER_REGS;
+ }
+
+ if (reg == frame_pointer_rtx
+ || reg == arg_pointer_rtx)
+ {
+ r = BASE_POINTER_REGS;
+ }
+ }
+ else if (frame_pointer_needed && reg == frame_pointer_rtx)
+ {
+ r = POINTER_Y_REGS;
+ }
}
else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
&& REG_P (XEXP (x, 0))
- && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
- : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
+ && avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC, strict))
{
r = POINTER_REGS;
}
/* Attempts to replace X with a valid
memory address for an operand of mode MODE */
-rtx
+static rtx
avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
{
bool big_offset_p = false;
}
+/* Implement `MODE_CODE_BASE_REG_CLASS'. */
+
+reg_class_t
+avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code ATTRIBUTE_UNUSED,
+ RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+ return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
+}
+
+
+/* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
+
+bool
+avr_regno_mode_code_ok_for_base_p (int regno,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code ATTRIBUTE_UNUSED,
+ RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+ if (regno < FIRST_PSEUDO_REGISTER
+ && (regno == REG_X
+ || regno == REG_Y
+ || regno == REG_Z
+ || regno == ARG_POINTER_REGNUM))
+ {
+ return true;
+ }
+
+ if (reg_renumber)
+ {
+ regno = reg_renumber[regno];
+
+ if (regno == REG_X
+ || regno == REG_Y
+ || regno == REG_Z
+ || regno == ARG_POINTER_REGNUM)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
/* A helper for `output_reload_insisf' and `output_reload_inhi'. */
/* Set 32-bit register OP[0] to compile-time constant OP[1].
CLOBBER_REG is a QI clobber register or NULL_RTX.
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
-#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
+#define MODE_CODE_BASE_REG_CLASS(mode, outer_code, index_code) \
+ avr_mode_code_base_reg_class (mode, outer_code, index_code)
#define INDEX_REG_CLASS NO_REGS
-#define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER \
- && ((r) == REG_X \
- || (r) == REG_Y \
- || (r) == REG_Z \
- || (r) == ARG_POINTER_REGNUM)) \
- || (reg_renumber \
- && (reg_renumber[r] == REG_X \
- || reg_renumber[r] == REG_Y \
- || reg_renumber[r] == REG_Z \
- || (reg_renumber[r] \
- == ARG_POINTER_REGNUM))))
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, outer_code, index_code) \
+ avr_regno_mode_code_ok_for_base_p (num, mode, outer_code, index_code)
#define REGNO_OK_FOR_INDEX_P(NUM) 0
#define MAX_REGS_PER_ADDRESS 1
-#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
- (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
do { \
rtx new_x = avr_legitimize_reload_address (X, MODE, OPNUM, TYPE, \