1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "Reactor.hpp" 16 17 #include "gtest/gtest.h" 18 19 using namespace sw; 20 21 int reference(int *p, int y) 22 { 23 int x = p[-1]; 24 int z = 4; 25 26 for(int i = 0; i < 10; i++) 27 { 28 z += (2 << i) - (i / 3); 29 } 30 31 int sum = x + y + z; 32 33 return sum; 34 } 35 36 TEST(SubzeroReactorTest, Sample) 37 { 38 Routine *routine = nullptr; 39 40 { 41 Function<Int(Pointer<Int>, Int)> function; 42 { 43 Pointer<Int> p = function.Arg<0>(); 44 Int x = p[-1]; 45 Int y = function.Arg<1>(); 46 Int z = 4; 47 48 For(Int i = 0, i < 10, i++) 49 { 50 z += (2 << i) - (i / 3); 51 } 52 53 Float4 v; 54 v.z = As<Float>(z); 55 z = As<Int>(Float(Float4(v.xzxx).y)); 56 57 Int sum = x + y + z; 58 59 Return(sum); 60 } 61 62 routine = function(L"one"); 63 64 if(routine) 65 { 66 int (*callable)(int*, int) = (int(*)(int*,int))routine->getEntry(); 67 int one[2] = {1, 0}; 68 int result = callable(&one[1], 2); 69 EXPECT_EQ(result, reference(&one[1], 2)); 70 } 71 } 72 73 delete routine; 74 } 75 76 TEST(SubzeroReactorTest, Uninitialized) 77 { 78 Routine *routine = nullptr; 79 80 { 81 Function<Int()> function; 82 { 83 Int a; 84 Int z = 4; 85 Int q; 86 Int c; 87 Int p; 88 Bool b; 89 90 q += q; 91 92 If(b) 93 { 94 c = p; 95 } 96 97 Return(a + z + q + c); 98 } 99 100 routine = function(L"one"); 101 102 if(routine) 103 { 104 int (*callable)() = (int(*)())routine->getEntry(); 105 int result = callable(); 106 EXPECT_EQ(result, result); // Anything is fine, just don't crash 107 } 108 } 109 110 delete routine; 111 } 112 113 TEST(SubzeroReactorTest, SubVectorLoadStore) 114 { 115 Routine *routine = nullptr; 116 117 { 118 Function<Int(Pointer<Byte>, Pointer<Byte>)> function; 119 { 120 Pointer<Byte> in = function.Arg<0>(); 121 Pointer<Byte> out = function.Arg<1>(); 122 123 *Pointer<Int4>(out + 16 * 0) = *Pointer<Int4>(in + 16 * 0); 124 *Pointer<Short4>(out + 16 * 1) = *Pointer<Short4>(in + 16 * 1); 125 *Pointer<Byte8>(out + 16 * 2) = *Pointer<Byte8>(in + 16 * 2); 126 *Pointer<Byte4>(out + 16 * 3) = *Pointer<Byte4>(in + 16 * 3); 127 *Pointer<Short2>(out + 16 * 4) = *Pointer<Short2>(in + 16 * 4); 128 129 Return(0); 130 } 131 132 routine = function(L"one"); 133 134 if(routine) 135 { 136 int8_t in[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 137 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 138 25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 139 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140 37, 38, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 141 142 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 145 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 146 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 147 148 int (*callable)(void*, void*) = (int(*)(void*,void*))routine->getEntry(); 149 callable(in, out); 150 151 for(int row = 0; row < 5; row++) 152 { 153 for(int col = 0; col < 16; col++) 154 { 155 int i = row * 16 + col; 156 157 if(in[i] == 0) 158 { 159 EXPECT_EQ(out[i], -1) << "Row " << row << " column " << col << " not left untouched."; 160 } 161 else 162 { 163 EXPECT_EQ(out[i], in[i]) << "Row " << row << " column " << col << " not equal to input."; 164 } 165 } 166 } 167 } 168 } 169 170 delete routine; 171 } 172 173 TEST(SubzeroReactorTest, VectorConstant) 174 { 175 Routine *routine = nullptr; 176 177 { 178 Function<Int(Pointer<Byte>)> function; 179 { 180 Pointer<Byte> out = function.Arg<0>(); 181 182 *Pointer<Int4>(out + 16 * 0) = Int4(0x04030201, 0x08070605, 0x0C0B0A09, 0x100F0E0D); 183 *Pointer<Short4>(out + 16 * 1) = Short4(0x1211, 0x1413, 0x1615, 0x1817); 184 *Pointer<Byte8>(out + 16 * 2) = Byte8(0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20); 185 *Pointer<Int2>(out + 16 * 3) = Int2(0x24232221, 0x28272625); 186 187 Return(0); 188 } 189 190 routine = function(L"one"); 191 192 if(routine) 193 { 194 int8_t out[16 * 4] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 196 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 198 199 int8_t exp[16 * 4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 200 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, 201 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, 202 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, -1, -1}; 203 204 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 205 callable(out); 206 207 for(int row = 0; row < 4; row++) 208 { 209 for(int col = 0; col < 16; col++) 210 { 211 int i = row * 16 + col; 212 213 EXPECT_EQ(out[i], exp[i]); 214 } 215 } 216 } 217 } 218 219 delete routine; 220 } 221 222 TEST(SubzeroReactorTest, Concatenate) 223 { 224 Routine *routine = nullptr; 225 226 { 227 Function<Int(Pointer<Byte>)> function; 228 { 229 Pointer<Byte> out = function.Arg<0>(); 230 231 *Pointer<Int4>(out + 16 * 0) = Int4(Int2(0x04030201, 0x08070605), Int2(0x0C0B0A09, 0x100F0E0D)); 232 *Pointer<Short8>(out + 16 * 1) = Short8(Short4(0x0201, 0x0403, 0x0605, 0x0807), Short4(0x0A09, 0x0C0B, 0x0E0D, 0x100F)); 233 234 Return(0); 235 } 236 237 routine = function(L"one"); 238 239 if(routine) 240 { 241 int8_t ref[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 242 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 243 244 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 245 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; 246 247 int (*callable)(void*) = (int(*)(void*))routine->getEntry(); 248 callable(out); 249 250 for(int row = 0; row < 2; row++) 251 { 252 for(int col = 0; col < 16; col++) 253 { 254 int i = row * 16 + col; 255 256 EXPECT_EQ(out[i], ref[i]) << "Row " << row << " column " << col << " not equal to reference."; 257 } 258 } 259 } 260 } 261 262 delete routine; 263 } 264 265 TEST(SubzeroReactorTest, Swizzle) 266 { 267 Routine *routine = nullptr; 268 269 { 270 Function<Int(Pointer<Byte>)> function; 271 { 272 Pointer<Byte> out = function.Arg<0>(); 273 274 for(int i = 0; i < 256; i++) 275 { 276 *Pointer<Float4>(out + 16 * i) = Swizzle(Float4(1.0f, 2.0f, 3.0f, 4.0f), i); 277 } 278 279 for(int i = 0; i < 256; i++) 280 { 281 *Pointer<Float4>(out + 16 * (256 + i)) = ShuffleLowHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f), i); 282 } 283 284 *Pointer<Float4>(out + 16 * (512 + 0)) = UnpackLow(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f)); 285 *Pointer<Float4>(out + 16 * (512 + 1)) = UnpackHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f)); 286 *Pointer<Int2>(out + 16 * (512 + 2)) = UnpackLow(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8)); 287 *Pointer<Int2>(out + 16 * (512 + 3)) = UnpackHigh(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8)); 288 *Pointer<Short4>(out + 16 * (512 + 4)) = UnpackLow(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16)); 289 *Pointer<Short4>(out + 16 * (512 + 5)) = UnpackHigh(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16)); 290 291 for(int i = 0; i < 256; i++) 292 { 293 *Pointer<Short4>(out + 16 * (512 + 6) + (8 * i)) = 294 Swizzle(Short4(1, 2, 3, 4), i); 295 } 296 297 for(int i = 0; i < 256; i++) 298 { 299 *Pointer<Int4>(out + 16 * (512 + 6 + i) + (8 * 256)) = 300 Swizzle(Int4(1, 2, 3, 4), i); 301 } 302 303 Return(0); 304 } 305 306 routine = function(L"one"); 307 308 if(routine) 309 { 310 struct 311 { 312 float f[256 + 256 + 2][4]; 313 int i[388][4]; 314 } out; 315 316 memset(&out, 0, sizeof(out)); 317 318 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 319 callable(&out); 320 321 for(int i = 0; i < 256; i++) 322 { 323 EXPECT_EQ(out.f[i][0], float((i >> 0) & 0x03) + 1.0f); 324 EXPECT_EQ(out.f[i][1], float((i >> 2) & 0x03) + 1.0f); 325 EXPECT_EQ(out.f[i][2], float((i >> 4) & 0x03) + 1.0f); 326 EXPECT_EQ(out.f[i][3], float((i >> 6) & 0x03) + 1.0f); 327 } 328 329 for(int i = 0; i < 256; i++) 330 { 331 EXPECT_EQ(out.f[256 + i][0], float((i >> 0) & 0x03) + 1.0f); 332 EXPECT_EQ(out.f[256 + i][1], float((i >> 2) & 0x03) + 1.0f); 333 EXPECT_EQ(out.f[256 + i][2], float((i >> 4) & 0x03) + 5.0f); 334 EXPECT_EQ(out.f[256 + i][3], float((i >> 6) & 0x03) + 5.0f); 335 } 336 337 EXPECT_EQ(out.f[512 + 0][0], 1.0f); 338 EXPECT_EQ(out.f[512 + 0][1], 5.0f); 339 EXPECT_EQ(out.f[512 + 0][2], 2.0f); 340 EXPECT_EQ(out.f[512 + 0][3], 6.0f); 341 342 EXPECT_EQ(out.f[512 + 1][0], 3.0f); 343 EXPECT_EQ(out.f[512 + 1][1], 7.0f); 344 EXPECT_EQ(out.f[512 + 1][2], 4.0f); 345 EXPECT_EQ(out.f[512 + 1][3], 8.0f); 346 347 EXPECT_EQ(out.i[0][0], 0x00050001); 348 EXPECT_EQ(out.i[0][1], 0x00060002); 349 EXPECT_EQ(out.i[0][2], 0x00000000); 350 EXPECT_EQ(out.i[0][3], 0x00000000); 351 352 EXPECT_EQ(out.i[1][0], 0x00070003); 353 EXPECT_EQ(out.i[1][1], 0x00080004); 354 EXPECT_EQ(out.i[1][2], 0x00000000); 355 EXPECT_EQ(out.i[1][3], 0x00000000); 356 357 EXPECT_EQ(out.i[2][0], 0x0A020901); 358 EXPECT_EQ(out.i[2][1], 0x0C040B03); 359 EXPECT_EQ(out.i[2][2], 0x00000000); 360 EXPECT_EQ(out.i[2][3], 0x00000000); 361 362 EXPECT_EQ(out.i[3][0], 0x0E060D05); 363 EXPECT_EQ(out.i[3][1], 0x10080F07); 364 EXPECT_EQ(out.i[3][2], 0x00000000); 365 EXPECT_EQ(out.i[3][3], 0x00000000); 366 367 for(int i = 0; i < 256; i++) 368 { 369 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] & 0xFFFF, 370 ((i >> 0) & 0x03) + 1); 371 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] >> 16, 372 ((i >> 2) & 0x03) + 1); 373 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] & 0xFFFF, 374 ((i >> 4) & 0x03) + 1); 375 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] >> 16, 376 ((i >> 6) & 0x03) + 1); 377 } 378 379 for(int i = 0; i < 256; i++) 380 { 381 EXPECT_EQ(out.i[132 + i][0], ((i >> 0) & 0x03) + 1); 382 EXPECT_EQ(out.i[132 + i][1], ((i >> 2) & 0x03) + 1); 383 EXPECT_EQ(out.i[132 + i][2], ((i >> 4) & 0x03) + 1); 384 EXPECT_EQ(out.i[132 + i][3], ((i >> 6) & 0x03) + 1); 385 } 386 } 387 } 388 389 delete routine; 390 } 391 392 TEST(SubzeroReactorTest, Branching) 393 { 394 Routine *routine = nullptr; 395 396 { 397 Function<Int(Void)> function; 398 { 399 Int x = 0; 400 401 For(Int i = 0, i < 8, i++) 402 { 403 If(i < 2) 404 { 405 x += 1; 406 } 407 Else If(i < 4) 408 { 409 x += 10; 410 } 411 Else If(i < 6) 412 { 413 x += 100; 414 } 415 Else 416 { 417 x += 1000; 418 } 419 420 For(Int i = 0, i < 5, i++) 421 x += 10000; 422 } 423 424 For(Int i = 0, i < 10, i++) 425 for(int i = 0; i < 10; i++) 426 For(Int i = 0, i < 10, i++) 427 { 428 x += 1000000; 429 } 430 431 For(Int i = 0, i < 2, i++) 432 If(x == 1000402222) 433 { 434 If(x != 1000402222) 435 x += 1000000000; 436 } 437 Else 438 x = -5; 439 440 Return(x); 441 } 442 443 routine = function(L"one"); 444 445 if(routine) 446 { 447 int(*callable)() = (int(*)())routine->getEntry(); 448 int result = callable(); 449 450 EXPECT_EQ(result, 1000402222); 451 } 452 } 453 454 delete routine; 455 } 456 457 TEST(SubzeroReactorTest, MinMax) 458 { 459 Routine *routine = nullptr; 460 461 { 462 Function<Int(Pointer<Byte>)> function; 463 { 464 Pointer<Byte> out = function.Arg<0>(); 465 466 *Pointer<Float4>(out + 16 * 0) = Min(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f)); 467 *Pointer<Float4>(out + 16 * 1) = Max(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f)); 468 469 *Pointer<Int4>(out + 16 * 2) = Min(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0)); 470 *Pointer<Int4>(out + 16 * 3) = Max(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0)); 471 *Pointer<UInt4>(out + 16 * 4) = Min(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0)); 472 *Pointer<UInt4>(out + 16 * 5) = Max(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0)); 473 474 *Pointer<Short4>(out + 16 * 6) = Min(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0)); 475 *Pointer<Short4>(out + 16 * 7) = Max(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0)); 476 *Pointer<UShort4>(out + 16 * 8) = Min(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0)); 477 *Pointer<UShort4>(out + 16 * 9) = Max(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0)); 478 479 Return(0); 480 } 481 482 routine = function(L"one"); 483 484 if(routine) 485 { 486 unsigned int out[10][4]; 487 488 memset(&out, 0, sizeof(out)); 489 490 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 491 callable(&out); 492 493 EXPECT_EQ(out[0][0], 0x00000000u); 494 EXPECT_EQ(out[0][1], 0x00000000u); 495 EXPECT_EQ(out[0][2], 0x00000000u); 496 EXPECT_EQ(out[0][3], 0x80000000u); 497 498 EXPECT_EQ(out[1][0], 0x3F800000u); 499 EXPECT_EQ(out[1][1], 0x3F800000u); 500 EXPECT_EQ(out[1][2], 0x00000000u); 501 EXPECT_EQ(out[1][3], 0x80000000u); 502 503 EXPECT_EQ(out[2][0], 0x00000000u); 504 EXPECT_EQ(out[2][1], 0x00000000u); 505 EXPECT_EQ(out[2][2], 0xFFFFFFFFu); 506 EXPECT_EQ(out[2][3], 0x00000000u); 507 508 EXPECT_EQ(out[3][0], 0x00000001u); 509 EXPECT_EQ(out[3][1], 0x00000001u); 510 EXPECT_EQ(out[3][2], 0x00000000u); 511 EXPECT_EQ(out[3][3], 0x00000000u); 512 513 EXPECT_EQ(out[4][0], 0x00000000u); 514 EXPECT_EQ(out[4][1], 0x00000000u); 515 EXPECT_EQ(out[4][2], 0x00000000u); 516 EXPECT_EQ(out[4][3], 0x00000000u); 517 518 EXPECT_EQ(out[5][0], 0x00000001u); 519 EXPECT_EQ(out[5][1], 0x00000001u); 520 EXPECT_EQ(out[5][2], 0xFFFFFFFFu); 521 EXPECT_EQ(out[5][3], 0x00000000u); 522 523 EXPECT_EQ(out[6][0], 0x00000000u); 524 EXPECT_EQ(out[6][1], 0x0000FFFFu); 525 EXPECT_EQ(out[6][2], 0x00000000u); 526 EXPECT_EQ(out[6][3], 0x00000000u); 527 528 EXPECT_EQ(out[7][0], 0x00010001u); 529 EXPECT_EQ(out[7][1], 0x00000000u); 530 EXPECT_EQ(out[7][2], 0x00000000u); 531 EXPECT_EQ(out[7][3], 0x00000000u); 532 533 EXPECT_EQ(out[8][0], 0x00000000u); 534 EXPECT_EQ(out[8][1], 0x00000000u); 535 EXPECT_EQ(out[8][2], 0x00000000u); 536 EXPECT_EQ(out[8][3], 0x00000000u); 537 538 EXPECT_EQ(out[9][0], 0x00010001u); 539 EXPECT_EQ(out[9][1], 0x0000FFFFu); 540 EXPECT_EQ(out[9][2], 0x00000000u); 541 EXPECT_EQ(out[9][3], 0x00000000u); 542 } 543 } 544 545 delete routine; 546 } 547 548 TEST(SubzeroReactorTest, NotNeg) 549 { 550 Routine *routine = nullptr; 551 552 { 553 Function<Int(Pointer<Byte>)> function; 554 { 555 Pointer<Byte> out = function.Arg<0>(); 556 557 *Pointer<Int>(out + 16 * 0) = ~Int(0x55555555); 558 *Pointer<Short>(out + 16 * 1) = ~Short(0x5555); 559 *Pointer<Int4>(out + 16 * 2) = ~Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF); 560 *Pointer<Short4>(out + 16 * 3) = ~Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF); 561 562 *Pointer<Int>(out + 16 * 4) = -Int(0x55555555); 563 *Pointer<Short>(out + 16 * 5) = -Short(0x5555); 564 *Pointer<Int4>(out + 16 * 6) = -Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF); 565 *Pointer<Short4>(out + 16 * 7) = -Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF); 566 567 *Pointer<Float4>(out + 16 * 8) = -Float4(1.0f, -1.0f, 0.0f, -0.0f); 568 569 Return(0); 570 } 571 572 routine = function(L"one"); 573 574 if(routine) 575 { 576 unsigned int out[10][4]; 577 578 memset(&out, 0, sizeof(out)); 579 580 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 581 callable(&out); 582 583 EXPECT_EQ(out[0][0], 0xAAAAAAAAu); 584 EXPECT_EQ(out[0][1], 0x00000000u); 585 EXPECT_EQ(out[0][2], 0x00000000u); 586 EXPECT_EQ(out[0][3], 0x00000000u); 587 588 EXPECT_EQ(out[1][0], 0x0000AAAAu); 589 EXPECT_EQ(out[1][1], 0x00000000u); 590 EXPECT_EQ(out[1][2], 0x00000000u); 591 EXPECT_EQ(out[1][3], 0x00000000u); 592 593 EXPECT_EQ(out[2][0], 0xAAAAAAAAu); 594 EXPECT_EQ(out[2][1], 0x55555555u); 595 EXPECT_EQ(out[2][2], 0xFFFFFFFFu); 596 EXPECT_EQ(out[2][3], 0x00000000u); 597 598 EXPECT_EQ(out[3][0], 0x5555AAAAu); 599 EXPECT_EQ(out[3][1], 0x0000FFFFu); 600 EXPECT_EQ(out[3][2], 0x00000000u); 601 EXPECT_EQ(out[3][3], 0x00000000u); 602 603 EXPECT_EQ(out[4][0], 0xAAAAAAABu); 604 EXPECT_EQ(out[4][1], 0x00000000u); 605 EXPECT_EQ(out[4][2], 0x00000000u); 606 EXPECT_EQ(out[4][3], 0x00000000u); 607 608 EXPECT_EQ(out[5][0], 0x0000AAABu); 609 EXPECT_EQ(out[5][1], 0x00000000u); 610 EXPECT_EQ(out[5][2], 0x00000000u); 611 EXPECT_EQ(out[5][3], 0x00000000u); 612 613 EXPECT_EQ(out[6][0], 0xAAAAAAABu); 614 EXPECT_EQ(out[6][1], 0x55555556u); 615 EXPECT_EQ(out[6][2], 0x00000000u); 616 EXPECT_EQ(out[6][3], 0x00000001u); 617 618 EXPECT_EQ(out[7][0], 0x5556AAABu); 619 EXPECT_EQ(out[7][1], 0x00010000u); 620 EXPECT_EQ(out[7][2], 0x00000000u); 621 EXPECT_EQ(out[7][3], 0x00000000u); 622 623 EXPECT_EQ(out[8][0], 0xBF800000u); 624 EXPECT_EQ(out[8][1], 0x3F800000u); 625 EXPECT_EQ(out[8][2], 0x80000000u); 626 EXPECT_EQ(out[8][3], 0x00000000u); 627 } 628 } 629 630 delete routine; 631 } 632 633 TEST(SubzeroReactorTest, VectorCompare) 634 { 635 Routine *routine = nullptr; 636 637 { 638 Function<Int(Pointer<Byte>)> function; 639 { 640 Pointer<Byte> out = function.Arg<0>(); 641 642 *Pointer<Int4>(out + 16 * 0) = CmpEQ(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f)); 643 *Pointer<Int4>(out + 16 * 1) = CmpEQ(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0)); 644 *Pointer<Byte8>(out + 16 * 2) = CmpEQ(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0)); 645 646 *Pointer<Int4>(out + 16 * 3) = CmpNLT(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f)); 647 *Pointer<Int4>(out + 16 * 4) = CmpNLT(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0)); 648 *Pointer<Byte8>(out + 16 * 5) = CmpGT(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0)); 649 650 Return(0); 651 } 652 653 routine = function(L"one"); 654 655 if(routine) 656 { 657 unsigned int out[6][4]; 658 659 memset(&out, 0, sizeof(out)); 660 661 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 662 callable(&out); 663 664 EXPECT_EQ(out[0][0], 0x00000000u); 665 EXPECT_EQ(out[0][1], 0xFFFFFFFFu); 666 EXPECT_EQ(out[0][2], 0xFFFFFFFFu); 667 EXPECT_EQ(out[0][3], 0xFFFFFFFFu); 668 669 EXPECT_EQ(out[1][0], 0x00000000u); 670 EXPECT_EQ(out[1][1], 0x00000000u); 671 EXPECT_EQ(out[1][2], 0x00000000u); 672 EXPECT_EQ(out[1][3], 0xFFFFFFFFu); 673 674 EXPECT_EQ(out[2][0], 0xFF000000u); 675 EXPECT_EQ(out[2][1], 0x00000000u); 676 677 EXPECT_EQ(out[3][0], 0xFFFFFFFFu); 678 EXPECT_EQ(out[3][1], 0xFFFFFFFFu); 679 EXPECT_EQ(out[3][2], 0xFFFFFFFFu); 680 EXPECT_EQ(out[3][3], 0xFFFFFFFFu); 681 682 EXPECT_EQ(out[4][0], 0xFFFFFFFFu); 683 EXPECT_EQ(out[4][1], 0x00000000u); 684 EXPECT_EQ(out[4][2], 0x00000000u); 685 EXPECT_EQ(out[4][3], 0xFFFFFFFFu); 686 687 EXPECT_EQ(out[5][0], 0x00000000u); 688 EXPECT_EQ(out[5][1], 0xFFFFFFFFu); 689 } 690 } 691 692 delete routine; 693 } 694 695 TEST(SubzeroReactorTest, SaturatedAddAndSubtract) 696 { 697 Routine *routine = nullptr; 698 699 { 700 Function<Int(Pointer<Byte>)> function; 701 { 702 Pointer<Byte> out = function.Arg<0>(); 703 704 *Pointer<Byte8>(out + 8 * 0) = 705 AddSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8), 706 Byte8(7, 6, 5, 4, 3, 2, 1, 0)); 707 *Pointer<Byte8>(out + 8 * 1) = 708 AddSat(Byte8(0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE), 709 Byte8(7, 6, 5, 4, 3, 2, 1, 0)); 710 *Pointer<Byte8>(out + 8 * 2) = 711 SubSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8), 712 Byte8(7, 6, 5, 4, 3, 2, 1, 0)); 713 714 *Pointer<SByte8>(out + 8 * 3) = 715 AddSat(SByte8(1, 2, 3, 4, 5, 6, 7, 8), 716 SByte8(7, 6, 5, 4, 3, 2, 1, 0)); 717 *Pointer<SByte8>(out + 8 * 4) = 718 AddSat(SByte8(0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E), 719 SByte8(7, 6, 5, 4, 3, 2, 1, 0)); 720 *Pointer<SByte8>(out + 8 * 5) = 721 AddSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88), 722 SByte8(-7, -6, -5, -4, -3, -2, -1, -0)); 723 *Pointer<SByte8>(out + 8 * 6) = 724 SubSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88), 725 SByte8(7, 6, 5, 4, 3, 2, 1, 0)); 726 727 *Pointer<Short4>(out + 8 * 7) = 728 AddSat(Short4(1, 2, 3, 4), Short4(3, 2, 1, 0)); 729 *Pointer<Short4>(out + 8 * 8) = 730 AddSat(Short4(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE), 731 Short4(3, 2, 1, 0)); 732 *Pointer<Short4>(out + 8 * 9) = 733 AddSat(Short4(0x8001, 0x8002, 0x8003, 0x8004), 734 Short4(-3, -2, -1, -0)); 735 *Pointer<Short4>(out + 8 * 10) = 736 SubSat(Short4(0x8001, 0x8002, 0x8003, 0x8004), 737 Short4(3, 2, 1, 0)); 738 739 *Pointer<UShort4>(out + 8 * 11) = 740 AddSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0)); 741 *Pointer<UShort4>(out + 8 * 12) = 742 AddSat(UShort4(0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE), 743 UShort4(3, 2, 1, 0)); 744 *Pointer<UShort4>(out + 8 * 13) = 745 SubSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0)); 746 747 Return(0); 748 } 749 750 routine = function(L"one"); 751 752 if(routine) 753 { 754 unsigned int out[14][2]; 755 756 memset(&out, 0, sizeof(out)); 757 758 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 759 callable(&out); 760 761 EXPECT_EQ(out[0][0], 0x08080808u); 762 EXPECT_EQ(out[0][1], 0x08080808u); 763 764 EXPECT_EQ(out[1][0], 0xFFFFFFFFu); 765 EXPECT_EQ(out[1][1], 0xFEFFFFFFu); 766 767 EXPECT_EQ(out[2][0], 0x00000000u); 768 EXPECT_EQ(out[2][1], 0x08060402u); 769 770 EXPECT_EQ(out[3][0], 0x08080808u); 771 EXPECT_EQ(out[3][1], 0x08080808u); 772 773 EXPECT_EQ(out[4][0], 0x7F7F7F7Fu); 774 EXPECT_EQ(out[4][1], 0x7E7F7F7Fu); 775 776 EXPECT_EQ(out[5][0], 0x80808080u); 777 EXPECT_EQ(out[5][1], 0x88868482u); 778 779 EXPECT_EQ(out[6][0], 0x80808080u); 780 EXPECT_EQ(out[6][1], 0x88868482u); 781 782 EXPECT_EQ(out[7][0], 0x00040004u); 783 EXPECT_EQ(out[7][1], 0x00040004u); 784 785 EXPECT_EQ(out[8][0], 0x7FFF7FFFu); 786 EXPECT_EQ(out[8][1], 0x7FFE7FFFu); 787 788 EXPECT_EQ(out[9][0], 0x80008000u); 789 EXPECT_EQ(out[9][1], 0x80048002u); 790 791 EXPECT_EQ(out[10][0], 0x80008000u); 792 EXPECT_EQ(out[10][1], 0x80048002u); 793 794 EXPECT_EQ(out[11][0], 0x00040004u); 795 EXPECT_EQ(out[11][1], 0x00040004u); 796 797 EXPECT_EQ(out[12][0], 0xFFFFFFFFu); 798 EXPECT_EQ(out[12][1], 0xFFFEFFFFu); 799 800 EXPECT_EQ(out[13][0], 0x00000000u); 801 EXPECT_EQ(out[13][1], 0x00040002u); 802 } 803 } 804 805 delete routine; 806 } 807 808 TEST(SubzeroReactorTest, Unpack) 809 { 810 Routine *routine = nullptr; 811 812 { 813 Function<Int(Pointer<Byte>,Pointer<Byte>)> function; 814 { 815 Pointer<Byte> in = function.Arg<0>(); 816 Pointer<Byte> out = function.Arg<1>(); 817 818 Byte4 test_byte_a = *Pointer<Byte4>(in + 4 * 0); 819 Byte4 test_byte_b = *Pointer<Byte4>(in + 4 * 1); 820 821 *Pointer<Short4>(out + 8 * 0) = 822 Unpack(test_byte_a, test_byte_b); 823 824 *Pointer<Short4>(out + 8 * 1) = Unpack(test_byte_a); 825 826 Return(0); 827 } 828 829 routine = function(L"one"); 830 831 if(routine) 832 { 833 unsigned int in[1][2]; 834 unsigned int out[2][2]; 835 836 memset(&out, 0, sizeof(out)); 837 838 in[0][0] = 0xABCDEF12u; 839 in[0][1] = 0x34567890u; 840 841 int(*callable)(void*,void*) = (int(*)(void*,void*))routine->getEntry(); 842 callable(&in, &out); 843 844 EXPECT_EQ(out[0][0], 0x78EF9012u); 845 EXPECT_EQ(out[0][1], 0x34AB56CDu); 846 847 EXPECT_EQ(out[1][0], 0xEFEF1212u); 848 EXPECT_EQ(out[1][1], 0xABABCDCDu); 849 } 850 } 851 852 delete routine; 853 } 854 855 TEST(SubzeroReactorTest, Pack) 856 { 857 Routine *routine = nullptr; 858 859 { 860 Function<Int(Pointer<Byte>)> function; 861 { 862 Pointer<Byte> out = function.Arg<0>(); 863 864 *Pointer<SByte8>(out + 8 * 0) = 865 PackSigned(Short4(-1, -2, 1, 2), 866 Short4(3, 4, -3, -4)); 867 868 *Pointer<Byte8>(out + 8 * 1) = 869 PackUnsigned(Short4(-1, -2, 1, 2), 870 Short4(3, 4, -3, -4)); 871 872 *Pointer<Short8>(out + 8 * 2) = 873 PackSigned(Int4(-1, -2, 1, 2), 874 Int4(3, 4, -3, -4)); 875 876 *Pointer<UShort8>(out + 8 * 4) = 877 PackUnsigned(Int4(-1, -2, 1, 2), 878 Int4(3, 4, -3, -4)); 879 880 Return(0); 881 } 882 883 routine = function(L"one"); 884 885 if(routine) 886 { 887 unsigned int out[6][2]; 888 889 memset(&out, 0, sizeof(out)); 890 891 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 892 callable(&out); 893 894 EXPECT_EQ(out[0][0], 0x0201FEFFu); 895 EXPECT_EQ(out[0][1], 0xFCFD0403u); 896 897 EXPECT_EQ(out[1][0], 0x02010000u); 898 EXPECT_EQ(out[1][1], 0x00000403u); 899 900 EXPECT_EQ(out[2][0], 0xFFFEFFFFu); 901 EXPECT_EQ(out[2][1], 0x00020001u); 902 903 EXPECT_EQ(out[3][0], 0x00040003u); 904 EXPECT_EQ(out[3][1], 0xFFFCFFFDu); 905 906 EXPECT_EQ(out[4][0], 0x00000000u); 907 EXPECT_EQ(out[4][1], 0x00020001u); 908 909 EXPECT_EQ(out[5][0], 0x00040003u); 910 EXPECT_EQ(out[5][1], 0x00000000u); 911 } 912 } 913 914 delete routine; 915 } 916 917 TEST(SubzeroReactorTest, MulHigh) 918 { 919 Routine *routine = nullptr; 920 921 { 922 Function<Int(Pointer<Byte>)> function; 923 { 924 Pointer<Byte> out = function.Arg<0>(); 925 926 *Pointer<Short4>(out + 8 * 0) = 927 MulHigh(Short4(0x1aa, 0x2dd, 0x3ee, 0xF422), 928 Short4(0x1bb, 0x2cc, 0x3ff, 0xF411)); 929 *Pointer<UShort4>(out + 8 * 1) = 930 MulHigh(UShort4(0x1aa, 0x2dd, 0x3ee, 0xF422), 931 UShort4(0x1bb, 0x2cc, 0x3ff, 0xF411)); 932 933 // (U)Short8 variants are mentioned but unimplemented 934 Return(0); 935 } 936 937 routine = function(L"one"); 938 939 if(routine) 940 { 941 unsigned int out[2][2]; 942 943 memset(&out, 0, sizeof(out)); 944 945 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 946 callable(&out); 947 948 EXPECT_EQ(out[0][0], 0x00080002u); 949 EXPECT_EQ(out[0][1], 0x008D000fu); 950 951 EXPECT_EQ(out[1][0], 0x00080002u); 952 EXPECT_EQ(out[1][1], 0xe8C0000Fu); 953 } 954 } 955 956 delete routine; 957 } 958 959 TEST(SubzeroReactorTest, MulAdd) 960 { 961 Routine *routine = nullptr; 962 963 { 964 Function<Int(Pointer<Byte>)> function; 965 { 966 Pointer<Byte> out = function.Arg<0>(); 967 968 *Pointer<Int2>(out + 8 * 0) = 969 MulAdd(Short4(0x1aa, 0x2dd, 0x3ee, 0xF422), 970 Short4(0x1bb, 0x2cc, 0x3ff, 0xF411)); 971 972 // (U)Short8 variant is mentioned but unimplemented 973 Return(0); 974 } 975 976 routine = function(L"one"); 977 978 if(routine) 979 { 980 unsigned int out[1][2]; 981 982 memset(&out, 0, sizeof(out)); 983 984 int(*callable)(void*) = (int(*)(void*))routine->getEntry(); 985 callable(&out); 986 987 EXPECT_EQ(out[0][0], 0x000AE34Au); 988 EXPECT_EQ(out[0][1], 0x009D5254u); 989 } 990 } 991 992 delete routine; 993 } 994 995 int main(int argc, char **argv) 996 { 997 ::testing::InitGoogleTest(&argc, argv); 998 return RUN_ALL_TESTS(); 999 } 1000