Home | History | Annotate | Download | only in ppc64
      1 
      2 /*
      3 This is a regression test for the following problem, noticed by
      4 Greg Parker:
      5 
      6 vex ppc64 generates bad code for instruction sequences like this:
      7 
      8     li    r0, 2
      9     stdx  r3, r1, r0
     10 
     11 gcc emits code like this when manipulating packed structures
     12 with 8-byte fields on 2-byte boundaries.
     13 
     14 First, vex's optimizer substitutes a constant 0x2 for r0:
     15 
     16     ------ IMark(0x100000F34, 4) ------
     17     PUT(1024) = 0x100000F34:I64
     18     t3 = GET:I64(24)
     19     t14 = GET:I64(8)
     20     t13 = Add64(t14,0x2:I64)
     21     STbe(t13) = t3
     22 
     23 Then instruction selection chooses `std` with an index not divisible by 4:
     24 
     25     -- STbe(Add64(GET:I64(8),0x2:I64)) = GET:I64(24)
     26     ldz %vR22,8(%r31)
     27     ldz %vR23,24(%r31)
     28     std %vR23,2(%vR22)
     29 
     30 Finally, the assembler silently strips the index&3 part,
     31 because `std` can't encode that:
     32 
     33     std %r6,2(%r5)
     34     F8 C5 00 00
     35 
     36 ...but 0xF8C50000 is `std r6, 0(r5)`, which writes to the wrong address.
     37 */
     38 
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <assert.h>
     42 
     43 typedef
     44 struct __attribute__ ((__packed__)) {
     45   char before[2];
     46   unsigned long long int w64;
     47   char after[6];
     48 }
     49 T;
     50 
     51 void foo (T* t, unsigned long long int w)
     52 {
     53   __asm__ __volatile__(
     54      "stdx %0,%1,%2"
     55      : : "b"(w), "b"(t), "b"(2) : "memory"
     56   );
     57 }
     58 
     59 int main ( void )
     60 {
     61   T* t;
     62   unsigned char* p;
     63   int i;
     64   assert(sizeof(T) == 16);
     65   t = calloc(sizeof(T),1);
     66   assert(t);
     67   /* check t is 8-aligned.  This causes the write done by 'foo' to be
     68      misaligned by 2 as desired, triggering the bug. */
     69   assert(0 == (((unsigned long)t) & 7));
     70   foo(t, 0x1122334455667788);
     71   p = (unsigned char*)t;
     72   for (i = 0; i < 16; i++)
     73     if (p[i] == 0)
     74       printf("..");
     75     else
     76       printf("%02x", (int)p[i]);
     77   printf("\n");
     78   return 0;
     79 }
     80