19b826d678462471e8112096c291d95cb61e99364sewardj/* https://bugs.kde.org/show_bug.cgi?id=308627 */
29b826d678462471e8112096c291d95cb61e99364sewardj
39b826d678462471e8112096c291d95cb61e99364sewardj#include "../../memcheck.h"
49b826d678462471e8112096c291d95cb61e99364sewardj
59b826d678462471e8112096c291d95cb61e99364sewardj#include <stdio.h>
69b826d678462471e8112096c291d95cb61e99364sewardj
79b826d678462471e8112096c291d95cb61e99364sewardjtypedef unsigned long ULong;
89b826d678462471e8112096c291d95cb61e99364sewardj
99b826d678462471e8112096c291d95cb61e99364sewardjtypedef struct {
109b826d678462471e8112096c291d95cb61e99364sewardj   ULong w64[2];  /* Note: little-endian */
119b826d678462471e8112096c291d95cb61e99364sewardj} V128;
129b826d678462471e8112096c291d95cb61e99364sewardj
139b826d678462471e8112096c291d95cb61e99364sewardjstatic int getMSBs16x8(V128 v)
149b826d678462471e8112096c291d95cb61e99364sewardj{
159b826d678462471e8112096c291d95cb61e99364sewardj   int result;
169b826d678462471e8112096c291d95cb61e99364sewardj   __asm__("movups %1,%%xmm6\n"
179b826d678462471e8112096c291d95cb61e99364sewardj           "\tpmovmskb %%xmm6,%0\n"
189b826d678462471e8112096c291d95cb61e99364sewardj           : "=r" (result) : "m" (v) : "xmm6");
199b826d678462471e8112096c291d95cb61e99364sewardj   return result;
209b826d678462471e8112096c291d95cb61e99364sewardj}
219b826d678462471e8112096c291d95cb61e99364sewardj
229b826d678462471e8112096c291d95cb61e99364sewardj/* Set the V bits on the data at "addr".  Note the convention: A zero
239b826d678462471e8112096c291d95cb61e99364sewardj   bit means "defined"; 1 means "undefined". */
249b826d678462471e8112096c291d95cb61e99364sewardjstatic void set_vbits(V128 *addr, V128 vbits)
259b826d678462471e8112096c291d95cb61e99364sewardj{
269b826d678462471e8112096c291d95cb61e99364sewardj   int i;
279b826d678462471e8112096c291d95cb61e99364sewardj   for (i=0 ; i<2 ; ++i) {
28e593275d41859efb73a2d0c7fc88473000f52c53sewardj      (void)VALGRIND_SET_VBITS(&addr->w64[i], &vbits.w64[i], sizeof(vbits.w64[i]));
299b826d678462471e8112096c291d95cb61e99364sewardj   }
309b826d678462471e8112096c291d95cb61e99364sewardj}
319b826d678462471e8112096c291d95cb61e99364sewardj
329b826d678462471e8112096c291d95cb61e99364sewardjstatic void print(V128 vbits, V128 val, int bit, int result)
339b826d678462471e8112096c291d95cb61e99364sewardj{
349b826d678462471e8112096c291d95cb61e99364sewardj   printf("vbits=0x%016lx%016lx val=0x%016lx%016lx bit=%d result=%d\n",
359b826d678462471e8112096c291d95cb61e99364sewardj          vbits.w64[1], vbits.w64[0], val.w64[1], val.w64[0],
369b826d678462471e8112096c291d95cb61e99364sewardj          bit, result);
379b826d678462471e8112096c291d95cb61e99364sewardj}
389b826d678462471e8112096c291d95cb61e99364sewardj
399b826d678462471e8112096c291d95cb61e99364sewardj/* Use a value that we know is invalid. */
409b826d678462471e8112096c291d95cb61e99364sewardjstatic void use(int index, int invalid)
419b826d678462471e8112096c291d95cb61e99364sewardj{
429b826d678462471e8112096c291d95cb61e99364sewardj   /* Convince GCC it does not know what is in "invalid" so it cannot
439b826d678462471e8112096c291d95cb61e99364sewardj      possibly optimize away the conditional branch below. */
449b826d678462471e8112096c291d95cb61e99364sewardj   __asm__ ("" : "=r" (invalid) : "0" (invalid));
459b826d678462471e8112096c291d95cb61e99364sewardj
469b826d678462471e8112096c291d95cb61e99364sewardj   /* Create a conditional branch on which our output depends, so that
479b826d678462471e8112096c291d95cb61e99364sewardj      memcheck cannot possibly optimize it away, either. */
489b826d678462471e8112096c291d95cb61e99364sewardj   fprintf(stderr, "%d: Invalid value is %s\n",
499b826d678462471e8112096c291d95cb61e99364sewardj           index, invalid ? "true" : "false");
509b826d678462471e8112096c291d95cb61e99364sewardj}
519b826d678462471e8112096c291d95cb61e99364sewardj
529b826d678462471e8112096c291d95cb61e99364sewardjstatic void doit(ULong vbits_hi, ULong vbits_lo, ULong val_hi, ULong val_lo)
539b826d678462471e8112096c291d95cb61e99364sewardj{
549b826d678462471e8112096c291d95cb61e99364sewardj   V128 vbits = { { vbits_lo, vbits_hi } };
559b826d678462471e8112096c291d95cb61e99364sewardj   V128 val = { { val_lo, val_hi } };
569b826d678462471e8112096c291d95cb61e99364sewardj
579b826d678462471e8112096c291d95cb61e99364sewardj   /* Since we are about to mark "val" partially undefined, make a
589b826d678462471e8112096c291d95cb61e99364sewardj      copy that we can use without generating a memcheck warning. */
599b826d678462471e8112096c291d95cb61e99364sewardj   V128 val_copy = val;
609b826d678462471e8112096c291d95cb61e99364sewardj
619b826d678462471e8112096c291d95cb61e99364sewardj   set_vbits(&val, vbits);
629b826d678462471e8112096c291d95cb61e99364sewardj
639b826d678462471e8112096c291d95cb61e99364sewardj   int result = getMSBs16x8(val);
649b826d678462471e8112096c291d95cb61e99364sewardj
659b826d678462471e8112096c291d95cb61e99364sewardj   int vbits_mask = getMSBs16x8(vbits);
669b826d678462471e8112096c291d95cb61e99364sewardj
679b826d678462471e8112096c291d95cb61e99364sewardj   int bit = 0; ULong mask = (1UL << bit);
689b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
699b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
709b826d678462471e8112096c291d95cb61e99364sewardj
719b826d678462471e8112096c291d95cb61e99364sewardj   bit = 1; mask = (1UL << bit);
729b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
739b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
749b826d678462471e8112096c291d95cb61e99364sewardj
759b826d678462471e8112096c291d95cb61e99364sewardj   bit = 2; mask = (1UL << bit);
769b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
779b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
789b826d678462471e8112096c291d95cb61e99364sewardj
799b826d678462471e8112096c291d95cb61e99364sewardj   bit = 3; mask = (1UL << bit);
809b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
819b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
829b826d678462471e8112096c291d95cb61e99364sewardj
839b826d678462471e8112096c291d95cb61e99364sewardj   bit = 4; mask = (1UL << bit);
849b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
859b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
869b826d678462471e8112096c291d95cb61e99364sewardj
879b826d678462471e8112096c291d95cb61e99364sewardj   bit = 5; mask = (1UL << bit);
889b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
899b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
909b826d678462471e8112096c291d95cb61e99364sewardj
919b826d678462471e8112096c291d95cb61e99364sewardj   bit = 6 ; mask = (1UL << bit);
929b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
939b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
949b826d678462471e8112096c291d95cb61e99364sewardj
959b826d678462471e8112096c291d95cb61e99364sewardj   bit = 7 ; mask = (1UL << bit);
969b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
979b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
989b826d678462471e8112096c291d95cb61e99364sewardj
999b826d678462471e8112096c291d95cb61e99364sewardj   bit = 8 ; mask = (1UL << bit);
1009b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1019b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1029b826d678462471e8112096c291d95cb61e99364sewardj
1039b826d678462471e8112096c291d95cb61e99364sewardj   bit = 9 ; mask = (1UL << bit);
1049b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1059b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1069b826d678462471e8112096c291d95cb61e99364sewardj
1079b826d678462471e8112096c291d95cb61e99364sewardj   bit = 10 ; mask = (1UL << bit);
1089b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1099b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1109b826d678462471e8112096c291d95cb61e99364sewardj
1119b826d678462471e8112096c291d95cb61e99364sewardj   bit = 11 ; mask = (1UL << bit);
1129b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1139b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1149b826d678462471e8112096c291d95cb61e99364sewardj
1159b826d678462471e8112096c291d95cb61e99364sewardj   bit = 12 ; mask = (1UL << bit);
1169b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1179b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1189b826d678462471e8112096c291d95cb61e99364sewardj
1199b826d678462471e8112096c291d95cb61e99364sewardj   bit = 13 ; mask = (1UL << bit);
1209b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1219b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1229b826d678462471e8112096c291d95cb61e99364sewardj
1239b826d678462471e8112096c291d95cb61e99364sewardj   bit = 14 ; mask = (1UL << bit);
1249b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1259b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1269b826d678462471e8112096c291d95cb61e99364sewardj
1279b826d678462471e8112096c291d95cb61e99364sewardj   bit = 15 ; mask = (1UL << bit);
1289b826d678462471e8112096c291d95cb61e99364sewardj   if ((vbits_mask & mask) == 0) print(vbits, val_copy, bit, result & mask);
1299b826d678462471e8112096c291d95cb61e99364sewardj   else use(bit, result & mask);
1309b826d678462471e8112096c291d95cb61e99364sewardj}
1319b826d678462471e8112096c291d95cb61e99364sewardj
1329b826d678462471e8112096c291d95cb61e99364sewardjint main(int argc, char *argv[])
1339b826d678462471e8112096c291d95cb61e99364sewardj{
1349b826d678462471e8112096c291d95cb61e99364sewardj   doit(0x0000000000000000, 0x0000000000000000,
1359b826d678462471e8112096c291d95cb61e99364sewardj        0x0000000000000000, 0x0000000000000000);
1369b826d678462471e8112096c291d95cb61e99364sewardj
1379b826d678462471e8112096c291d95cb61e99364sewardj   doit(0x0707070707070707, 0x0707070707070707,
1389b826d678462471e8112096c291d95cb61e99364sewardj        0x0000000000000000, 0x0000000000000000);
1399b826d678462471e8112096c291d95cb61e99364sewardj
1409b826d678462471e8112096c291d95cb61e99364sewardj   doit(0x8080808080808080, 0x8080808080808080,
1419b826d678462471e8112096c291d95cb61e99364sewardj        0x0000000000000000, 0x0000000000000000);
1429b826d678462471e8112096c291d95cb61e99364sewardj
1439b826d678462471e8112096c291d95cb61e99364sewardj   doit(0x13579BDF02468ACE, 0xFEDCBA9876543210,
1449b826d678462471e8112096c291d95cb61e99364sewardj        0xFEEDFACEDEADBEEF, 0xFEE1DEADDABBAD00);
1459b826d678462471e8112096c291d95cb61e99364sewardj
1469b826d678462471e8112096c291d95cb61e99364sewardj   return 0;
1479b826d678462471e8112096c291d95cb61e99364sewardj}
148