switch (GET_CODE (addr))
{
case POST_INC:
- mn10300_print_operand_address (file, XEXP (addr, 0));
+ mn10300_print_operand (file, XEXP (addr, 0), 0);
fputc ('+', file);
break;
+
+ case POST_MODIFY:
+ mn10300_print_operand (file, XEXP (addr, 0), 0);
+ fputc ('+', file);
+ fputc (',', file);
+ mn10300_print_operand (file, XEXP (addr, 1), 0);
+ break;
+
case REG:
mn10300_print_operand (file, addr, 0);
break;
case PLUS:
{
- rtx base, index;
- if (REG_P (XEXP (addr, 0))
- && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
- base = XEXP (addr, 0), index = XEXP (addr, 1);
- else if (REG_P (XEXP (addr, 1))
- && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
- base = XEXP (addr, 1), index = XEXP (addr, 0);
- else
- gcc_unreachable ();
+ rtx base = XEXP (addr, 0);
+ rtx index = XEXP (addr, 1);
+
+ if (REG_P (index) && !REG_OK_FOR_INDEX_P (index))
+ {
+ rtx x = base;
+ base = index;
+ index = x;
+
+ gcc_assert (REG_P (index) && REG_OK_FOR_INDEX_P (index));
+ }
+ gcc_assert (REG_OK_FOR_BASE_P (base));
+
mn10300_print_operand (file, index, 0);
fputc (',', file);
- mn10300_print_operand (file, base, 0);;
+ mn10300_print_operand (file, base, 0);
break;
}
case SYMBOL_REF:
if (in_p
&& rclass != SP_REGS
&& rclass != SP_OR_ADDRESS_REGS
- && rclass != SP_OR_EXTENDED_REGS
- && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS
+ && rclass != SP_OR_GENERAL_REGS
&& GET_CODE (x) == PLUS
&& (XEXP (x, 0) == stack_pointer_rtx
|| XEXP (x, 1) == stack_pointer_rtx))
addr = XEXP (x, 0);
if (addr && CONSTANT_ADDRESS_P (addr))
- return DATA_OR_EXTENDED_REGS;
+ return GENERAL_REGS;
}
/* Otherwise assume no secondary reloads are needed. */
static bool
mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
- if (CONSTANT_ADDRESS_P (x)
- && (! flag_pic || mn10300_legitimate_pic_operand_p (x)))
- return TRUE;
+ rtx base, index;
+
+ if (CONSTANT_ADDRESS_P (x))
+ return !flag_pic || mn10300_legitimate_pic_operand_p (x);
if (RTX_OK_FOR_BASE_P (x, strict))
- return TRUE;
+ return true;
- if (TARGET_AM33
- && GET_CODE (x) == POST_INC
- && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
- && (mode == SImode || mode == SFmode || mode == HImode))
- return TRUE;
+ if (TARGET_AM33 && (mode == SImode || mode == SFmode || mode == HImode))
+ {
+ if (GET_CODE (x) == POST_INC)
+ return RTX_OK_FOR_BASE_P (XEXP (x, 0), strict);
+ if (GET_CODE (x) == POST_MODIFY)
+ return (RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
+ && CONSTANT_ADDRESS_P (XEXP (x, 1)));
+ }
- if (GET_CODE (x) == PLUS)
+ if (GET_CODE (x) != PLUS)
+ return false;
+
+ base = XEXP (x, 0);
+ index = XEXP (x, 1);
+
+ if (!REG_P (base))
+ return false;
+ if (REG_P (index))
{
- rtx base = 0, index = 0;
+ /* ??? Without AM33 generalized (Ri,Rn) addressing, reg+reg
+ addressing is hard to satisfy. */
+ if (!TARGET_AM33)
+ return false;
- if (REG_P (XEXP (x, 0))
- && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict))
- {
- base = XEXP (x, 0);
- index = XEXP (x, 1);
- }
+ return (REGNO_GENERAL_P (REGNO (base), strict)
+ && REGNO_GENERAL_P (REGNO (index), strict));
+ }
- if (REG_P (XEXP (x, 1))
- && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict))
- {
- base = XEXP (x, 1);
- index = XEXP (x, 0);
- }
+ if (!REGNO_STRICT_OK_FOR_BASE_P (REGNO (base), strict))
+ return false;
- if (base != 0 && index != 0)
- {
- if (CONST_INT_P (index))
- return TRUE;
- if (GET_CODE (index) == CONST
- && GET_CODE (XEXP (index, 0)) != PLUS
- && (! flag_pic
- || (mn10300_legitimate_pic_operand_p (index)
- && GET_MODE_SIZE (mode) == 4)))
- return TRUE;
- }
+ if (CONST_INT_P (index))
+ return IN_RANGE (INTVAL (index), -1 - 0x7fffffff, 0x7fffffff);
+
+ if (CONSTANT_ADDRESS_P (index))
+ return !flag_pic || mn10300_legitimate_pic_operand_p (index);
+
+ return false;
+}
+
+bool
+mn10300_regno_in_class_p (unsigned regno, int rclass, bool strict)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ if (!strict)
+ return true;
+ if (!reg_renumber)
+ return false;
+ regno = reg_renumber[regno];
+ }
+ return TEST_HARD_REG_BIT (reg_class_contents[rclass], regno);
+}
+
+rtx
+mn10300_legitimize_reload_address (rtx x,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED)
+{
+ bool any_change = false;
+
+ /* See above re disabling reg+reg addressing for MN103. */
+ if (!TARGET_AM33)
+ return NULL_RTX;
+
+ if (GET_CODE (x) != PLUS)
+ return NULL_RTX;
+
+ if (XEXP (x, 0) == stack_pointer_rtx)
+ {
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ any_change = true;
+ }
+ if (XEXP (x, 1) == stack_pointer_rtx)
+ {
+ push_reload (XEXP (x, 1), NULL_RTX, &XEXP (x, 1), NULL,
+ GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ any_change = true;
}
- return FALSE;
+ return any_change ? x : NULL_RTX;
}
/* Used by LEGITIMATE_CONSTANT_P(). Returns TRUE if X is a valid
enum reg_class
{
- NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS,
- DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS,
- EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
- SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS,
- FP_REGS, FP_ACC_REGS, CC_REGS,
- GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
+ NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, SP_OR_ADDRESS_REGS,
+ EXTENDED_REGS, FP_REGS, FP_ACC_REGS, CC_REGS,
+ GENERAL_REGS, SP_OR_GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
};
#define N_REG_CLASSES (int) LIM_REG_CLASSES
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
-{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \
- "SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \
- "EXTENDED_REGS", \
- "DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \
- "SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \
- "FP_REGS", "FP_ACC_REGS", "CC_REGS", \
- "GENERAL_REGS", "ALL_REGS", "LIM_REGS" \
+{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", "SP_REGS", "SP_OR_ADDRESS_REGS", \
+ "EXTENDED_REGS", "FP_REGS", "FP_ACC_REGS", "CC_REGS", \
+ "GENERAL_REGS", "SP_OR_GENERAL_REGS", "ALL_REGS", "LIM_REGS" \
}
/* Define which registers fit in which classes.
{ 0x0000000f, 0 }, /* DATA_REGS */ \
{ 0x000001f0, 0 }, /* ADDRESS_REGS */ \
{ 0x00000200, 0 }, /* SP_REGS */ \
- { 0x000001ff, 0 }, /* DATA_OR_ADDRESS_REGS */ \
{ 0x000003f0, 0 }, /* SP_OR_ADDRESS_REGS */ \
{ 0x0003fc00, 0 }, /* EXTENDED_REGS */ \
- { 0x0003fc0f, 0 }, /* DATA_OR_EXTENDED_REGS */ \
- { 0x0003fdf0, 0 }, /* ADDRESS_OR_EXTENDED_REGS */ \
- { 0x0003fe00, 0 }, /* SP_OR_EXTENDED_REGS */ \
- { 0x0003fff0, 0 }, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \
{ 0xfffc0000, 0x3ffff },/* FP_REGS */ \
{ 0x03fc0000, 0 }, /* FP_ACC_REGS */ \
{ 0x00000000, 0x80000 },/* CC_REGS */ \
{ 0x0003fdff, 0 }, /* GENERAL_REGS */ \
+ { 0x0003ffff, 0 }, /* SP_OR_GENERAL_REGS */ \
{ 0xffffffff, 0xfffff } /* ALL_REGS */ \
}
NO_REGS)
/* The class value for index registers, and the one for base regs. */
-#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS
-#define BASE_REG_CLASS SP_OR_ADDRESS_REGS
+#define INDEX_REG_CLASS \
+ (TARGET_AM33 ? GENERAL_REGS : DATA_REGS)
+#define BASE_REG_CLASS \
+ (TARGET_AM33 ? SP_OR_GENERAL_REGS : SP_OR_ADDRESS_REGS)
/* Macros to check register numbers against specific register classes. */
# define REG_STRICT 1
#endif
-# define REGNO_IN_RANGE_P(regno,min,max,strict) \
- (IN_RANGE ((regno), (min), (max)) \
- || ((strict) \
- ? (reg_renumber \
- && reg_renumber[(regno)] >= (min) \
- && reg_renumber[(regno)] <= (max)) \
- : (regno) >= FIRST_PSEUDO_REGISTER))
-
#define REGNO_DATA_P(regno, strict) \
- (REGNO_IN_RANGE_P ((regno), FIRST_DATA_REGNUM, LAST_DATA_REGNUM, \
- (strict)))
+ mn10300_regno_in_class_p (regno, DATA_REGS, strict)
#define REGNO_ADDRESS_P(regno, strict) \
- (REGNO_IN_RANGE_P ((regno), FIRST_ADDRESS_REGNUM, LAST_ADDRESS_REGNUM, \
- (strict)))
-#define REGNO_SP_P(regno, strict) \
- (REGNO_IN_RANGE_P ((regno), STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, \
- (strict)))
+ mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict)
#define REGNO_EXTENDED_P(regno, strict) \
- (REGNO_IN_RANGE_P ((regno), FIRST_EXTENDED_REGNUM, LAST_EXTENDED_REGNUM, \
- (strict)))
-#define REGNO_AM33_P(regno, strict) \
- (REGNO_DATA_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)) \
- || REGNO_EXTENDED_P ((regno), (strict)))
-#define REGNO_FP_P(regno, strict) \
- (REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM, (strict)))
+ mn10300_regno_in_class_p (regno, EXTENDED_REGS, strict)
+#define REGNO_GENERAL_P(regno, strict) \
+ mn10300_regno_in_class_p (regno, GENERAL_REGS, strict)
#define REGNO_STRICT_OK_FOR_BASE_P(regno, strict) \
- (REGNO_SP_P ((regno), (strict)) \
- || REGNO_ADDRESS_P ((regno), (strict)) \
- || REGNO_EXTENDED_P ((regno), (strict)))
+ mn10300_regno_in_class_p (regno, BASE_REG_CLASS, strict)
#define REGNO_OK_FOR_BASE_P(regno) \
(REGNO_STRICT_OK_FOR_BASE_P ((regno), REG_STRICT))
#define REG_OK_FOR_BASE_P(X) \
(REGNO_OK_FOR_BASE_P (REGNO (X)))
#define REGNO_STRICT_OK_FOR_BIT_BASE_P(regno, strict) \
- (REGNO_SP_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)))
+ mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict)
#define REGNO_OK_FOR_BIT_BASE_P(regno) \
(REGNO_STRICT_OK_FOR_BIT_BASE_P ((regno), REG_STRICT))
#define REG_OK_FOR_BIT_BASE_P(X) \
(REGNO_OK_FOR_BIT_BASE_P (REGNO (X)))
#define REGNO_STRICT_OK_FOR_INDEX_P(regno, strict) \
- (REGNO_DATA_P ((regno), (strict)) || REGNO_EXTENDED_P ((regno), (strict)))
+ mn10300_regno_in_class_p (regno, INDEX_REG_CLASS, strict)
#define REGNO_OK_FOR_INDEX_P(regno) \
(REGNO_STRICT_OK_FOR_INDEX_P ((regno), REG_STRICT))
#define REG_OK_FOR_INDEX_P(X) \
#define MAX_REGS_PER_ADDRESS 2
\f
-#define HAVE_POST_INCREMENT (TARGET_AM33)
+/* We have post-increments. */
+#define HAVE_POST_INCREMENT TARGET_AM33
+#define HAVE_POST_MODIFY_DISP TARGET_AM33
+
+/* ... But we don't want to use them for block moves. Small offsets are
+ just as effective, at least for inline block move sizes, and appears
+ to produce cleaner code. */
+#define USE_LOAD_POST_INCREMENT(M) 0
+#define USE_STORE_POST_INCREMENT(M) 0
/* Accept either REG or SUBREG where a register is valid. */
&& REGNO_STRICT_OK_FOR_BASE_P (REGNO (SUBREG_REG (X)), \
(strict))))
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
+do { \
+ rtx new_x = mn10300_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \
+ if (new_x) \
+ { \
+ X = new_x; \
+ goto WIN; \
+ } \
+} while (0)
\f
/* Nonzero if the constant value X is a legitimate general operand.