Home | History | Annotate | Download | only in amd64
      1 /* https://bugs.kde.org/show_bug.cgi?id=308626 */
      2 
      3 #include "../../memcheck.h"
      4 
      5 #include <stdio.h>
      6 #include <assert.h>
      7 
      8 typedef unsigned int UInt;
      9 
     10 /* Calculate ctz(x) using bsfl instruction. */
     11 static int ctz(UInt x)
     12 {
     13    assert(sizeof(UInt) == 4);
     14    int result=8*sizeof(UInt);
     15    /* BSFL does not change the destination when the input is zero. */
     16    asm("bsfl %1,%0" : "=r" (result) : "r" (x), "0" (result) : "cc");
     17    return result;
     18 }
     19 
     20 /* Set the V bits at "addr".  Note the convention: A zero bit means
     21    "defined"; 1 means "undefined". */
     22 static void set_vbits(UInt *addr, UInt vbits)
     23 {
     24    (void)VALGRIND_SET_VBITS(addr, &vbits, sizeof(unsigned));
     25 }
     26 
     27 static void doit(unsigned vbits, unsigned val)
     28 {
     29    /* Since we are about to mark "val" partially undefined, make a
     30       copy that we can use without generating a memcheck warning. */
     31    unsigned val_copy = val;
     32 
     33    /* Mark "val" partially undefined. */
     34    set_vbits(&val, vbits);
     35 
     36    /* Convince GCC it does not know what is in "val" so it does not
     37       optimize away any uses of it. */
     38    __asm__ ("" : "=r" (val) : "0" (val));
     39 
     40    int result = ctz(val);
     41 
     42    /* The following code is carefully constructed: The conditional
     43       itself should generate a memcheck warning if and only if it is
     44       false.  (Specifically, if the first "1" bit in val comes before
     45       the first "undefined" bit, or the entire word is valid, then
     46       ctz(val) is defined; else it is undefined.) */
     47    if (result < ctz(vbits) || vbits == 0) {
     48       /* There should be no memcheck warning on this printf, since
     49          "result" is fully-defined in this case. */
     50       printf("vbits=0x%08x ctz(0x%08x)=%d\n", vbits, val_copy, result);
     51    }
     52    else {
     53        /* memcheck should have output a warning.  But we want
     54           something here so there is no possibiliy of Valgrind
     55           optimizing out the conditional itself. */
     56        fprintf(stderr, "0x%08x: Invalid value is %d\n", val_copy,
     57                ctz(val_copy));
     58    }
     59 }
     60 
     61 int main(int argc, char *argv[])
     62 {
     63    doit(0x00000000, 0x00000000);
     64    doit(0x00000000, 0x00000001);
     65    doit(0x00000001, 0x00000000);
     66    doit(0x00000001, 0x00000001);
     67 
     68    /* valid bit / data bit sandwich */
     69    doit(0x00000090, 0x00000040);
     70    doit(0x00000040, 0x00000090);
     71 
     72    /* Interleaving */
     73    doit(0x00000500, 0x00000a00);
     74    doit(0x00000a00, 0x00000500);
     75 
     76    doit(0x000f0000, 0x001e0000);
     77    doit(0x001e0000, 0x000f0000);
     78 
     79    doit(0xffffffff, 0xffffffff);
     80    doit(0xfffffffe, 0xffffffff);
     81    doit(0xffffffff, 0xfffffffe);
     82    doit(0xfffffffe, 0xfffffffe);
     83 
     84    return 0;
     85 }
     86