+2004-06-21 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ PR rtl-optimization/14782
+ * pa.c (emit_move_sequence): Use SFmode for 4-byte modes when doing
+ the address checks for secondary reloads for loads from and stores
+ to floating-point registers.
+ * pa.h (EXTRA_CONSTRAINT, case T): Use SFmode for 4-byte modes
+ in the address check. Move work around for ELF32 targets to
+ GO_IF_LEGITIMATE_ADDRESS.
+ (GO_IF_LEGITIMATE_ADDRESS): Require constant offsets to be
+ correctly aligned for DImode loads and stores. Don't allow long
+ SFmode displacements on ELF32.
+
2004-06-21 Richard Henderson <rth@redhat.com>
PR rtl-opt/16114
operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
/* Handle secondary reloads for loads/stores of FP registers from
- REG+D addresses where D does not fit in 5 bits, including
+ REG+D addresses where D does not fit in 5 or 14 bits, including
(subreg (mem (addr))) cases. */
if (scratch_reg
&& fp_reg_operand (operand0, mode)
&& ((GET_CODE (operand1) == MEM
- && !memory_address_p (DFmode, XEXP (operand1, 0)))
+ && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
+ XEXP (operand1, 0)))
|| ((GET_CODE (operand1) == SUBREG
&& GET_CODE (XEXP (operand1, 0)) == MEM
- && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))))
+ && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+ ? SFmode : DFmode),
+ XEXP (XEXP (operand1, 0), 0))))))
{
if (GET_CODE (operand1) == SUBREG)
operand1 = XEXP (operand1, 0);
else if (scratch_reg
&& fp_reg_operand (operand1, mode)
&& ((GET_CODE (operand0) == MEM
- && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+ && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+ ? SFmode : DFmode),
+ XEXP (operand0, 0)))
|| ((GET_CODE (operand0) == SUBREG)
&& GET_CODE (XEXP (operand0, 0)) == MEM
- && !memory_address_p (DFmode,
+ && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+ ? SFmode : DFmode),
XEXP (XEXP (operand0, 0), 0)))))
{
if (GET_CODE (operand0) == SUBREG)
`S' is the constant 31.
- `T' is for fp loads and stores.
+ `T' is for floating-point loads and stores.
`U' is the constant 63. */
(GET_CODE (OP) == MEM \
&& !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)) \
&& !IS_INDEX_ADDR_P (XEXP (OP, 0)) \
- /* Using DFmode forces only short displacements \
- to be recognized as valid in reg+d addresses. \
- However, this is not necessary for PA2.0 since \
- it has long FP loads/stores. \
+ /* Floating-point loads and stores are used to load \
+ integer values as well as floating-point values. \
+ They don't have the same set of REG+D address modes \
+ as integer loads and stores. PA 1.x supports only \
+ short displacements. PA 2.0 supports long displacements \
+ but the base register needs to be aligned. \
\
- FIXME: the ELF32 linker clobbers the LSB of \
- the FP register number in {fldw,fstw} insns. \
- Thus, we only allow long FP loads/stores on \
- TARGET_64BIT. */ \
- && memory_address_p ((TARGET_PA_20 && !TARGET_ELF32 \
- ? GET_MODE (OP) \
+ The checks in GO_IF_LEGITIMATE_ADDRESS for SFmode and \
+ DFmode test the validity of an address for use in a \
+ floating point load or store. So, we use SFmode/DFmode \
+ to see if the address is valid for a floating-point \
+ load/store operation. */ \
+ && memory_address_p ((GET_MODE_SIZE (GET_MODE (OP)) == 4 \
+ ? SFmode \
: DFmode), \
XEXP (OP, 0))) \
: ((C) == 'S' ? \
if (base \
&& GET_CODE (index) == CONST_INT \
&& ((INT_14_BITS (index) \
- && (TARGET_SOFT_FLOAT \
- || (TARGET_PA_20 \
- && ((MODE == SFmode \
- && (INTVAL (index) % 4) == 0) \
- || (MODE == DFmode \
- && (INTVAL (index) % 8) == 0))) \
- || ((MODE) != SFmode && (MODE) != DFmode))) \
+ && (((MODE) != DImode \
+ && (MODE) != SFmode \
+ && (MODE) != DFmode) \
+ /* The base register for DImode loads and stores \
+ with long displacements must be aligned because \
+ the lower three bits in the displacement are \
+ assumed to be zero. */ \
+ || ((MODE) == DImode \
+ && (!TARGET_64BIT \
+ || (INTVAL (index) % 8) == 0)) \
+ /* Similarly, the base register for SFmode/DFmode \
+ loads and stores with long displacements must \
+ be aligned. \
+ \
+ FIXME: the ELF32 linker clobbers the LSB of \
+ the FP register number in PA 2.0 floating-point \
+ insns with long displacements. This is because \
+ R_PARISC_DPREL14WR and other relocations like \
+ it are not supported. For now, we reject long \
+ displacements on this target. */ \
+ || (((MODE) == SFmode || (MODE) == DFmode) \
+ && (TARGET_SOFT_FLOAT \
+ || (TARGET_PA_20 \
+ && !TARGET_ELF32 \
+ && (INTVAL (index) \
+ % GET_MODE_SIZE (MODE)) == 0))))) \
|| INT_5_BITS (index))) \
goto ADDR; \
if (!TARGET_DISABLE_INDEXING \
else \
newoffset = offset & ~mask; \
\
+ /* Ensure that long displacements are aligned. */ \
+ if (!VAL_5_BITS_P (newoffset) \
+ && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ newoffset &= ~(GET_MODE_SIZE (MODE) -1); \
+ \
if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \
{ \
temp = gen_rtx_PLUS (Pmode, XEXP (new, 0), \