Home | History | Annotate | Download | only in Reactor
      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