summaryrefslogtreecommitdiff
path: root/gcc/config/pa
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-21 23:49:04 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-21 23:49:04 +0000
commit047e31217cbb6af2c833f5dc47d96c72940eae02 (patch)
tree849135555b08d2fca700a6e4b72f2efaba5ccb2f /gcc/config/pa
parentb57e33a433988215880ee38d0f392bba7a5c8726 (diff)
downloadgcc-047e31217cbb6af2c833f5dc47d96c72940eae02.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83464 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/pa')
-rw-r--r--gcc/config/pa/pa.c16
-rw-r--r--gcc/config/pa/pa.h63
2 files changed, 56 insertions, 23 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 8bae9e32ad7..3aee1adecbd 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
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);
@@ -1600,10 +1603,13 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
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)
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), \