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