return 0;
}
\f
+/* Return TRUE for a valid displacement for the REG+disp addressing
+ with MODE. */
+
+/* ??? The SH2e does not have the REG+disp addressing mode when loading values
+ into the FRx registers. We implement this by setting the maximum offset
+ to zero when the value is SFmode. This also restricts loading of SFmode
+ values into the integer registers, but that can't be helped. */
+
+/* The SH allows a displacement in a QI or HI amode, but only when the
+ other operand is R0. GCC doesn't handle this very well, so we forgot
+ all of that.
+
+ A legitimate index for a QI or HI is 0, SI can be any number 0..63,
+ DI can be any number 0..60. */
+
+bool
+sh_legitimate_index_p (enum machine_mode mode, rtx op)
+{
+ if (GET_CODE (op) == CONST_INT)
+ {
+ if (TARGET_SHMEDIA)
+ {
+ int size;
+
+ /* Check if this the address of an unaligned load / store. */
+ if (mode == VOIDmode)
+ return CONST_OK_FOR_I06 (INTVAL (op));
+
+ size = GET_MODE_SIZE (mode);
+ return (!(INTVAL (op) & (size - 1))
+ && INTVAL (op) >= -512 * size
+ && INTVAL (op) < 512 * size);
+ }
+
+ if (TARGET_SH2A)
+ {
+ if (GET_MODE_SIZE (mode) == 1
+ && (unsigned) INTVAL (op) < 4096)
+ return true;
+ }
+
+ if ((GET_MODE_SIZE (mode) == 4
+ && (unsigned) INTVAL (op) < 64
+ && !(INTVAL (op) & 3)
+ && !(TARGET_SH2E && mode == SFmode))
+ || (GET_MODE_SIZE (mode) == 4
+ && (unsigned) INTVAL (op) < 16383
+ && !(INTVAL (op) & 3) && TARGET_SH2A))
+ return true;
+
+ if ((GET_MODE_SIZE (mode) == 8
+ && (unsigned) INTVAL (op) < 60
+ && !(INTVAL (op) & 3)
+ && !((TARGET_SH4 || TARGET_SH2A) && mode == DFmode))
+ || ((GET_MODE_SIZE (mode)==8)
+ && (unsigned) INTVAL (op) < 8192
+ && !(INTVAL (op) & (TARGET_SH2A_DOUBLE ? 7 : 3))
+ && (TARGET_SH2A && mode == DFmode)))
+ return true;
+ }
+
+ return false;
+}
+
+/* Recognize an RTL expression that is a valid memory address for
+ an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+ Allow REG
+ REG+disp
+ REG+r0
+ REG++
+ --REG */
+
+bool
+sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ if (MAYBE_BASE_REGISTER_RTX_P (x, strict))
+ return true;
+ else if ((GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC)
+ && ! TARGET_SHMEDIA
+ && MAYBE_BASE_REGISTER_RTX_P (XEXP (x, 0), strict))
+ return true;
+ else if (GET_CODE (x) == PLUS
+ && (mode != PSImode || reload_completed))
+ {
+ rtx xop0 = XEXP (x, 0);
+ rtx xop1 = XEXP (x, 1);
+
+ if (GET_MODE_SIZE (mode) <= 8
+ && MAYBE_BASE_REGISTER_RTX_P (xop0, strict)
+ && sh_legitimate_index_p (mode, xop1))
+ return true;
+
+ if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode
+ || ((xop0 == stack_pointer_rtx
+ || xop0 == hard_frame_pointer_rtx)
+ && REG_P (xop1) && REGNO (xop1) == R0_REG)
+ || ((xop1 == stack_pointer_rtx
+ || xop1 == hard_frame_pointer_rtx)
+ && REG_P (xop0) && REGNO (xop0) == R0_REG))
+ && ((!TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 4)
+ || (TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 8)
+ || ((TARGET_SH4 || TARGET_SH2A_DOUBLE)
+ && TARGET_FMOVD && mode == DFmode)))
+ {
+ if (MAYBE_BASE_REGISTER_RTX_P (xop1, strict)
+ && MAYBE_INDEX_REGISTER_RTX_P (xop0, strict))
+ return true;
+ if (MAYBE_INDEX_REGISTER_RTX_P (xop1, strict)
+ && MAYBE_BASE_REGISTER_RTX_P (xop0, strict))
+ return true;
+ }
+ }
+
+ return false;
+}
+\f
/* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
isn't protected by a PIC unspec. */
int
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
- We have two alternate definitions for each of them.
- The usual definition accepts all pseudo regs; the other rejects
- them unless they have been allocated suitable hard regs.
- The symbol REG_OK_STRICT causes the latter definition to be used. */
-
-#ifndef REG_OK_STRICT
-
-/* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) \
- (GENERAL_OR_AP_REGISTER_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. */
-#define REG_OK_FOR_INDEX_P(X) \
- ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
- : REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-/* Nonzero if X/OFFSET is a hard reg that can be used as an index
- or if X is a pseudo reg. */
-#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
- ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
- : REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#else
-
-/* Nonzero if X is a hard reg that can be used as a base reg. */
-#define REG_OK_FOR_BASE_P(X) \
- REGNO_OK_FOR_BASE_P (REGNO (X))
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) \
- REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-/* Nonzero if X/OFFSET is a hard reg that can be used as an index. */
-#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
- (REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
-
-#endif
+ The suitable hard regs are always accepted and all pseudo regs
+ are also accepted if STRICT is not set. */
+
+/* Nonzero if X is a reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X, STRICT) \
+ (GENERAL_OR_AP_REGISTER_P (REGNO (X)) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X is a reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X, STRICT) \
+ ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+ : REGNO (X) == R0_REG) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X/OFFSET is a reg that can be used as an index. */
+#define SUBREG_OK_FOR_INDEX_P(X, OFFSET, STRICT) \
+ ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+ : REGNO (X) == R0_REG && OFFSET == 0) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Macros for extra constraints. */
|| PCREL_SYMOFF_P (OP)) \
: NON_PIC_REFERENCE_P (OP))
\f
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address. */
-
-#define MODE_DISP_OK_4(X,MODE) \
-(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
-
-#define MODE_DISP_OK_8(X,MODE) \
-((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
- && ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
-
-#undef MODE_DISP_OK_4
-#define MODE_DISP_OK_4(X,MODE) \
-((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
- || ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383) \
- && ! (INTVAL(X) & 3) && TARGET_SH2A))
-
-#undef MODE_DISP_OK_8
-#define MODE_DISP_OK_8(X,MODE) \
-(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
- && ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
- || ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192) \
- && ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
-
-#define BASE_REGISTER_RTX_P(X) \
- ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
- || (GET_CODE (X) == SUBREG \
- && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
+#define MAYBE_BASE_REGISTER_RTX_P(X, STRICT) \
+ ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X, STRICT)) \
+ || (GET_CODE (X) == SUBREG \
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
- && GET_CODE (SUBREG_REG (X)) == REG \
- && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
+ && GET_CODE (SUBREG_REG (X)) == REG \
+ && REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
/* Since this must be r0, which is a single register class, we must check
SUBREGs more carefully, to be sure that we don't accept one that extends
outside the class. */
-#define INDEX_REGISTER_RTX_P(X) \
- ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
- || (GET_CODE (X) == SUBREG \
+#define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT) \
+ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X, STRICT)) \
+ || (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
&& GET_CODE (SUBREG_REG (X)) == REG \
- && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
-
-/* Jump to LABEL if X is a valid address RTX. This must also take
- REG_OK_STRICT into account when deciding about valid registers, but it uses
- the above macros so we are in luck.
+ && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
- Allow REG
- REG+disp
- REG+r0
- REG++
- --REG */
-
-/* ??? The SH2e does not have the REG+disp addressing mode when loading values
- into the FRx registers. We implement this by setting the maximum offset
- to zero when the value is SFmode. This also restricts loading of SFmode
- values into the integer registers, but that can't be helped. */
-
-/* The SH allows a displacement in a QI or HI amode, but only when the
- other operand is R0. GCC doesn't handle this very well, so we forgo
- all of that.
-
- A legitimate index for a QI or HI is 0, SI can be any number 0..63,
- DI can be any number 0..60. */
-
-#define GO_IF_LEGITIMATE_INDEX(MODE, OP, LABEL) \
- do { \
- if (GET_CODE (OP) == CONST_INT) \
- { \
- if (TARGET_SHMEDIA) \
- { \
- int MODE_SIZE; \
- /* Check if this the address of an unaligned load / store. */\
- if ((MODE) == VOIDmode) \
- { \
- if (CONST_OK_FOR_I06 (INTVAL (OP))) \
- goto LABEL; \
- break; \
- } \
- MODE_SIZE = GET_MODE_SIZE (MODE); \
- if (! (INTVAL (OP) & (MODE_SIZE - 1)) \
- && INTVAL (OP) >= -512 * MODE_SIZE \
- && INTVAL (OP) < 512 * MODE_SIZE) \
- goto LABEL; \
- else \
- break; \
- } \
- if (TARGET_SH2A) \
- { \
- if (GET_MODE_SIZE (MODE) == 1 \
- && (unsigned) INTVAL (OP) < 4096) \
- goto LABEL; \
- } \
- if (MODE_DISP_OK_4 ((OP), (MODE))) goto LABEL; \
- if (MODE_DISP_OK_8 ((OP), (MODE))) goto LABEL; \
- } \
- } while(0)
+#ifdef REG_OK_STRICT
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, true)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, true)
+#else
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, false)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, false)
+#endif
#define ALLOW_INDEXED_ADDRESS \
((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
-{ \
- if (BASE_REGISTER_RTX_P (X)) \
- goto LABEL; \
- else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
- && ! TARGET_SHMEDIA \
- && BASE_REGISTER_RTX_P (XEXP ((X), 0))) \
- goto LABEL; \
- else if (GET_CODE (X) == PLUS \
- && ((MODE) != PSImode || reload_completed)) \
- { \
- rtx xop0 = XEXP ((X), 0); \
- rtx xop1 = XEXP ((X), 1); \
- if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \
- GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL); \
- if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode \
- || ((xop0 == stack_pointer_rtx \
- || xop0 == hard_frame_pointer_rtx) \
- && REG_P (xop1) && REGNO (xop1) == R0_REG) \
- || ((xop1 == stack_pointer_rtx \
- || xop1 == hard_frame_pointer_rtx) \
- && REG_P (xop0) && REGNO (xop0) == R0_REG)) \
- && ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4) \
- || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8) \
- || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \
- && TARGET_FMOVD && MODE == DFmode))) \
- { \
- if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
- goto LABEL; \
- if (INDEX_REGISTER_RTX_P (xop1) && BASE_REGISTER_RTX_P (xop0))\
- goto LABEL; \
- } \
- } \
-}
+#define GO_IF_LEGITIMATE_INDEX(MODE, OP, WIN) \
+ do { \
+ if (sh_legitimate_index_p ((MODE), (OP))) \
+ goto WIN; \
+ } while (0)
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
+ do { \
+ if (sh_legitimate_address_p ((MODE), (X), true)) \
+ goto LABEL; \
+ } while (0)
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
+ do { \
+ if (sh_legitimate_address_p ((MODE), (X), false)) \
+ goto LABEL; \
+ } while (0)
+#endif
\f
/* A C compound statement that attempts to replace X, which is an address
that needs reloading, with a valid memory address for an operand of