aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@cavium.com>2012-07-21 10:38:20 +0000
committerAndrew Pinski <pinskia@gcc.gnu.org>2012-07-21 03:38:20 -0700
commitaea21190650881b9b17580a55f61393eb78f33a4 (patch)
tree82994461bf1705ad28d5bc60086f1c77591e01f6
parent6220bf437fdafee2250024aacff0a37e33ebd96b (diff)
downloadgcc-aea21190650881b9b17580a55f61393eb78f33a4.zip
gcc-aea21190650881b9b17580a55f61393eb78f33a4.tar.gz
gcc-aea21190650881b9b17580a55f61393eb78f33a4.tar.bz2
mips-protos.h (mips_expand_ext_as_unaligned_load): Add a bool argument.
2012-07-21 Andrew Pinski <apinski@cavium.com> * config/mips/mips-protos.h (mips_expand_ext_as_unaligned_load): Add a bool argument. * config/mips/mips.c (mips_block_move_straight): Update call to mips_expand_ext_as_unaligned_load. (mips_expand_ext_as_unaligned_load): Add unsigned_p argument. Accept DImode dest when the width is that of SImode. * config/mips/mips.md (extv): Update call to mips_expand_ext_as_unaligned_load. (extzv): Likewise. 2012-07-21 Andrew Pinski <apinski@cavium.com> * gcc.target/mips/unaligned-1.c: New testcase. From-SVN: r189742
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/mips/mips-protos.h2
-rw-r--r--gcc/config/mips/mips.c25
-rw-r--r--gcc/config/mips/mips.md6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/unaligned-1.c44
6 files changed, 88 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fec3d36..4027766 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
2012-07-21 Andrew Pinski <apinski@cavium.com>
+ * config/mips/mips-protos.h (mips_expand_ext_as_unaligned_load):
+ Add a bool argument.
+ * config/mips/mips.c (mips_block_move_straight): Update call to
+ mips_expand_ext_as_unaligned_load.
+ (mips_expand_ext_as_unaligned_load): Add unsigned_p argument.
+ Accept DImode dest when the width is that of SImode.
+ * config/mips/mips.md (extv): Update call to
+ mips_expand_ext_as_unaligned_load.
+ (extzv): Likewise.
+
+2012-07-21 Andrew Pinski <apinski@cavium.com>
+
* config/mips/mips.c (mips_get_unaligned_mem): Copy *op after calling
adjust_address.
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index d1fa160..cba76b6 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -241,7 +241,7 @@ extern bool mips_pad_arg_upward (enum machine_mode, const_tree);
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);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 498dc27..e4e93e6 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -6916,7 +6916,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
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 ();
}
}
@@ -7249,9 +7249,10 @@ mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
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
@@ -7261,6 +7262,16 @@ mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
&& 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)
@@ -7280,6 +7291,16 @@ mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
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;
}
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index b6b2beb..0edc9d9 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3657,7 +3657,8 @@
{
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)
@@ -3694,7 +3695,8 @@
{
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])))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9450484..25ca135 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2012-07-21 Andrew Pinski <apinski@cavium.com>
+
+ * gcc.target/mips/unaligned-1.c: New testcase.
+
2012-07-21 Hans-Peter Nilsson <hp@axis.com>
* gcc.c-torture/execute/20101011-1.c (DO_TEST): Define as 0 for CRIS.
diff --git a/gcc/testsuite/gcc.target/mips/unaligned-1.c b/gcc/testsuite/gcc.target/mips/unaligned-1.c
new file mode 100644
index 0000000..23b6c8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/unaligned-1.c
@@ -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;
+}