===================================================================
@@ -0,0 +1,44 @@
+/* { dg-options "-O2 -mgp64" } */
+/* { dg-final { scan-assembler-times "sdl\t" 1 } } */
+/* { dg-final { scan-assembler-times "sdr\t" 1 } } */
+/* { dg-final { scan-assembler-times "ldl\t" 1 } } */
+/* { dg-final { scan-assembler-times "ldr\t" 1 } } */
+/* { dg-final { scan-assembler-times "swl\t" 1 } } */
+/* { dg-final { scan-assembler-times "swr\t" 1 } } */
+/* { dg-final { scan-assembler-times "lwl\t" 1 } } */
+/* { dg-final { scan-assembler-times "lwr\t" 1 } } */
+/* { dg-final { scan-assembler-not "nop" } } */
+
+/* Test to make sure we produce the unaligned load/store for
+ both 64bit and 32bits sized accesses. */
+
+struct s
+{
+ char c;
+ int i;
+ long long l;
+} __attribute__ ((packed)) s __attribute__((aligned(1) ));
+
+void
+sd (long long l)
+{
+ s.l = l;
+}
+
+long long
+ld ()
+{
+ return s.l;
+}
+
+void
+sw (int i)
+{
+ s.i = i;
+}
+
+int
+lw ()
+{
+ return s.i;
+}
===================================================================
@@ -3653,7 +3653,8 @@ (define_expand "extv"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
- INTVAL (operands[3])))
+ INTVAL (operands[3]),
+ /*unsigned=*/ false))
DONE;
else if (register_operand (operands[1], GET_MODE (operands[0]))
&& ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32)
@@ -3690,7 +3691,8 @@ (define_expand "extzv"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
- INTVAL (operands[3])))
+ INTVAL (operands[3]),
+ /*unsigned=*/true))
DONE;
else if (mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
INTVAL (operands[3])))
===================================================================
@@ -241,7 +241,7 @@ extern bool mips_pad_arg_upward (enum ma
extern bool mips_pad_reg_upward (enum machine_mode, tree);
extern bool mips_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
- HOST_WIDE_INT);
+ HOST_WIDE_INT, bool);
extern bool mips_expand_ins_as_unaligned_store (rtx, rtx, HOST_WIDE_INT,
HOST_WIDE_INT);
extern bool mips_mem_fits_mode_p (enum machine_mode mode, rtx x);
===================================================================
@@ -6916,7 +6916,7 @@ mips_block_move_straight (rtx dest, rtx
else
{
rtx part = adjust_address (src, BLKmode, offset);
- if (!mips_expand_ext_as_unaligned_load (regs[i], part, bits, 0))
+ if (!mips_expand_ext_as_unaligned_load (regs[i], part, bits, 0, 0))
gcc_unreachable ();
}
}
@@ -7248,9 +7248,10 @@ mips_get_unaligned_mem (rtx *op, HOST_WI
bool
mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
- HOST_WIDE_INT bitpos)
+ HOST_WIDE_INT bitpos, bool unsigned_p)
{
rtx left, right, temp;
+ rtx dest1 = NULL_RTX;
/* If TARGET_64BIT, the destination of a 32-bit "extz" or "extzv" will
be a paradoxical word_mode subreg. This is the only case in which
@@ -7260,6 +7261,16 @@ mips_expand_ext_as_unaligned_load (rtx d
&& GET_MODE (SUBREG_REG (dest)) == SImode)
dest = SUBREG_REG (dest);
+ /* If TARGET_64BIT, the destination of a 32-bit "extz" or "extzv" will
+ be a DImode, create a new temp and emit a zero extend at the end. */
+ if (GET_MODE (dest) == DImode
+ && REG_P (dest)
+ && GET_MODE_BITSIZE (SImode) == width)
+ {
+ dest1 = dest;
+ dest = gen_reg_rtx (SImode);
+ }
+
/* After the above adjustment, the destination must be the same
width as the source. */
if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
@@ -7279,6 +7290,16 @@ mips_expand_ext_as_unaligned_load (rtx d
emit_insn (gen_mov_lwl (temp, src, left));
emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
}
+
+ /* If we were loading 32bits and the original register was DI then
+ sign/zero extend into the orignal dest. */
+ if (dest1)
+ {
+ if (unsigned_p)
+ emit_insn (gen_zero_extendsidi2 (dest1, dest));
+ else
+ emit_insn (gen_extendsidi2 (dest1, dest));
+ }
return true;
}