1 2 /* A Memcheck test program for conditional loads and stores, 3 as shown in do_conditional_{load,store}32. 4 5 Program is run twice, once for loads and once for stores, only 6 because each run generates 80 errors, and we want to see them all. 7 Doing both loads and stores in each run runs into the problem that 8 errors are more aggressively commoned up after the 100th, and so 9 some that we want to see aren't shown. Splitting the run into two 10 pieces avoids this. 11 12 On ARM we hardwire genuine conditional loads and stores to be 13 tested -- which is the real point of this test, since we are sure 14 they will turn into IRLoadG/IRStoreG. On other platforms we make 15 do with whatever gcc gives us for the equivalent C fragment. In 16 both cases Memcheck's results should be identical -- at least in 17 error counts; line numbers unfortunately will differ. Hence there 18 are -arm and -non-arm expected output files. */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <assert.h> 23 #include <string.h> 24 25 #include "../memcheck.h" 26 27 typedef unsigned int UInt; 28 29 typedef unsigned char Bool; 30 #define False ((Bool)0) 31 #define True ((Bool)1) 32 33 static void make_undef ( void* addr, size_t len ) 34 { 35 (void) VALGRIND_MAKE_MEM_UNDEFINED(addr, len); 36 } 37 38 static void make_def ( void* addr, size_t len ) 39 { 40 (void) VALGRIND_MAKE_MEM_DEFINED(addr, len); 41 } 42 43 // Returns either |*src| or |alt|. 44 __attribute__((noinline)) 45 UInt do_conditional_load32 ( UInt* src, UInt alt, Bool b ) 46 { 47 UInt res; 48 # if defined(__linux__) && defined(__arm__) 49 __asm__ __volatile__( 50 "mov r5, %2" "\n\t" // alt 51 "tst %3, #0xFF" "\n\t" // b 52 "it ne" "\n\t" 53 "ldrne r5, [%1]" "\n\t" // src 54 "mov %0, r5" "\n\t" // res 55 : /*OUT*/"=r"(res) 56 : /*IN*/"r"(src), "r"(alt), "r"(b) 57 : /*TRASH*/ "r5","cc","memory" 58 ); 59 # else 60 __asm__ __volatile__("" ::: "cc","memory"); 61 res = b ? *src : alt; 62 # endif 63 // res might be undefined. Paint it as defined so the 64 // caller can look at it without invoking further errors. 65 make_def(&res, sizeof(res)); 66 return res; 67 } 68 69 // Possibly writes |alt| to |*dst|, and returns the resulting 70 // value of |*dst|. 71 __attribute__((noinline)) 72 UInt do_conditional_store32 ( UInt* dst, UInt alt, Bool b ) 73 { 74 # if defined(__linux__) && defined(__arm__) 75 __asm__ __volatile__( 76 "mov r5, %1" "\n\t" // alt 77 "tst %2, #0xFF" "\n\t" // b 78 "it ne" "\n\t" 79 "strne r5, [%0]" "\n\t" // dst 80 : /*OUT*/ 81 : /*IN*/"r"(dst), "r"(alt), "r"(b) 82 : /*TRASH*/ "r5","cc","memory" 83 ); 84 # else 85 __asm__ __volatile__("" ::: "cc","memory"); 86 if (b) *dst = alt; 87 # endif 88 /* Now we need to get hold of the value at *dst. But it might be 89 unaddressible and/or undefined. Hence turn off error reporting 90 when getting it. */ 91 UInt res; 92 VALGRIND_DISABLE_ERROR_REPORTING; 93 res = *dst; 94 VALGRIND_ENABLE_ERROR_REPORTING; 95 make_def(&res, sizeof(res)); 96 return res; 97 } 98 99 100 /* --- LOAD ----------------------------------------- LOAD --- */ 101 /* --- LOAD ----------------------------------------- LOAD --- */ 102 /* --- LOAD ----------------------------------------- LOAD --- */ 103 104 /* For conditional loads, there are 64 combinations to test. 105 106 cond: { defined-true, defined-false, 107 undefined-true, undefined-false } D1 D0 U1 U0 108 x 109 addr: { defined-valid, defined-invalid, 110 undefined-valid, undefined-invalid } DV DI UV UI 111 x 112 alt: { defined, undefined } Da Ub 113 x 114 data: { defined, undefined } Dc Ud 115 116 // a, b, c, d refer to actual values 117 118 The general form of the test is: 119 1. Place data at *addr 120 2. return "cond ? *addr : alt" 121 */ 122 typedef enum { Cond_D1=10, Cond_D0, Cond_U1, Cond_U0 } Inp_Cond; 123 typedef enum { Addr_DV=20, Addr_DI, Addr_UV, Addr_UI } Inp_Addr; 124 typedef enum { Alt_Da=30, Alt_Ub } Inp_Alt; 125 typedef enum { Data_Dc=40, Data_Ud } Inp_Data; 126 127 typedef 128 struct { Inp_Cond inp_Cond; Inp_Addr inp_Addr; 129 Inp_Alt inp_Alt; Inp_Data inp_Data; 130 char res; char defErr_Cond; char defErr_Addr; char addrErr; } 131 TestCase; 132 133 const TestCase loadCases[64] = { 134 135 // ADDR ALT COND DATA Res 136 // defErr-COND 137 // defErr-ADDR 138 // addrErr 139 140 // In all of the next 16 cases, the load definitely happens 141 // and |alt| is therefore irrelevant 142 { Cond_D1, Addr_DV, Alt_Da, Data_Dc, 'C', 'N', 'N', 'N' }, // 0 143 { Cond_D1, Addr_DV, Alt_Da, Data_Ud, 'D', 'N', 'N', 'N' }, 144 { Cond_D1, Addr_DV, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'N' }, 145 { Cond_D1, Addr_DV, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'N' }, 146 { Cond_D1, Addr_DI, Alt_Da, Data_Dc, 'C', 'N', 'N', 'Y' }, 147 { Cond_D1, Addr_DI, Alt_Da, Data_Ud, 'D', 'N', 'N', 'Y' }, 148 { Cond_D1, Addr_DI, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'Y' }, 149 { Cond_D1, Addr_DI, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'Y' }, 150 151 { Cond_D1, Addr_UV, Alt_Da, Data_Dc, 'C', 'N', 'Y', 'N' }, // 8 152 { Cond_D1, Addr_UV, Alt_Da, Data_Ud, 'D', 'N', 'Y', 'N' }, 153 { Cond_D1, Addr_UV, Alt_Ub, Data_Dc, 'C', 'N', 'Y', 'N' }, 154 { Cond_D1, Addr_UV, Alt_Ub, Data_Ud, 'D', 'N', 'Y', 'N' }, 155 { Cond_D1, Addr_UI, Alt_Da, Data_Dc, 'C', 'N', 'Y', 'Y' }, 156 { Cond_D1, Addr_UI, Alt_Da, Data_Ud, 'D', 'N', 'Y', 'Y' }, 157 { Cond_D1, Addr_UI, Alt_Ub, Data_Dc, 'C', 'N', 'Y', 'Y' }, 158 { Cond_D1, Addr_UI, Alt_Ub, Data_Ud, 'D', 'N', 'Y', 'Y' }, 159 160 // In the next 16 cases, the load definitely does not happen, 161 // so we just return |alt|. 162 { Cond_D0, Addr_DV, Alt_Da, Data_Dc, 'A', 'N', 'N', 'N' }, // 16 163 { Cond_D0, Addr_DV, Alt_Da, Data_Ud, 'A', 'N', 'N', 'N' }, 164 { Cond_D0, Addr_DV, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'N' }, 165 { Cond_D0, Addr_DV, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'N' }, 166 { Cond_D0, Addr_DI, Alt_Da, Data_Dc, 'A', 'N', 'N', 'N' }, 167 { Cond_D0, Addr_DI, Alt_Da, Data_Ud, 'A', 'N', 'N', 'N' }, 168 { Cond_D0, Addr_DI, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'N' }, 169 { Cond_D0, Addr_DI, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'N' }, 170 171 { Cond_D0, Addr_UV, Alt_Da, Data_Dc, 'A', 'N', 'N', 'N' }, // 24 172 { Cond_D0, Addr_UV, Alt_Da, Data_Ud, 'A', 'N', 'N', 'N' }, 173 { Cond_D0, Addr_UV, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'N' }, 174 { Cond_D0, Addr_UV, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'N' }, 175 { Cond_D0, Addr_UI, Alt_Da, Data_Dc, 'A', 'N', 'N', 'N' }, 176 { Cond_D0, Addr_UI, Alt_Da, Data_Ud, 'A', 'N', 'N', 'N' }, 177 { Cond_D0, Addr_UI, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'N' }, 178 { Cond_D0, Addr_UI, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'N' }, 179 180 // ADDR ALT COND DATA Res 181 // defErr-COND 182 // defErr-ADDR 183 // addrErr 184 185 // In the next 16 cases, the load happens, but the condition 186 // is undefined. This means that it should behave like the 187 // first group of 16 cases, except that we should also get a 188 // complaint about the definedness of the condition. 189 { Cond_U1, Addr_DV, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'N' }, // 32 190 { Cond_U1, Addr_DV, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'N' }, 191 { Cond_U1, Addr_DV, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'N' }, 192 { Cond_U1, Addr_DV, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'N' }, 193 { Cond_U1, Addr_DI, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'Y' }, 194 { Cond_U1, Addr_DI, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'Y' }, 195 { Cond_U1, Addr_DI, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'Y' }, 196 { Cond_U1, Addr_DI, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'Y' }, 197 198 { Cond_U1, Addr_UV, Alt_Da, Data_Dc, 'C', 'Y', 'Y', 'N' }, // 40 199 { Cond_U1, Addr_UV, Alt_Da, Data_Ud, 'D', 'Y', 'Y', 'N' }, 200 { Cond_U1, Addr_UV, Alt_Ub, Data_Dc, 'C', 'Y', 'Y', 'N' }, 201 { Cond_U1, Addr_UV, Alt_Ub, Data_Ud, 'D', 'Y', 'Y', 'N' }, 202 { Cond_U1, Addr_UI, Alt_Da, Data_Dc, 'C', 'Y', 'Y', 'Y' }, 203 { Cond_U1, Addr_UI, Alt_Da, Data_Ud, 'D', 'Y', 'Y', 'Y' }, 204 { Cond_U1, Addr_UI, Alt_Ub, Data_Dc, 'C', 'Y', 'Y', 'Y' }, 205 { Cond_U1, Addr_UI, Alt_Ub, Data_Ud, 'D', 'Y', 'Y', 'Y' }, 206 207 // In this last group of 16 cases, the load does not happen, 208 // but the condition is undefined. So we just return |alt|, 209 // and also complain about the condition. Hence it's like the 210 // second group of 16 cases except that we also get a complaint 211 // about the condition. 212 { Cond_U0, Addr_DV, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'N' }, // 48 213 { Cond_U0, Addr_DV, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'N' }, 214 { Cond_U0, Addr_DV, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'N' }, 215 { Cond_U0, Addr_DV, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'N' }, 216 { Cond_U0, Addr_DI, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'N' }, 217 { Cond_U0, Addr_DI, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'N' }, 218 { Cond_U0, Addr_DI, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'N' }, 219 { Cond_U0, Addr_DI, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'N' }, 220 221 { Cond_U0, Addr_UV, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'N' }, // 56 222 { Cond_U0, Addr_UV, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'N' }, 223 { Cond_U0, Addr_UV, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'N' }, 224 { Cond_U0, Addr_UV, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'N' }, 225 { Cond_U0, Addr_UI, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'N' }, 226 { Cond_U0, Addr_UI, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'N' }, 227 { Cond_U0, Addr_UI, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'N' }, 228 { Cond_U0, Addr_UI, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'N' } // 63 229 }; 230 231 // Constant, corresponding to the test enums 232 static Bool c_Cond_D1, c_Cond_D0, c_Cond_U1, c_Cond_U0; 233 static UInt *c_Addr_DV, *c_Addr_DI, *c_Addr_UV, *c_Addr_UI; 234 static UInt c_Alt_Da, c_Alt_Ub; 235 236 static void setup_test_data ( Inp_Data inp_Data ) 237 { 238 c_Cond_D1 = c_Cond_U1 = True; 239 c_Cond_D0 = c_Cond_U0 = False; 240 make_undef(&c_Cond_U1, sizeof(c_Cond_U1)); 241 make_undef(&c_Cond_U0, sizeof(c_Cond_U0)); 242 243 c_Addr_DV = c_Addr_UV = malloc(4); 244 c_Addr_DI = c_Addr_UI = malloc(4); 245 // install test data at the given address 246 UInt testd = inp_Data == Data_Dc ? 0xCCCCCCCC : 0xDDDDDDDD; 247 *c_Addr_DV = *c_Addr_DI = testd; 248 if (inp_Data == Data_Dc) { 249 // it's already defined 250 } else { 251 make_undef(c_Addr_DV, 4); 252 make_undef(c_Addr_DI, 4); 253 } 254 255 // make the invalid address invalid. This unfortunately loses 256 // the definedness state of the data that is stored there. 257 free(c_Addr_DI); 258 259 // and set the definedness of the pointers themselves. 260 make_undef(&c_Addr_UV, sizeof(c_Addr_UV)); 261 make_undef(&c_Addr_UI, sizeof(c_Addr_UI)); 262 263 // and set up alt 264 c_Alt_Da = 0xAAAAAAAA; 265 c_Alt_Ub = 0xBBBBBBBB; 266 make_undef(&c_Alt_Ub, sizeof(c_Alt_Ub)); 267 } 268 269 static void do_test_case ( int caseNo, Bool isLoad, const TestCase* lc ) 270 { 271 fprintf(stderr, 272 "\n-----------------------------------------------------------\n"); 273 fprintf(stderr, "%s CASE %d\n", isLoad ? "LOAD" : "STORE", caseNo); 274 // validate .. 275 assert(Cond_D1 <= lc->inp_Cond && lc->inp_Cond <= Cond_U0); 276 assert(Addr_DV <= lc->inp_Addr && lc->inp_Addr <= Addr_UI); 277 assert(lc->inp_Alt == Alt_Da || lc->inp_Alt == Alt_Ub); 278 assert(lc->inp_Data == Data_Dc || lc->inp_Data == Data_Ud); 279 assert('A' <= lc->res && lc->res <= 'D'); 280 assert(lc->defErr_Cond == 'Y' || lc->defErr_Cond == 'N'); 281 assert(lc->defErr_Addr == 'Y' || lc->defErr_Addr == 'N'); 282 assert(lc->addrErr == 'Y' || lc->addrErr == 'N'); 283 // set up test data constants 284 setup_test_data(lc->inp_Data); 285 286 // and select constants for the test, depending on |lc| 287 // Except, skip i_Data since setup_test_data takes care of it. 288 Bool i_Cond; 289 UInt* i_Addr; 290 UInt i_Alt; 291 switch (lc->inp_Cond) { 292 case Cond_D1: i_Cond = c_Cond_D1; break; 293 case Cond_D0: i_Cond = c_Cond_D0; break; 294 case Cond_U1: i_Cond = c_Cond_U1; break; 295 case Cond_U0: i_Cond = c_Cond_U0; break; 296 default: assert(0); 297 } 298 switch (lc->inp_Addr) { 299 case Addr_DV: i_Addr = c_Addr_DV; break; 300 case Addr_DI: i_Addr = c_Addr_DI; break; 301 case Addr_UV: i_Addr = c_Addr_UV; break; 302 case Addr_UI: i_Addr = c_Addr_UI; break; 303 default: assert(0); 304 } 305 switch (lc->inp_Alt) { 306 case Alt_Da: i_Alt = c_Alt_Da; break; 307 case Alt_Ub: i_Alt = c_Alt_Ub; break; 308 default: assert(0); 309 } 310 311 // How many errors do we expect from this? 312 UInt n_errs_exp 313 = (lc->defErr_Cond == 'Y' ? 1 : 0) + (lc->defErr_Addr == 'Y' ? 1 : 0) 314 + (lc->addrErr == 'Y' ? 1 : 0); 315 316 UInt n_errs_act = VALGRIND_COUNT_ERRORS; 317 UInt res_act; 318 if (isLoad) { 319 res_act = do_conditional_load32(i_Addr, i_Alt, i_Cond); 320 } else { 321 res_act = do_conditional_store32(i_Addr, i_Alt, i_Cond); 322 } 323 n_errs_act = VALGRIND_COUNT_ERRORS - n_errs_act; 324 325 if (n_errs_act == n_errs_exp) { 326 fprintf(stderr, "PASS: %u errors\n", n_errs_act); 327 } else { 328 fprintf(stderr, "FAIL: %u errors expected, %u actual\n", 329 n_errs_exp, n_errs_act); 330 } 331 332 // What's the expected result value (actual loaded data?) 333 UInt res_exp = 0; 334 switch (lc->res) { 335 case 'A': res_exp = 0xAAAAAAAA; break; 336 case 'B': res_exp = 0xBBBBBBBB; break; 337 case 'C': res_exp = 0xCCCCCCCC; break; 338 case 'D': res_exp = 0xDDDDDDDD; break; 339 default: assert(0); 340 } 341 342 if (res_act == res_exp) { 343 fprintf(stderr, "PASS: correct result\n"); 344 } else { 345 fprintf(stderr, "FAIL: result: %08x expected, %08x actual\n", 346 res_exp, res_act); 347 } 348 349 free(c_Addr_DV); 350 } 351 352 353 void do_test_case_steer ( void (*fn)(int,Bool,const TestCase*), 354 int i, Bool isLd, const TestCase* tc ) 355 { 356 __asm__ __volatile__(""); 357 if (i == 0) { fn(i,isLd,tc); return; }; 358 __asm__ __volatile__(""); 359 if (i == 1) { fn(i,isLd,tc); return; }; 360 __asm__ __volatile__(""); 361 if (i == 2) { fn(i,isLd,tc); return; }; 362 __asm__ __volatile__(""); 363 if (i == 3) { fn(i,isLd,tc); return; }; 364 __asm__ __volatile__(""); 365 if (i == 4) { fn(i,isLd,tc); return; }; 366 __asm__ __volatile__(""); 367 if (i == 5) { fn(i,isLd,tc); return; }; 368 __asm__ __volatile__(""); 369 if (i == 6) { fn(i,isLd,tc); return; }; 370 __asm__ __volatile__(""); 371 if (i == 7) { fn(i,isLd,tc); return; }; 372 __asm__ __volatile__(""); 373 if (i == 8) { fn(i,isLd,tc); return; }; 374 __asm__ __volatile__(""); 375 if (i == 9) { fn(i,isLd,tc); return; }; 376 __asm__ __volatile__(""); 377 if (i == 10) { fn(i,isLd,tc); return; }; 378 __asm__ __volatile__(""); 379 if (i == 11) { fn(i,isLd,tc); return; }; 380 __asm__ __volatile__(""); 381 if (i == 12) { fn(i,isLd,tc); return; }; 382 __asm__ __volatile__(""); 383 if (i == 13) { fn(i,isLd,tc); return; }; 384 __asm__ __volatile__(""); 385 if (i == 14) { fn(i,isLd,tc); return; }; 386 __asm__ __volatile__(""); 387 if (i == 15) { fn(i,isLd,tc); return; }; 388 __asm__ __volatile__(""); 389 if (i == 16) { fn(i,isLd,tc); return; }; 390 __asm__ __volatile__(""); 391 if (i == 17) { fn(i,isLd,tc); return; }; 392 __asm__ __volatile__(""); 393 if (i == 18) { fn(i,isLd,tc); return; }; 394 __asm__ __volatile__(""); 395 if (i == 19) { fn(i,isLd,tc); return; }; 396 __asm__ __volatile__(""); 397 if (i == 20) { fn(i,isLd,tc); return; }; 398 __asm__ __volatile__(""); 399 if (i == 21) { fn(i,isLd,tc); return; }; 400 __asm__ __volatile__(""); 401 if (i == 22) { fn(i,isLd,tc); return; }; 402 __asm__ __volatile__(""); 403 if (i == 23) { fn(i,isLd,tc); return; }; 404 __asm__ __volatile__(""); 405 if (i == 24) { fn(i,isLd,tc); return; }; 406 __asm__ __volatile__(""); 407 if (i == 25) { fn(i,isLd,tc); return; }; 408 __asm__ __volatile__(""); 409 if (i == 26) { fn(i,isLd,tc); return; }; 410 __asm__ __volatile__(""); 411 if (i == 27) { fn(i,isLd,tc); return; }; 412 __asm__ __volatile__(""); 413 if (i == 28) { fn(i,isLd,tc); return; }; 414 __asm__ __volatile__(""); 415 if (i == 29) { fn(i,isLd,tc); return; }; 416 __asm__ __volatile__(""); 417 if (i == 30) { fn(i,isLd,tc); return; }; 418 __asm__ __volatile__(""); 419 if (i == 31) { fn(i,isLd,tc); return; }; 420 __asm__ __volatile__(""); 421 if (i == 32) { fn(i,isLd,tc); return; }; 422 __asm__ __volatile__(""); 423 if (i == 33) { fn(i,isLd,tc); return; }; 424 __asm__ __volatile__(""); 425 if (i == 34) { fn(i,isLd,tc); return; }; 426 __asm__ __volatile__(""); 427 if (i == 35) { fn(i,isLd,tc); return; }; 428 __asm__ __volatile__(""); 429 if (i == 36) { fn(i,isLd,tc); return; }; 430 __asm__ __volatile__(""); 431 if (i == 37) { fn(i,isLd,tc); return; }; 432 __asm__ __volatile__(""); 433 if (i == 38) { fn(i,isLd,tc); return; }; 434 __asm__ __volatile__(""); 435 if (i == 39) { fn(i,isLd,tc); return; }; 436 __asm__ __volatile__(""); 437 if (i == 40) { fn(i,isLd,tc); return; }; 438 __asm__ __volatile__(""); 439 if (i == 41) { fn(i,isLd,tc); return; }; 440 __asm__ __volatile__(""); 441 if (i == 42) { fn(i,isLd,tc); return; }; 442 __asm__ __volatile__(""); 443 if (i == 43) { fn(i,isLd,tc); return; }; 444 __asm__ __volatile__(""); 445 if (i == 44) { fn(i,isLd,tc); return; }; 446 __asm__ __volatile__(""); 447 if (i == 45) { fn(i,isLd,tc); return; }; 448 __asm__ __volatile__(""); 449 if (i == 46) { fn(i,isLd,tc); return; }; 450 __asm__ __volatile__(""); 451 if (i == 47) { fn(i,isLd,tc); return; }; 452 __asm__ __volatile__(""); 453 if (i == 48) { fn(i,isLd,tc); return; }; 454 __asm__ __volatile__(""); 455 if (i == 49) { fn(i,isLd,tc); return; }; 456 __asm__ __volatile__(""); 457 if (i == 50) { fn(i,isLd,tc); return; }; 458 __asm__ __volatile__(""); 459 if (i == 51) { fn(i,isLd,tc); return; }; 460 __asm__ __volatile__(""); 461 if (i == 52) { fn(i,isLd,tc); return; }; 462 __asm__ __volatile__(""); 463 if (i == 53) { fn(i,isLd,tc); return; }; 464 __asm__ __volatile__(""); 465 if (i == 54) { fn(i,isLd,tc); return; }; 466 __asm__ __volatile__(""); 467 if (i == 55) { fn(i,isLd,tc); return; }; 468 __asm__ __volatile__(""); 469 if (i == 56) { fn(i,isLd,tc); return; }; 470 __asm__ __volatile__(""); 471 if (i == 57) { fn(i,isLd,tc); return; }; 472 __asm__ __volatile__(""); 473 if (i == 58) { fn(i,isLd,tc); return; }; 474 __asm__ __volatile__(""); 475 if (i == 59) { fn(i,isLd,tc); return; }; 476 __asm__ __volatile__(""); 477 if (i == 60) { fn(i,isLd,tc); return; }; 478 __asm__ __volatile__(""); 479 if (i == 61) { fn(i,isLd,tc); return; }; 480 __asm__ __volatile__(""); 481 if (i == 62) { fn(i,isLd,tc); return; }; 482 __asm__ __volatile__(""); 483 if (i == 63) { fn(i,isLd,tc); return; }; 484 assert(0); 485 } 486 487 488 /* --- STORE --------------------------------------- STORE --- */ 489 /* --- STORE --------------------------------------- STORE --- */ 490 /* --- STORE --------------------------------------- STORE --- */ 491 492 /* For conditional stores, there are 64 combinations to test. 493 494 cond: { defined-true, defined-false, 495 undefined-true, undefined-false } D1 D0 U1 U0 496 x 497 addr: { defined-valid, defined-invalid, 498 undefined-valid, undefined-invalid } DV DI UV UI 499 x 500 alt: { defined, undefined } Da Ub 501 x 502 data: { defined, undefined } Dc Ud 503 504 // a, b, c, d refer to actual values 505 506 The general form of the test is: 507 1. Place data at *addr 508 2. do "if (cond) *addr = alt" 509 3 return *addr 510 511 Hence identical setup to the load cases, although the roles of 512 data and alt are somewhat confusingly swapped. |data| here is 513 the "didn't happen" result, and |alt| is the "did happen" result. 514 */ 515 516 const TestCase storeCases[64] = { 517 518 // ADDR ALT COND DATA Res 519 // defErr-COND 520 // defErr-ADDR 521 // addrErr 522 523 // In all of the next 16 cases, the store definitely happens 524 // and |data| is therefore irrelevant 525 { Cond_D1, Addr_DV, Alt_Da, Data_Dc, 'A', 'N', 'N', 'N' }, // 0 526 { Cond_D1, Addr_DV, Alt_Da, Data_Ud, 'A', 'N', 'N', 'N' }, 527 { Cond_D1, Addr_DV, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'N' }, 528 { Cond_D1, Addr_DV, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'N' }, 529 { Cond_D1, Addr_DI, Alt_Da, Data_Dc, 'A', 'N', 'N', 'Y' }, 530 { Cond_D1, Addr_DI, Alt_Da, Data_Ud, 'A', 'N', 'N', 'Y' }, 531 { Cond_D1, Addr_DI, Alt_Ub, Data_Dc, 'B', 'N', 'N', 'Y' }, 532 { Cond_D1, Addr_DI, Alt_Ub, Data_Ud, 'B', 'N', 'N', 'Y' }, 533 534 { Cond_D1, Addr_UV, Alt_Da, Data_Dc, 'A', 'N', 'Y', 'N' }, // 8 535 { Cond_D1, Addr_UV, Alt_Da, Data_Ud, 'A', 'N', 'Y', 'N' }, 536 { Cond_D1, Addr_UV, Alt_Ub, Data_Dc, 'B', 'N', 'Y', 'N' }, 537 { Cond_D1, Addr_UV, Alt_Ub, Data_Ud, 'B', 'N', 'Y', 'N' }, 538 { Cond_D1, Addr_UI, Alt_Da, Data_Dc, 'A', 'N', 'Y', 'Y' }, 539 { Cond_D1, Addr_UI, Alt_Da, Data_Ud, 'A', 'N', 'Y', 'Y' }, 540 { Cond_D1, Addr_UI, Alt_Ub, Data_Dc, 'B', 'N', 'Y', 'Y' }, 541 { Cond_D1, Addr_UI, Alt_Ub, Data_Ud, 'B', 'N', 'Y', 'Y' }, 542 543 // In the next 16 cases, the store definitely does not happen, 544 // so we just return |data|. 545 { Cond_D0, Addr_DV, Alt_Da, Data_Dc, 'C', 'N', 'N', 'N' }, // 16 546 { Cond_D0, Addr_DV, Alt_Da, Data_Ud, 'D', 'N', 'N', 'N' }, 547 { Cond_D0, Addr_DV, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'N' }, 548 { Cond_D0, Addr_DV, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'N' }, 549 { Cond_D0, Addr_DI, Alt_Da, Data_Dc, 'C', 'N', 'N', 'N' }, 550 { Cond_D0, Addr_DI, Alt_Da, Data_Ud, 'D', 'N', 'N', 'N' }, 551 { Cond_D0, Addr_DI, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'N' }, 552 { Cond_D0, Addr_DI, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'N' }, 553 554 { Cond_D0, Addr_UV, Alt_Da, Data_Dc, 'C', 'N', 'N', 'N' }, // 24 555 { Cond_D0, Addr_UV, Alt_Da, Data_Ud, 'D', 'N', 'N', 'N' }, 556 { Cond_D0, Addr_UV, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'N' }, 557 { Cond_D0, Addr_UV, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'N' }, 558 { Cond_D0, Addr_UI, Alt_Da, Data_Dc, 'C', 'N', 'N', 'N' }, 559 { Cond_D0, Addr_UI, Alt_Da, Data_Ud, 'D', 'N', 'N', 'N' }, 560 { Cond_D0, Addr_UI, Alt_Ub, Data_Dc, 'C', 'N', 'N', 'N' }, 561 { Cond_D0, Addr_UI, Alt_Ub, Data_Ud, 'D', 'N', 'N', 'N' }, 562 563 // ADDR ALT COND DATA Res 564 // defErr-COND 565 // defErr-ADDR 566 // addrErr 567 568 // In the next 16 cases, the store happens, but the condition 569 // is undefined. This means that it should behave like the 570 // first group of 16 cases, except that we should also get a 571 // complaint about the definedness of the condition. 572 { Cond_U1, Addr_DV, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'N' }, // 32 573 { Cond_U1, Addr_DV, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'N' }, 574 { Cond_U1, Addr_DV, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'N' }, 575 { Cond_U1, Addr_DV, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'N' }, 576 { Cond_U1, Addr_DI, Alt_Da, Data_Dc, 'A', 'Y', 'N', 'Y' }, 577 { Cond_U1, Addr_DI, Alt_Da, Data_Ud, 'A', 'Y', 'N', 'Y' }, 578 { Cond_U1, Addr_DI, Alt_Ub, Data_Dc, 'B', 'Y', 'N', 'Y' }, 579 { Cond_U1, Addr_DI, Alt_Ub, Data_Ud, 'B', 'Y', 'N', 'Y' }, 580 581 { Cond_U1, Addr_UV, Alt_Da, Data_Dc, 'A', 'Y', 'Y', 'N' }, // 40 582 { Cond_U1, Addr_UV, Alt_Da, Data_Ud, 'A', 'Y', 'Y', 'N' }, 583 { Cond_U1, Addr_UV, Alt_Ub, Data_Dc, 'B', 'Y', 'Y', 'N' }, 584 { Cond_U1, Addr_UV, Alt_Ub, Data_Ud, 'B', 'Y', 'Y', 'N' }, 585 { Cond_U1, Addr_UI, Alt_Da, Data_Dc, 'A', 'Y', 'Y', 'Y' }, 586 { Cond_U1, Addr_UI, Alt_Da, Data_Ud, 'A', 'Y', 'Y', 'Y' }, 587 { Cond_U1, Addr_UI, Alt_Ub, Data_Dc, 'B', 'Y', 'Y', 'Y' }, 588 { Cond_U1, Addr_UI, Alt_Ub, Data_Ud, 'B', 'Y', 'Y', 'Y' }, 589 590 // In this last group of 16 cases, the store does not happen, 591 // but the condition is undefined. So we just return |data|, 592 // and also complain about the condition. Hence it's like the 593 // second group of 16 cases except that we also get a complaint 594 // about the condition. 595 { Cond_U0, Addr_DV, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'N' }, // 48 596 { Cond_U0, Addr_DV, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'N' }, 597 { Cond_U0, Addr_DV, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'N' }, 598 { Cond_U0, Addr_DV, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'N' }, 599 { Cond_U0, Addr_DI, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'N' }, 600 { Cond_U0, Addr_DI, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'N' }, 601 { Cond_U0, Addr_DI, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'N' }, 602 { Cond_U0, Addr_DI, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'N' }, 603 604 { Cond_U0, Addr_UV, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'N' }, // 56 605 { Cond_U0, Addr_UV, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'N' }, 606 { Cond_U0, Addr_UV, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'N' }, 607 { Cond_U0, Addr_UV, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'N' }, 608 { Cond_U0, Addr_UI, Alt_Da, Data_Dc, 'C', 'Y', 'N', 'N' }, 609 { Cond_U0, Addr_UI, Alt_Da, Data_Ud, 'D', 'Y', 'N', 'N' }, 610 { Cond_U0, Addr_UI, Alt_Ub, Data_Dc, 'C', 'Y', 'N', 'N' }, 611 { Cond_U0, Addr_UI, Alt_Ub, Data_Ud, 'D', 'Y', 'N', 'N' } // 63 612 }; 613 614 void usage ( char* pname ) 615 { 616 fprintf(stderr, "usage: %s [loads|stores]\n", pname); 617 exit(1); 618 } 619 620 int main ( int argc, char** argv ) 621 { 622 UInt i, nCases; 623 624 if (argc != 2) usage(argv[0]); 625 626 Bool doLoad = False; 627 if (0 == strcmp(argv[1], "loads")) { 628 doLoad = True; 629 } 630 else if (0 == strcmp(argv[1], "stores")) { 631 doLoad = False; 632 } 633 else usage(argv[0]); 634 635 if (doLoad) { 636 nCases = sizeof(loadCases) / sizeof(loadCases[0]); 637 assert(nCases == 64); 638 for (i = 0; i < nCases; i++) 639 do_test_case_steer( do_test_case, i, True/*isLoad*/, &loadCases[i] ); 640 } else { 641 nCases = sizeof(storeCases) / sizeof(storeCases[0]); 642 assert(nCases == 64); 643 for (i = 0; i < nCases; i++) 644 do_test_case_steer( do_test_case, i, False/*!isLoad*/, &storeCases[i] ); 645 } 646 647 return 0; 648 } 649