aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranz Sirl <Franz.Sirl-kernel@lauterbach.com>2001-05-02 20:30:19 +0000
committerFranz Sirl <sirl@gcc.gnu.org>2001-05-02 20:30:19 +0000
commit258bfae2f7ab7b1c369fe3343a1132f16396072b (patch)
treedc28da252f441098a54788a3e9014a940e14515a
parentd34c5b8062a04951df36f69493cb9084e7645ccc (diff)
downloadgcc-258bfae2f7ab7b1c369fe3343a1132f16396072b.zip
gcc-258bfae2f7ab7b1c369fe3343a1132f16396072b.tar.gz
gcc-258bfae2f7ab7b1c369fe3343a1132f16396072b.tar.bz2
rs6000.c (rs6000_legitimate_address): Allow any stack offsets if not REG_OK_STRICT.
2000-05-01 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> * config/rs6000/rs6000.c (rs6000_legitimate_address): Allow any stack offsets if not REG_OK_STRICT. * config/rs6000/rs6000.h (REG_OK_STRICT_FLAG): New macro. (INT_REG_OK_FOR_INDEX_P): Likewise. (INT_REG_OK_FOR_BASE_P): Likewise. (REG_OK_FOR_INDEX_P): Use INT_REG_OK_FOR_INDEX_P. (REG_OK_FOR_BASE_P): Use INT_REG_OK_FOR_BASE_P. (LEGITIMATE_OFFSET_ADDRESS_P): Use INT_REG_OK_FOR_INDEX_P and INT_REG_OK_FOR_BASE_P instead of REG_OK_FOR_INDEX_P and REG_OK_FOR_BASE_P. Take an additional parameter. (LEGITIMATE_INDEXED_ADDRESS_P): Likeewise. (LEGITIMATE_INDIRECT_ADDRESS_P): Likewise. (LEGITIMATE_LO_SUM_ADDRESS_P): Likewise. (GO_IF_LEGITIMATE_ADDRESS): Move code into new function rs6000_legitimate_address() and use it. * config/rs6000/rs6000.c: Update all callers. (rs6000_legitimate_address): New function. From-SVN: r41772
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c70
-rw-r--r--gcc/config/rs6000/rs6000.h125
4 files changed, 138 insertions, 79 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eded70f..83ca906 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2000-05-01 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/rs6000.c (rs6000_legitimate_address): Allow any stack
+ offsets if not REG_OK_STRICT.
+
+ * config/rs6000/rs6000.h (REG_OK_STRICT_FLAG): New macro.
+ (INT_REG_OK_FOR_INDEX_P): Likewise.
+ (INT_REG_OK_FOR_BASE_P): Likewise.
+ (REG_OK_FOR_INDEX_P): Use INT_REG_OK_FOR_INDEX_P.
+ (REG_OK_FOR_BASE_P): Use INT_REG_OK_FOR_BASE_P.
+ (LEGITIMATE_OFFSET_ADDRESS_P): Use INT_REG_OK_FOR_INDEX_P and
+ INT_REG_OK_FOR_BASE_P instead of REG_OK_FOR_INDEX_P and
+ REG_OK_FOR_BASE_P. Take an additional parameter.
+ (LEGITIMATE_INDEXED_ADDRESS_P): Likeewise.
+ (LEGITIMATE_INDIRECT_ADDRESS_P): Likewise.
+ (LEGITIMATE_LO_SUM_ADDRESS_P): Likewise.
+ (GO_IF_LEGITIMATE_ADDRESS): Move code into new function
+ rs6000_legitimate_address() and use it.
+ * config/rs6000/rs6000.c: Update all callers.
+ (rs6000_legitimate_address): New function.
+
2001-05-02 David Edelsohn <edelsohn@gnu.org>
* config/rs6000/rs6000.c (rs6000_emit_move): Merge
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 9f8f984..7e95c0b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -107,6 +107,7 @@ extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
+extern int rs6000_legitimate_address PARAMS ((enum machine_mode, rtx, int));
extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
extern rtx rs6000_return_addr PARAMS ((int, rtx));
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d89e687..4a22802 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1550,6 +1550,58 @@ rs6000_legitimize_address (x, oldx, mode)
else
return NULL_RTX;
}
+
+/* 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.
+
+ On the RS/6000, there are four valid address: a SYMBOL_REF that
+ refers to a constant pool entry of an address (or the sum of it
+ plus a constant), a short (16-bit signed) constant plus a register,
+ the sum of two registers, or a register indirect, possibly with an
+ auto-increment. For DFmode and DImode with an constant plus register,
+ we must ensure that both words are addressable or PowerPC64 with offset
+ word aligned.
+
+ For modes spanning multiple registers (DFmode in 32-bit GPRs,
+ 32-bit DImode, TImode), indexed addressing cannot be used because
+ adjacent memory cells are accessed by adding word-sized offsets
+ during assembly output. */
+int
+rs6000_legitimate_address (mode, x, reg_ok_strict)
+ enum machine_mode mode;
+ rtx x;
+ int reg_ok_strict;
+{
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (x, reg_ok_strict))
+ return 1;
+ if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && TARGET_UPDATE
+ && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (x, 0), reg_ok_strict))
+ return 1;
+ if (LEGITIMATE_SMALL_DATA_P (mode, x))
+ return 1;
+ if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
+ return 1;
+ /* If not REG_OK_STRICT (before reload) let pass any stack offset. */
+ if (! reg_ok_strict
+ && GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && XEXP (x, 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ return 1;
+ if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, reg_ok_strict))
+ return 1;
+ if (mode != TImode
+ && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
+ && (TARGET_POWERPC64 || mode != DImode)
+ && LEGITIMATE_INDEXED_ADDRESS_P (x, reg_ok_strict))
+ return 1;
+ if (LEGITIMATE_LO_SUM_ADDRESS_P (mode, x, reg_ok_strict))
+ return 1;
+ return 0;
+}
/* Emit a move from SOURCE to DEST in mode MODE. */
void
@@ -3098,14 +3150,14 @@ lmw_operation (op, mode)
|| count != 32 - (int) dest_regno)
return 0;
- if (LEGITIMATE_INDIRECT_ADDRESS_P (src_addr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (src_addr, 0))
{
offset = 0;
base_regno = REGNO (src_addr);
if (base_regno == 0)
return 0;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, src_addr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, src_addr, 0))
{
offset = INTVAL (XEXP (src_addr, 1));
base_regno = REGNO (XEXP (src_addr, 0));
@@ -3128,12 +3180,12 @@ lmw_operation (op, mode)
|| GET_MODE (SET_SRC (elt)) != SImode)
return 0;
newaddr = XEXP (SET_SRC (elt), 0);
- if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
{
newoffset = 0;
addr_reg = newaddr;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
@@ -3176,14 +3228,14 @@ stmw_operation (op, mode)
|| count != 32 - (int) src_regno)
return 0;
- if (LEGITIMATE_INDIRECT_ADDRESS_P (dest_addr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (dest_addr, 0))
{
offset = 0;
base_regno = REGNO (dest_addr);
if (base_regno == 0)
return 0;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, dest_addr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, dest_addr, 0))
{
offset = INTVAL (XEXP (dest_addr, 1));
base_regno = REGNO (XEXP (dest_addr, 0));
@@ -3206,12 +3258,12 @@ stmw_operation (op, mode)
|| GET_MODE (SET_DEST (elt)) != SImode)
return 0;
newaddr = XEXP (SET_DEST (elt), 0);
- if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
{
newoffset = 0;
addr_reg = newaddr;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
@@ -4270,7 +4322,7 @@ print_operand (file, x, code)
case 'X':
if (GET_CODE (x) == MEM
- && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0)))
+ && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0), 0))
putc ('x', file);
return;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index cf3f947..694bc03 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1789,26 +1789,28 @@ typedef struct rs6000_args
After reload, it makes no difference, since pseudo regs have
been eliminated by then. */
-#ifndef REG_OK_STRICT
+#ifdef REG_OK_STRICT
+# define REG_OK_STRICT_FLAG 1
+#else
+# define REG_OK_STRICT_FLAG 0
+#endif
/* 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) \
- (REGNO (X) <= 31 || REGNO (X) == 67 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+ or if it is a pseudo reg in the non-strict case. */
+#define INT_REG_OK_FOR_INDEX_P(X, STRICT) \
+ ((! (STRICT) \
+ && (REGNO (X) <= 31 \
+ || REGNO (X) == ARG_POINTER_REGNUM \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER)) \
+ || ((STRICT) && REGNO_OK_FOR_INDEX_P (REGNO (X))))
/* 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) \
- (REGNO (X) > 0 && REG_OK_FOR_INDEX_P (X))
-
-#else
-
-/* 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 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))
+ or if it is a pseudo reg in the non-strict case. */
+#define INT_REG_OK_FOR_BASE_P(X, STRICT) \
+ (REGNO (X) > 0 && INT_REG_OK_FOR_INDEX_P (X, (STRICT)))
-#endif
+#define REG_OK_FOR_INDEX_P(X) INT_REG_OK_FOR_INDEX_P (X, REG_OK_STRICT_FLAG)
+#define REG_OK_FOR_BASE_P(X) INT_REG_OK_FOR_BASE_P (X, REG_OK_STRICT_FLAG)
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
@@ -1845,68 +1847,51 @@ typedef struct rs6000_args
&& (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST) \
&& small_data_operand (X, MODE))
-#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET) \
+#define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET) \
(GET_CODE (X) == CONST_INT \
&& (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE,X) \
- (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
- && (((MODE) != DFmode && (MODE) != DImode) \
- || (TARGET_32BIT \
- ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
- : ! (INTVAL (XEXP (X, 1)) & 3))) \
- && ((MODE) != TImode \
- || (TARGET_32BIT \
- ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
- : (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, STRICT) \
+ (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+ && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
+ && (((MODE) != DFmode && (MODE) != DImode) \
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
+ : ! (INTVAL (XEXP (X, 1)) & 3))) \
+ && ((MODE) != TImode \
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
+ : (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
&& ! (INTVAL (XEXP (X, 1)) & 3)))))
-#define LEGITIMATE_INDEXED_ADDRESS_P(X) \
- (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && ((REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- || (REG_OK_FOR_BASE_P (XEXP (X, 1)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)))))
-
-#define LEGITIMATE_INDIRECT_ADDRESS_P(X) \
- (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
-
-#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
- (TARGET_ELF \
- && ! flag_pic && ! TARGET_TOC \
- && (MODE) != DImode \
- && (MODE) != TImode \
- && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
- && GET_CODE (X) == LO_SUM \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+#define LEGITIMATE_INDEXED_ADDRESS_P(X, STRICT) \
+ (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && GET_CODE (XEXP (X, 1)) == REG \
+ && ((INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+ && INT_REG_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT))) \
+ || (INT_REG_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
+ && INT_REG_OK_FOR_INDEX_P (XEXP (X, 0), (STRICT)))))
+
+#define LEGITIMATE_INDIRECT_ADDRESS_P(X, STRICT) \
+ (GET_CODE (X) == REG && INT_REG_OK_FOR_BASE_P (X, (STRICT)))
+
+#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X, STRICT) \
+ (TARGET_ELF \
+ && ! flag_pic && ! TARGET_TOC \
+ && (MODE) != DImode \
+ && (MODE) != TImode \
+ && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
+ && GET_CODE (X) == LO_SUM \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
&& CONSTANT_P (XEXP (X, 1)))
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (LEGITIMATE_INDIRECT_ADDRESS_P (X)) \
- goto ADDR; \
- if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
- && TARGET_UPDATE \
- && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
- goto ADDR; \
- if (LEGITIMATE_SMALL_DATA_P (MODE, X)) \
- goto ADDR; \
- if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_OFFSET_ADDRESS_P (MODE, X)) \
- goto ADDR; \
- if ((MODE) != TImode \
- && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || (MODE) != DFmode) \
- && (TARGET_POWERPC64 || (MODE) != DImode) \
- && LEGITIMATE_INDEXED_ADDRESS_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_LO_SUM_ADDRESS_P (MODE, X)) \
- goto ADDR; \
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (rs6000_legitimate_address (MODE, X, REG_OK_STRICT_FLAG)) \
+ goto ADDR; \
}
/* Try machine-dependent ways of modifying an illegitimate address