1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This program is a thorough test of the LOADVn/STOREVn shadow memory
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// operations.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h>
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "memcheck/memcheck.h"
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// All the sizes here are in *bytes*, not bits.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned char        U1;
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned short       U2;
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned int         U4;
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned long long   U8;
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef float                F4;
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef double               F8;
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SZB_OF_a    64
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a[] is the array in which we do our loads and stores.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// b[] is another one in which we do some copying.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownU8 a [SZB_OF_a / 8];    // Type is U8 to ensure it's 8-aligned
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownU8 b [SZB_OF_a / 8];    // same size as a[]
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: should check the error cases for SET/GET_VBITS also
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// For the byte 'x', build a value of 'size' bytes from that byte, eg:
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   size 1 --> x
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   size 2 --> xx
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   size 4 --> xxxx
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   size 8 --> xxxxxxxx
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// where the 0 bits are seen by Memcheck as defined, and the 1 bits are
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// seen as undefined (ie. the value of each bit matches its V bit, ie. the
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// resulting value is the same as its metavalue).
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownU8 build(int size, U1 byte)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U8 mask = 0;
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U8 shres;
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U8 res = 0xffffffffffffffffULL, res2;
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   (void)VALGRIND_MAKE_MEM_UNDEFINED(&res, 8);
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(1 == size || 2 == size || 4 == size || 8 == size);
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < size; i++) {
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask <<= 8;
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask |= (U8)byte;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res &= mask;
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // res is now considered partially defined, but we know exactly what its
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // value is (it happens to be the same as its metavalue).
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (void)VALGRIND_GET_VBITS(&res, &shres, 8);
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res2 = res;
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (void)VALGRIND_MAKE_MEM_DEFINED(&res2, 8);  // avoid the 'undefined' warning
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(res2 == shres);
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Check that all the bytes in a[x..y-1] have their V byte equal
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to either 'expected_byte' or 'expected_byte_alt'.
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 'str' and 'offset' are only used for printing an error message if
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// something goes wrong.
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid check_all(U4 x, U4 y, U1 expected_byte, U1 expected_byte_alt,
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           char* str, int offset)
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U1 sh[SZB_OF_a];     // Used for getting a[]'s V bits
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (void)VALGRIND_GET_VBITS(a, sh, sizeof(a));
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = x; i < y; i++) {
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( expected_byte != sh[i] && expected_byte_alt != sh[i] ) {
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fprintf(stderr, "\n\nFAILURE: %s, offset %d, byte %d -- "
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         "is 0x%x, should be 0x%x or 0x%x\n\n",
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         str, offset, i, sh[i], expected_byte,
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         expected_byte_alt);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         exit(1);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(void)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int h, i, j;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   U1 *undefA, expected_byte, expected_byte_alt;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 == RUNNING_ON_VALGRIND) {
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      fprintf(stderr,
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              "error: this program only works when run under Valgrind\n");
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exit(1);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Check a[] has the expected alignment, and that it's not too high in
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the address space (which would trigger the slow cases in
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // LOADVn/STOREVn) on 64-bit platforms).
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert( 0 == (long)a % 8);
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sizeof(void*) == 8) {
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert( ((U1*)(&a[0])) < ((U1*)(32ULL * 1024*1024*1024)/*32G*/) );
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Check basic types have the expected sizes.
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(1 == sizeof(U1));
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(2 == sizeof(U2));
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(4 == sizeof(U4));
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(8 == sizeof(U8));
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Create an array of values that has all the possible V bit metavalues.
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Because 0 represents a defined bit, and because undefA[] is initially
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // zeroed, we have the nice property that:
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //    i == undefA[i] == V_bits_of(undefA[i])
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // which is useful for testing below.
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   undefA = calloc(1, 256);         // one for each possible undefinedness value
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   (void)VALGRIND_MAKE_MEM_UNDEFINED(undefA, 256);
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 256; i++) {
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      undefA[i] &= i;
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This code does a whole lot of reads and writes of a particular size
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (NNN = 1, 2, 4 or 8), with varying alignments, of values with
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // different not/partially/fully defined metavalues, and checks that the
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // V bits are set in a[] as expected using GET_VBITS.
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // 'Ty' is the type of the thing we are copying.  It can be an integer
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // type or an FP type.  'ITy' is the same-sized integer type (and thus
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // will be the same as 'Ty' if 'ITy' is an integer type).  'ITy' is used
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // when doing shifting/masking and stuff like that.
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DO(NNN, Ty, ITy, isF4) \
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   fprintf(stderr, "-- NNN: %d %s %s ------------------------\n", \
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           NNN, #Ty, #ITy); \
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For all of the alignments from (0..NNN-1), eg. if NNN==4, we do */ \
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* alignments of 0, 1, 2, 3. */ \
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (h = 0; h < NNN; h++) { \
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      \
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size_t n  = sizeof(a); \
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size_t nN = n / sizeof(Ty); \
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ty* aN    = (Ty*)a; \
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ty* bN    = (Ty*)b; \
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ty* aNb   = (Ty*)(((U1*)aN) + h); /* set offset from a[] */ \
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ty* bNb   = (Ty*)(((U1*)bN) + h); /* set offset from b[] */ \
147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      \
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "h = %d (checking %d..%d)   ", h, h, (int)(n-NNN+h)); \
149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      \
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For each of the 256 possible V byte values... */ \
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < 256; j++) { \
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* build the value for i (one of: i, ii, iiii, iiiiiiii) */ \
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         U8  tmp        = build(NNN, j); \
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ITy undefN_ITy = (ITy)tmp; \
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ty* undefN_Ty; \
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { /* This just checks that no overflow occurred when squeezing */ \
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /* the output of build() into a variable of type 'Ty'. */ \
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            U8  tmpDef     = tmp; \
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ITy undefN_ITyDef = undefN_ITy; \
160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            (void)VALGRIND_MAKE_MEM_DEFINED(&tmpDef,        8  );       \
161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            (void)VALGRIND_MAKE_MEM_DEFINED(&undefN_ITyDef, NNN);       \
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assert(tmpDef == (U8)undefN_ITyDef); \
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         \
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We have to use an array for undefN_Ty -- because if we try to
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * convert an integer type from build into an FP type with a
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * straight cast -- eg "float f = (float)i" -- the value gets
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * converted.  With this pointer/array nonsense the exact bit
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * pattern gets used as an FP value unchanged (that FP value is
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * undoubtedly nonsense, but that's not a problem here). */ \
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         undefN_Ty = (Ty*)&undefN_ITy; \
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 == j % 32) fprintf(stderr, "%d...", j); /* progress meter */ \
173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         \
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A nasty exception: most machines so far (x86/PPC32/PPC64)
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * don't have 32-bit floats.  So 32-bit floats get cast to 64-bit
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * floats.  Memcheck does a PCast in this case, which means that if
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * any V bits for the 32-bit float are undefined (ie. 0 != j), all
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * the V bits in the 64-bit float are undefined.  So account for
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * this when checking.  AMD64 typically does FP arithmetic on
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * SSE, effectively giving it access to 32-bit FP registers.  So
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * in short, for floats, we have to allow either 'j' or 0xFF
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * as an acceptable result.  Sigh. */ \
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isF4) { \
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expected_byte = j; \
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expected_byte_alt = 0 != j ? 0xFF : j; \
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else { \
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expected_byte = j; \
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expected_byte_alt = j; \
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         \
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* STOREVn.  Note that we use the first element of the undefN_Ty
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * array, as explained above. */ \
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nN-1; i++) { aNb[i] = undefN_Ty[0]; } \
194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         check_all(h, n-NNN+h, expected_byte, expected_byte_alt, \
195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "STOREVn", h); \
196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         \
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* LOADVn -- by copying the values to one place and then back,
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * we ensure that LOADVn gets exercised. */ \
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nN-1; i++) { bNb[i] = aNb[i]; } \
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nN-1; i++) { aNb[i] = bNb[i]; } \
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         check_all(h, n-NNN+h, expected_byte, expected_byte_alt, "LOADVn", h); \
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "\n"); \
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // For sizes 4 and 8 we do both integer and floating-point types.  The
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // reason being that on 32-bit machines just using integer types never
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // exercises LOADV8/STOREV8 -- for integer types these loads/stores get
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // broken into two 32-bit loads/stores.
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(1, U1, U1, /*isF4*/0);
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(2, U2, U2, /*isF4*/0);
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(4, U4, U4, /*isF4*/0);
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(4, F4, U4, /*isF4*/1);
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(8, U8, U8, /*isF4*/0);
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(8, F8, U8, /*isF4*/0);
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
219