summaryrefslogtreecommitdiff
path: root/gcc/config/pa/pa.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/pa/pa.h')
-rw-r--r--gcc/config/pa/pa.h63
1 files changed, 45 insertions, 18 deletions
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index b08021dd472..5edc151d26d 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1284,7 +1284,7 @@ extern int may_call_alloca;
`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. */
@@ -1307,17 +1307,20 @@ extern int may_call_alloca;
(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' ? \
@@ -1467,13 +1470,32 @@ extern int may_call_alloca;
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 \
@@ -1589,6 +1611,11 @@ do { \
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), \