Home | History | Annotate | Download | only in amd64
      1 /* https://bugs.kde.org/show_bug.cgi?id=308627 */
      2 
      3 #include "../../memcheck.h"
      4 
      5 #include <stdio.h>
      6 
      7 typedef unsigned long ULong;
      8 
      9 typedef struct {
     10    ULong w64[2];  /* Note: little-endian */
     11 } V128;
     12 
     13 static int getMSBs16x8(V128 v)
     14 {
     15    int result;
     16    __asm__("movups %1,%%xmm6\n"
     17            "\tpmovmskb %%xmm6,%0\n"
     18            : "=r" (result) : "m" (v) : "xmm6");
     19    return result;
     20 }
     21 
     22 /* Set the V bits on the data at "addr".  Note the convention: A zero
     23    bit means "defined"; 1 means "undefined". */
     24 static void set_vbits(V128 *addr, V128 vbits)
     25 {
     26    int i;
     27    for (i=0 ; i<2 ; ++i) {
     28       (void)VALGRIND_SET_VBITS(&addr->w64[i], &vbits.w64[i], sizeof(vbits.w64[i]));
     29    }
     30 }
     31 
     32 static void print(V128 vbits, V128 val, int bit, int result)
     33 {
     34    printf("vbits=0x%016lx%016lx val=0x%016lx%016lx bit=%d result=%d\n",
     35           vbits.w64[1], vbits.w64[0], val.w64[1], val.w64[0],
     36           bit, result);
     37 }
     38 
     39 /* Use a value that we know is invalid. */
     40 static void use(int index, int invalid)
     41 {
     42    /* Convince GCC it does not know what is in "invalid" so it cannot
     43       possibly optimize away the conditional branch below. */
     44    __asm__ ("" : "=r" (invalid) : "0" (invalid));
     45 
     46    /* Create a conditional branch on which our output depends, so that
     47       memcheck cannot possibly optimize it away, either. */
     48    fprintf(stderr, "%d: Invalid value is %s\n",
     49            index, invalid ? "true" : "false");
     50 }
     51 
     52 static void doit(ULong vbits_hi, ULong vbits_lo, ULong val_hi, ULong val_lo)
     53 {
     54    V128 vbits = { { vbits_lo, vbits_hi } };
     55    V128 val = { { val_lo, val_hi } };
     56 
     57    /* Since we are about to mark "val" partially undefined, make a
     58       copy that we can use without generating a memcheck warning. */
     59    V128 val_copy = val;
     60 
     61    set_vbits(&val, vbits);
     62 
     63    int result = getMSBs16x8(val);
     64 
     65    int vbits_mask = getMSBs16x8(vbits);
     66 
     67    int bit = 0; ULong mask = (1UL << bit);
     68    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     69    else use(bit, result & mask);
     70 
     71    bit = 1; mask = (1UL << bit);
     72    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     73    else use(bit, result & mask);
     74 
     75    bit = 2; mask = (1UL << bit);
     76    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     77    else use(bit, result & mask);
     78 
     79    bit = 3; mask = (1UL << bit);
     80    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     81    else use(bit, result & mask);
     82 
     83    bit = 4; mask = (1UL << bit);
     84    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     85    else use(bit, result & mask);
     86 
     87    bit = 5; mask = (1UL << bit);
     88    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     89    else use(bit, result & mask);
     90 
     91    bit = 6 ; mask = (1UL << bit);
     92    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     93    else use(bit, result & mask);
     94 
     95    bit = 7 ; mask = (1UL << bit);
     96    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
     97    else use(bit, result & mask);
     98 
     99    bit = 8 ; mask = (1UL << bit);
    100    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    101    else use(bit, result & mask);
    102 
    103    bit = 9 ; mask = (1UL << bit);
    104    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    105    else use(bit, result & mask);
    106 
    107    bit = 10 ; mask = (1UL << bit);
    108    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    109    else use(bit, result & mask);
    110 
    111    bit = 11 ; mask = (1UL << bit);
    112    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    113    else use(bit, result & mask);
    114 
    115    bit = 12 ; mask = (1UL << bit);
    116    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    117    else use(bit, result & mask);
    118 
    119    bit = 13 ; mask = (1UL << bit);
    120    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    121    else use(bit, result & mask);
    122 
    123    bit = 14 ; mask = (1UL << bit);
    124    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    125    else use(bit, result & mask);
    126 
    127    bit = 15 ; mask = (1UL << bit);
    128    if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
    129    else use(bit, result & mask);
    130 }
    131 
    132 int main(int argc, char *argv[])
    133 {
    134    doit(0x0000000000000000, 0x0000000000000000,
    135         0x0000000000000000, 0x0000000000000000);
    136 
    137    doit(0x0707070707070707, 0x0707070707070707,
    138         0x0000000000000000, 0x0000000000000000);
    139 
    140    doit(0x8080808080808080, 0x8080808080808080,
    141         0x0000000000000000, 0x0000000000000000);
    142 
    143    doit(0x13579BDF02468ACE, 0xFEDCBA9876543210,
    144         0xFEEDFACEDEADBEEF, 0xFEE1DEADDABBAD00);
    145 
    146    return 0;
    147 }
    148