===================================================================
@@ -351,16 +351,17 @@ static const struct reload_reg_map_type
/* Mask bits for each register class, indexed per mode. Historically the
compiler has been more restrictive which types can do PRE_MODIFY instead of
PRE_INC and PRE_DEC, so keep track of sepaate bits for these two. */
-typedef unsigned char addr_mask_type;
+typedef unsigned short addr_mask_type;
-#define RELOAD_REG_VALID 0x01 /* Mode valid in register.. */
-#define RELOAD_REG_MULTIPLE 0x02 /* Mode takes multiple registers. */
-#define RELOAD_REG_INDEXED 0x04 /* Reg+reg addressing. */
-#define RELOAD_REG_OFFSET 0x08 /* Reg+offset addressing. */
-#define RELOAD_REG_PRE_INCDEC 0x10 /* PRE_INC/PRE_DEC valid. */
-#define RELOAD_REG_PRE_MODIFY 0x20 /* PRE_MODIFY valid. */
-#define RELOAD_REG_AND_M16 0x40 /* AND -16 addressing. */
-#define RELOAD_REG_QUAD_OFFSET 0x80 /* quad offset is limited. */
+#define RELOAD_REG_VALID 0x001 /* Mode valid in register. */
+#define RELOAD_REG_MULTIPLE 0x002 /* Mode takes multiple registers. */
+#define RELOAD_REG_INDEXED 0x004 /* Reg+reg addressing. */
+#define RELOAD_REG_OFFSET 0x008 /* Reg+offset addressing. */
+#define RELOAD_REG_PRE_INCDEC 0x010 /* PRE_INC/PRE_DEC valid. */
+#define RELOAD_REG_PRE_MODIFY 0x020 /* PRE_MODIFY valid. */
+#define RELOAD_REG_AND_M16 0x040 /* AND -16 addressing. */
+#define RELOAD_REG_QUAD_OFFSET 0x080 /* quad offset is limited. */
+#define RELOAD_REG_DS_OFFSET 0x100 /* quad offset is limited. */
/* Register type masks based on the type, of valid addressing modes. */
struct rs6000_reg_addr {
@@ -2078,6 +2079,8 @@ rs6000_debug_addr_mask (addr_mask_type m
if ((mask & RELOAD_REG_QUAD_OFFSET) != 0)
*p++ = 'O';
+ else if ((mask & RELOAD_REG_DS_OFFSET) != 0)
+ *p++ = 'd';
else if ((mask & RELOAD_REG_OFFSET) != 0)
*p++ = 'o';
else if (keep_spaces)
@@ -2539,8 +2542,6 @@ rs6000_setup_reg_addr_masks (void)
{
machine_mode m2 = (machine_mode) m;
bool complex_p = false;
- bool small_int_p = (m2 == QImode || m2 == HImode || m2 == SImode);
- size_t msize;
if (COMPLEX_MODE_P (m2))
{
@@ -2548,7 +2549,9 @@ rs6000_setup_reg_addr_masks (void)
m2 = GET_MODE_INNER (m2);
}
- msize = GET_MODE_SIZE (m2);
+ ssize_t msize = GET_MODE_SIZE (m2);
+ bool small_int_p = (m2 == QImode || m2 == HImode || m2 == SImode);
+ bool float_2reg_p = FLOAT128_2REG_P (m2);
/* SDmode is special in that we want to access it only via REG+REG
addressing on power7 and above, since we want to use the LFIWZX and
@@ -2633,25 +2636,43 @@ rs6000_setup_reg_addr_masks (void)
possibly for SDmode. ISA 3.0 (i.e. power9) adds D-form addressing
for 64-bit scalars and 32-bit SFmode to altivec registers. */
if ((addr_mask != 0) && !indexed_only_p
- && msize <= 8
+ && (msize <= 8 || float_2reg_p)
&& (rc == RELOAD_REG_GPR
- || ((msize == 8 || m2 == SFmode)
+ || ((msize == 8 || m2 == SFmode || float_2reg_p)
&& (rc == RELOAD_REG_FPR
|| (rc == RELOAD_REG_VMX && TARGET_P9_VECTOR)))))
- addr_mask |= RELOAD_REG_OFFSET;
+ {
+ addr_mask |= RELOAD_REG_OFFSET;
+
+ /* 64-bit types in GPRs in 64-bit mode need DS-form memory.
+ Likewise any offsettable load in Altivec registers needs
+ DS-form. */
+ if ((rc == RELOAD_REG_GPR && msize == 8 && TARGET_POWERPC64)
+ || rc == RELOAD_REG_VMX)
+ addr_mask |= RELOAD_REG_DS_OFFSET;
+ }
/* VSX registers can do REG+OFFSET addresssing if ISA 3.0
instructions are enabled. The offset for 128-bit VSX registers is
- only 12-bits. While GPRs can handle the full offset range, VSX
- registers can only handle the restricted range. */
+ only 12-bits (DQ addressing). */
else if ((addr_mask != 0) && !indexed_only_p
&& msize == 16 && TARGET_P9_VECTOR
+ && (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX)
&& (ALTIVEC_OR_VSX_VECTOR_MODE (m2)
|| (m2 == TImode && TARGET_VSX)))
+ addr_mask |= (RELOAD_REG_OFFSET | RELOAD_REG_QUAD_OFFSET);
+
+ /* Vectors in GPR registers can do REG+OFFSET addressing. We need to
+ set DQ addressing if quad memory instructions are enabled, and DS
+ addressing for 64-bit mode for the LD/STD instructions. */
+ else if ((addr_mask != 0) && !indexed_only_p
+ && msize >= 16 && rc == RELOAD_REG_GPR)
{
addr_mask |= RELOAD_REG_OFFSET;
- if (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX)
+ if (TARGET_QUAD_MEMORY)
addr_mask |= RELOAD_REG_QUAD_OFFSET;
+ else if (TARGET_POWERPC64)
+ addr_mask |= RELOAD_REG_DS_OFFSET;
}
/* VMX registers can do (REG & -16) and ((REG+REG) & -16)