]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a test for vex ppc64 code generation bug fixed by vex r1739
authorJulian Seward <jseward@acm.org>
Mon, 12 Mar 2007 02:10:23 +0000 (02:10 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 12 Mar 2007 02:10:23 +0000 (02:10 +0000)
(When generating 64-bit code, ensure that any addresses used in 4 or 8
byte loads or stores of the form reg+imm have the lowest 2 bits of imm
set to zero, so that they can safely be used in ld/ldu/lda/std/stdu
instructions.)

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6645

none/tests/ppc64/Makefile.am
none/tests/ppc64/std_reg_imm.c [new file with mode: 0644]
none/tests/ppc64/std_reg_imm.stderr.exp [new file with mode: 0644]
none/tests/ppc64/std_reg_imm.stdout.exp [new file with mode: 0644]
none/tests/ppc64/std_reg_imm.vgtest [new file with mode: 0644]

index 3a6974cc787c6115ff643ea93042d4884cc1081b..ef4861ce99d786ae438885197ff533c7f242671e 100644 (file)
@@ -6,11 +6,12 @@ EXTRA_DIST = $(noinst_SCRIPTS) \
        jm-fp.stderr.exp  jm-fp.stdout.exp  jm-fp.vgtest \
        jm-vmx.stderr.exp jm-vmx.stdout.exp jm-vmx.vgtest \
        lsw.stderr.exp lsw.stdout.exp lsw.vgtest \
+       std_reg_imm.vgtest std_reg_imm.stderr.exp std_reg_imm.stdout.exp \
        round.stderr.exp round.stdout.exp round.vgtest \
        twi_tdi.stderr.exp twi_tdi.stdout.exp twi_tdi.vgtest
 
 check_PROGRAMS = \
-       jm-insns lsw round twi_tdi
+       jm-insns lsw round std_reg_imm twi_tdi
 
 AM_CFLAGS   = $(WERROR) -Winline -Wall -Wshadow -g -I$(top_srcdir)/include \
                @FLAG_M64@
diff --git a/none/tests/ppc64/std_reg_imm.c b/none/tests/ppc64/std_reg_imm.c
new file mode 100644 (file)
index 0000000..5e6599d
--- /dev/null
@@ -0,0 +1,79 @@
+
+/*
+This is a regression test for the following problem, noticed by
+Greg Parker:
+
+vex ppc64 generates bad code for instruction sequences like this:
+
+    li    r0, 2
+    stdx  r3, r1, r0
+
+gcc emits code like this when manipulating packed structures 
+with 8-byte fields on 2-byte boundaries.
+
+First, vex's optimizer substitutes a constant 0x2 for r0:
+
+    ------ IMark(0x100000F34, 4) ------
+    PUT(1024) = 0x100000F34:I64
+    t3 = GET:I64(24)
+    t14 = GET:I64(8)
+    t13 = Add64(t14,0x2:I64)
+    STbe(t13) = t3
+
+Then instruction selection chooses `std` with an index not divisible by 4:
+
+    -- STbe(Add64(GET:I64(8),0x2:I64)) = GET:I64(24)
+    ldz %vR22,8(%r31)
+    ldz %vR23,24(%r31)
+    std %vR23,2(%vR22)
+
+Finally, the assembler silently strips the index&3 part, 
+because `std` can't encode that:
+
+    std %r6,2(%r5)
+    F8 C5 00 00 
+
+...but 0xF8C50000 is `std r6, 0(r5)`, which writes to the wrong address.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+typedef 
+struct __attribute__ ((__packed__)) {
+  char before[2];
+  unsigned long long int w64;
+  char after[6];
+}
+T;
+
+void foo (T* t, unsigned long long int w)
+{
+  __asm__ __volatile__(
+     "stdx %0,%1,%2"
+     : : "b"(w), "b"(t), "b"(2) : "memory"
+  );
+}
+
+int main ( void )
+{
+  T* t;
+  unsigned char* p;
+  int i;
+  assert(sizeof(T) == 16);
+  t = calloc(sizeof(T),1);
+  assert(t);
+  /* check t is 8-aligned.  This causes the write done by 'foo' to be
+     misaligned by 2 as desired, triggering the bug. */
+  assert(0 == (((unsigned long)t) & 7));
+  foo(t, 0x1122334455667788);
+  p = (unsigned char*)t;
+  for (i = 0; i < 16; i++)
+    if (p[i] == 0)
+      printf(".."); 
+    else
+      printf("%02x", (int)p[i]);
+  printf("\n");
+  return 0;
+}
diff --git a/none/tests/ppc64/std_reg_imm.stderr.exp b/none/tests/ppc64/std_reg_imm.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/none/tests/ppc64/std_reg_imm.stdout.exp b/none/tests/ppc64/std_reg_imm.stdout.exp
new file mode 100644 (file)
index 0000000..69bf7fb
--- /dev/null
@@ -0,0 +1 @@
+....1122334455667788............
diff --git a/none/tests/ppc64/std_reg_imm.vgtest b/none/tests/ppc64/std_reg_imm.vgtest
new file mode 100644 (file)
index 0000000..4e8d3eb
--- /dev/null
@@ -0,0 +1,2 @@
+prog: std_reg_imm
+vgopts: -q