From: Julian Seward Date: Mon, 12 Mar 2007 02:10:23 +0000 (+0000) Subject: Add a test for vex ppc64 code generation bug fixed by vex r1739 X-Git-Tag: svn/VALGRIND_3_3_0~321 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3235d88de86e3ec5b7bba55f9401b0e5c3e5eb5d;p=thirdparty%2Fvalgrind.git Add a test for vex ppc64 code generation bug fixed by vex r1739 (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 --- diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am index 3a6974cc78..ef4861ce99 100644 --- a/none/tests/ppc64/Makefile.am +++ b/none/tests/ppc64/Makefile.am @@ -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 index 0000000000..5e6599de13 --- /dev/null +++ b/none/tests/ppc64/std_reg_imm.c @@ -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 +#include +#include + +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 index 0000000000..e69de29bb2 diff --git a/none/tests/ppc64/std_reg_imm.stdout.exp b/none/tests/ppc64/std_reg_imm.stdout.exp new file mode 100644 index 0000000000..69bf7fbd66 --- /dev/null +++ b/none/tests/ppc64/std_reg_imm.stdout.exp @@ -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 index 0000000000..4e8d3eba2b --- /dev/null +++ b/none/tests/ppc64/std_reg_imm.vgtest @@ -0,0 +1,2 @@ +prog: std_reg_imm +vgopts: -q