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 rr;
20
reference(int * p,int y)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
TEST(ReactorUnitTests,Sample)36 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Uninitialized)76 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,SubVectorLoadStore)113 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,VectorConstant)173 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Concatenate)222 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Swizzle)265 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Branching)392 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,MinMax)457 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,NotNeg)548 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,VectorCompare)633 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,SaturatedAddAndSubtract)695 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Unpack)808 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,Pack)855 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,MulHigh)917 TEST(ReactorUnitTests, 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("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
TEST(ReactorUnitTests,MulAdd)959 TEST(ReactorUnitTests, 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("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
main(int argc,char ** argv)995 int main(int argc, char **argv)
996 {
997 ::testing::InitGoogleTest(&argc, argv);
998 return RUN_ALL_TESTS();
999 }
1000