diff options
Diffstat (limited to 'gcc/config/pa/pa.h')
-rw-r--r-- | gcc/config/pa/pa.h | 63 |
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), \ |