mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
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
This commit is contained in:
parent
34454d5464
commit
3235d88de8
@ -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@
|
||||
|
||||
79
none/tests/ppc64/std_reg_imm.c
Normal file
79
none/tests/ppc64/std_reg_imm.c
Normal file
@ -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;
|
||||
}
|
||||
0
none/tests/ppc64/std_reg_imm.stderr.exp
Normal file
0
none/tests/ppc64/std_reg_imm.stderr.exp
Normal file
1
none/tests/ppc64/std_reg_imm.stdout.exp
Normal file
1
none/tests/ppc64/std_reg_imm.stdout.exp
Normal file
@ -0,0 +1 @@
|
||||
....1122334455667788............
|
||||
2
none/tests/ppc64/std_reg_imm.vgtest
Normal file
2
none/tests/ppc64/std_reg_imm.vgtest
Normal file
@ -0,0 +1,2 @@
|
||||
prog: std_reg_imm
|
||||
vgopts: -q
|
||||
Loading…
x
Reference in New Issue
Block a user