1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* https://bugs.kde.org/show_bug.cgi?id=308627 */
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "../../memcheck.h"
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h>
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef unsigned long ULong;
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtypedef struct {
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong w64[2];  /* Note: little-endian */
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} V128;
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int getMSBs16x8(V128 v)
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int result;
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   __asm__("movups %1,%%xmm6\n"
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           "\tpmovmskb %%xmm6,%0\n"
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           : "=r" (result) : "m" (v) : "xmm6");
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return result;
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Set the V bits on the data at "addr".  Note the convention: A zero
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit means "defined"; 1 means "undefined". */
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void set_vbits(V128 *addr, V128 vbits)
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int i;
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i=0 ; i<2 ; ++i) {
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      (void)VALGRIND_SET_VBITS(&addr->w64[i], &vbits.w64[i], sizeof(vbits.w64[i]));
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void print(V128 vbits, V128 val, int bit, int result)
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   printf("vbits=0x%016lx%016lx val=0x%016lx%016lx bit=%d result=%d\n",
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          vbits.w64[1], vbits.w64[0], val.w64[1], val.w64[0],
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          bit, result);
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Use a value that we know is invalid. */
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void use(int index, int invalid)
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Convince GCC it does not know what is in "invalid" so it cannot
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      possibly optimize away the conditional branch below. */
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   __asm__ ("" : "=r" (invalid) : "0" (invalid));
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Create a conditional branch on which our output depends, so that
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      memcheck cannot possibly optimize it away, either. */
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   fprintf(stderr, "%d: Invalid value is %s\n",
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           index, invalid ? "true" : "false");
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void doit(ULong vbits_hi, ULong vbits_lo, ULong val_hi, ULong val_lo)
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   V128 vbits = { { vbits_lo, vbits_hi } };
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   V128 val = { { val_lo, val_hi } };
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Since we are about to mark "val" partially undefined, make a
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      copy that we can use without generating a memcheck warning. */
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   V128 val_copy = val;
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   set_vbits(&val, vbits);
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int result = getMSBs16x8(val);
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int vbits_mask = getMSBs16x8(vbits);
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int bit = 0; ULong mask = (1UL << bit);
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 1; mask = (1UL << bit);
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 2; mask = (1UL << bit);
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 3; mask = (1UL << bit);
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 4; mask = (1UL << bit);
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 5; mask = (1UL << bit);
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 6 ; mask = (1UL << bit);
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 7 ; mask = (1UL << bit);
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 8 ; mask = (1UL << bit);
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 9 ; mask = (1UL << bit);
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 10 ; mask = (1UL << bit);
108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 11 ; mask = (1UL << bit);
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 12 ; mask = (1UL << bit);
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 13 ; mask = (1UL << bit);
120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 14 ; mask = (1UL << bit);
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   bit = 15 ; mask = (1UL << bit);
128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else use(bit, result & mask);
130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint main(int argc, char *argv[])
133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   doit(0x0000000000000000, 0x0000000000000000,
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        0x0000000000000000, 0x0000000000000000);
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   doit(0x0707070707070707, 0x0707070707070707,
138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        0x0000000000000000, 0x0000000000000000);
139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   doit(0x8080808080808080, 0x8080808080808080,
141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        0x0000000000000000, 0x0000000000000000);
142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   doit(0x13579BDF02468ACE, 0xFEDCBA9876543210,
144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        0xFEEDFACEDEADBEEF, 0xFEE1DEADDABBAD00);
145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return 0;
147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
148