mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-06 19:54:18 +00:00
(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
80 lines
1.7 KiB
C
80 lines
1.7 KiB
C
|
|
/*
|
|
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;
|
|
}
|