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
This commit is contained in:
Franz Sirl 2001-05-02 20:30:19 +00:00 committed by Franz Sirl
parent d34c5b8062
commit 258bfae2f7
4 changed files with 136 additions and 77 deletions

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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))
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)))
#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))
#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_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) \
(GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
#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) \
(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_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