diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eded70f6b52..83ca906c43d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2000-05-01 Franz Sirl + + * 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 * 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 9f8f984c7b1..7e95c0bd7b6 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 d89e6875cd4..4a22802a593 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 cf3f9474813..694bc039b9d 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)) + 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