This patch by adrian.sendroiu@freescale.com fixes the lrmw and stmw
instructions.
The patch also adds ppc32 and ppc64 test cases for the instructions.
The patch is a fix for bugzilla 329956 "valgrind crashes when lmw/stmw instructions are used on ppc64".
The VEX code commit is 2802
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13780 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/none/tests/ppc32/Makefile.am b/none/tests/ppc32/Makefile.am
index 4f581b6..08486cd 100644
--- a/none/tests/ppc32/Makefile.am
+++ b/none/tests/ppc32/Makefile.am
@@ -43,7 +43,8 @@
jm_int_isa_2_07.stderr.exp jm_int_isa_2_07.stdout.exp jm_int_isa_2_07.vgtest \
test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest \
test_tm.stderr.exp test_tm.stdout.exp test_tm.vgtest \
- test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest
+ test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest \
+ ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest
check_PROGRAMS = \
@@ -59,7 +60,8 @@
test_isa_2_07_part1 \
test_isa_2_07_part2 \
test_tm \
- test_touch_tm
+ test_touch_tm \
+ ldst_multiple
AM_CFLAGS += @FLAG_M32@
AM_CXXFLAGS += @FLAG_M32@
diff --git a/none/tests/ppc32/ldst_multiple.c b/none/tests/ppc32/ldst_multiple.c
new file mode 100644
index 0000000..6c610b9
--- /dev/null
+++ b/none/tests/ppc32/ldst_multiple.c
@@ -0,0 +1,191 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#ifndef __powerpc64__
+typedef uint32_t HWord_t;
+#else
+typedef uint64_t HWord_t;
+#endif
+
+typedef void (*test_func_t)();
+
+typedef struct test_table {
+ test_func_t func;
+ char *name;
+} test_table_t;
+
+static uint32_t values[] = {
+ 0x6efbcfdf,
+ 0xd16c2fd4,
+ 0xf9dc1743,
+ 0xa5aa0bd4,
+ 0x6c8f0c14,
+ 0x69a24188,
+ 0x53b57f1b,
+};
+
+register HWord_t r27 asm("r27");
+register HWord_t r28 asm("r28");
+register HWord_t r29 asm("r29");
+register HWord_t r30 asm("r30");
+register HWord_t r31 asm("r31");
+
+register HWord_t r14 asm("r14");
+
+HWord_t temp[5];
+
+#ifdef __powerpc64__
+
+#define SAVE_REGS(addr) \
+ asm volatile( \
+ " std 27, 0(%0) \n" \
+ " std 28, 8(%0) \n" \
+ " std 29, 16(%0) \n" \
+ " std 30, 24(%0) \n" \
+ " std 31, 32(%0) \n" \
+ ::"b"(addr))
+
+#define RESTORE_REGS(addr) \
+ asm volatile( \
+ " ld 27, 0(%0) \n" \
+ " ld 28, 8(%0) \n" \
+ " ld 29, 16(%0) \n" \
+ " ld 30, 24(%0) \n" \
+ " ld 31, 32(%0) \n" \
+ ::"b"(addr))
+
+#else /* !__powerpc64__ */
+
+#define SAVE_REGS(addr) \
+ asm volatile( \
+ " stw 27, 0(%0) \n" \
+ " stw 28, 4(%0) \n" \
+ " stw 29, 8(%0) \n" \
+ " stw 30, 12(%0) \n" \
+ " stw 31, 16(%0) \n" \
+ ::"b"(addr))
+
+#define RESTORE_REGS(addr) \
+ asm volatile( \
+ " lwz 27, 0(%0) \n" \
+ " lwz 28, 4(%0) \n" \
+ " lwz 29, 8(%0) \n" \
+ " lwz 30, 12(%0) \n" \
+ " lwz 31, 16(%0) \n" \
+ ::"b"(addr))
+
+#endif /* __powerpc64__ */
+
+/*
+ * gcc is not happy if we modify r31 (the frame pointer) behind its back
+ * so we omit it
+ */
+static void __attribute__((optimize("-fomit-frame-pointer"))) test_lmw(void)
+{
+ r14 = (HWord_t)values;
+
+ /* save r27 - r31 */
+ SAVE_REGS(temp);
+
+ /* load r27 - r31 */
+ asm volatile(
+ " lmw %r27, 0(%r14) \n");
+
+#ifdef __powerpc64__
+ printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
+#else
+ printf("lmw => %08x %08x %08x %08x %08x\n",
+#endif
+ r27, r28, r29, r30, r31);
+
+ /*
+ * test load multiple with nonzero immediate offset
+ * load the last two values into r30 - r31.
+ * r27 - r29 should remain the same
+ */
+ asm volatile(
+ " lmw %r30, 20(%r14) \n");
+
+#ifdef __powerpc64__
+ printf("lmw => %016lx %016lx %016lx %016lx %016lx\n",
+#else
+ printf("lmw => %08x %08x %08x %08x %08x\n",
+#endif
+ r27, r28, r29, r30, r31);
+
+ /* restore r27 - r31 */
+ RESTORE_REGS(temp);
+}
+
+/*
+ * gcc is not happy if we modify r31 (the frame pointer) behind its back
+ * so we omit it
+ */
+static void __attribute__((optimize("-fomit-frame-pointer"))) test_stmw(void)
+{
+ uint32_t result[7] = { 0 };
+ int i;
+
+ SAVE_REGS(temp);
+
+#ifdef __powerpc64__
+ asm volatile(
+ " lwz 27, 0(%0) \n" \
+ " lwz 28, 4(%0) \n" \
+ " lwz 29, 8(%0) \n" \
+ " lwz 30, 12(%0) \n" \
+ " lwz 31, 16(%0) \n" \
+ ::"b"(values));
+#else
+ RESTORE_REGS(values);
+#endif
+
+ r14 = (HWord_t)&result;
+
+ /* store r27 - r31 */
+ asm volatile(
+ " stmw %r27, 0(%r14) \n");
+
+ printf("stmw => ");
+ for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
+ printf("%08x ", result[i]);
+
+ printf("\n");
+
+ /*
+ * test store multiple with nonzero immediate offset
+ * store r30 - r31 into the last two places in the array
+ * the rest of the array should remain the same
+ */
+ asm volatile(
+ " stmw %r30, 20(%r14) \n");
+
+ printf("stmw => ");
+ for (i = 0; i < sizeof(result) / sizeof(result[0]); i++)
+ printf("%08x ", result[i]);
+
+ printf("\n");
+
+ RESTORE_REGS(temp);
+}
+
+static test_table_t all_tests[] = {
+ { &test_lmw,
+ "Test Load Multiple instruction" },
+ { &test_stmw,
+ "Test Store Multiple instruction" },
+ { NULL, NULL },
+};
+
+int main(void)
+{
+ test_func_t func;
+ int i = 0;
+
+ while ((func = all_tests[i].func)) {
+ (*func)();
+ i++;
+ }
+
+ return 0;
+}
diff --git a/none/tests/ppc32/ldst_multiple.stderr.exp b/none/tests/ppc32/ldst_multiple.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/ppc32/ldst_multiple.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/ppc32/ldst_multiple.stdout.exp b/none/tests/ppc32/ldst_multiple.stdout.exp
new file mode 100644
index 0000000..f3579dc
--- /dev/null
+++ b/none/tests/ppc32/ldst_multiple.stdout.exp
@@ -0,0 +1,4 @@
+lmw => 6efbcfdf d16c2fd4 f9dc1743 a5aa0bd4 6c8f0c14
+lmw => 6efbcfdf d16c2fd4 f9dc1743 69a24188 53b57f1b
+stmw => 6efbcfdf d16c2fd4 f9dc1743 a5aa0bd4 6c8f0c14 00000000 00000000
+stmw => 6efbcfdf d16c2fd4 f9dc1743 a5aa0bd4 6c8f0c14 a5aa0bd4 6c8f0c14
diff --git a/none/tests/ppc32/ldst_multiple.vgtest b/none/tests/ppc32/ldst_multiple.vgtest
new file mode 100644
index 0000000..87e668e
--- /dev/null
+++ b/none/tests/ppc32/ldst_multiple.vgtest
@@ -0,0 +1 @@
+prog: ldst_multiple
diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am
index 93c6fe1..fc43f08 100644
--- a/none/tests/ppc64/Makefile.am
+++ b/none/tests/ppc64/Makefile.am
@@ -31,7 +31,8 @@
jm_int_isa_2_07.stderr.exp jm_int_isa_2_07.stdout.exp jm_int_isa_2_07.vgtest \
test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest \
test_tm.stderr.exp test_tm.stdout.exp test_tm.vgtest \
- test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest
+ test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest \
+ ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest
check_PROGRAMS = \
allexec \
@@ -39,7 +40,7 @@
power6_mf_gpr test_isa_2_06_part1 test_isa_2_06_part2 \
test_isa_2_06_part3 test_dfp1 test_dfp2 test_dfp3 test_dfp4 \
test_dfp5 test_isa_2_07_part1 test_isa_2_07_part2 \
- test_tm test_touch_tm
+ test_tm test_touch_tm ldst_multiple
AM_CFLAGS += @FLAG_M64@
AM_CXXFLAGS += @FLAG_M64@
diff --git a/none/tests/ppc64/ldst_multiple.c b/none/tests/ppc64/ldst_multiple.c
new file mode 120000
index 0000000..d155824
--- /dev/null
+++ b/none/tests/ppc64/ldst_multiple.c
@@ -0,0 +1 @@
+../ppc32/ldst_multiple.c
\ No newline at end of file
diff --git a/none/tests/ppc64/ldst_multiple.stderr.exp b/none/tests/ppc64/ldst_multiple.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/ppc64/ldst_multiple.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/ppc64/ldst_multiple.stdout.exp b/none/tests/ppc64/ldst_multiple.stdout.exp
new file mode 100644
index 0000000..31f923b
--- /dev/null
+++ b/none/tests/ppc64/ldst_multiple.stdout.exp
@@ -0,0 +1,4 @@
+lmw => 000000006efbcfdf 00000000d16c2fd4 00000000f9dc1743 00000000a5aa0bd4 000000006c8f0c14
+lmw => 000000006efbcfdf 00000000d16c2fd4 00000000f9dc1743 0000000069a24188 0000000053b57f1b
+stmw => 6efbcfdf d16c2fd4 f9dc1743 a5aa0bd4 6c8f0c14 00000000 00000000
+stmw => 6efbcfdf d16c2fd4 f9dc1743 a5aa0bd4 6c8f0c14 a5aa0bd4 6c8f0c14
diff --git a/none/tests/ppc64/ldst_multiple.vgtest b/none/tests/ppc64/ldst_multiple.vgtest
new file mode 100644
index 0000000..87e668e
--- /dev/null
+++ b/none/tests/ppc64/ldst_multiple.vgtest
@@ -0,0 +1 @@
+prog: ldst_multiple