blob: e74703b8f80c248aca3abf7a88e9bbe0972b9022 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029#include <iostream> // NOLINT(readability/streams)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030
31#include "src/v8.h"
32#include "test/cctest/cctest.h"
33
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "src/macro-assembler.h"
36#include "src/mips64/macro-assembler-mips64.h"
37#include "src/mips64/simulator-mips64.h"
38
39
40using namespace v8::internal;
41
42typedef void* (*F)(int64_t x, int64_t y, int p2, int p3, int p4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044
45#define __ masm->
46
47
48static byte to_non_zero(int n) {
49 return static_cast<unsigned>(n) % 255 + 1;
50}
51
52
53static bool all_zeroes(const byte* beg, const byte* end) {
54 CHECK(beg);
55 CHECK(beg <= end);
56 while (beg < end) {
57 if (*beg++ != 0)
58 return false;
59 }
60 return true;
61}
62
63
64TEST(CopyBytes) {
65 CcTest::InitializeVM();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 Isolate* isolate = CcTest::i_isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 HandleScope handles(isolate);
68
69 const int data_size = 1 * KB;
70 size_t act_size;
71
72 // Allocate two blocks to copy data between.
73 byte* src_buffer =
74 static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
75 CHECK(src_buffer);
76 CHECK(act_size >= static_cast<size_t>(data_size));
77 byte* dest_buffer =
78 static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
79 CHECK(dest_buffer);
80 CHECK(act_size >= static_cast<size_t>(data_size));
81
82 // Storage for a0 and a1.
83 byte* a0_;
84 byte* a1_;
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 MacroAssembler assembler(isolate, NULL, 0,
87 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 MacroAssembler* masm = &assembler;
89
90 // Code to be generated: The stuff in CopyBytes followed by a store of a0 and
91 // a1, respectively.
92 __ CopyBytes(a0, a1, a2, a3);
93 __ li(a2, Operand(reinterpret_cast<int64_t>(&a0_)));
94 __ li(a3, Operand(reinterpret_cast<int64_t>(&a1_)));
95 __ sd(a0, MemOperand(a2));
96 __ jr(ra);
97 __ sd(a1, MemOperand(a3));
98
99 CodeDesc desc;
100 masm->GetCode(&desc);
101 Handle<Code> code = isolate->factory()->NewCode(
102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
103
104 ::F f = FUNCTION_CAST< ::F>(code->entry());
105
106 // Initialise source data with non-zero bytes.
107 for (int i = 0; i < data_size; i++) {
108 src_buffer[i] = to_non_zero(i);
109 }
110
111 const int fuzz = 11;
112
113 for (int size = 0; size < 600; size++) {
114 for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) {
115 for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) {
116 memset(dest_buffer, 0, data_size);
117 CHECK(dest + size < dest_buffer + data_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 (void)CALL_GENERATED_CODE(isolate, f, reinterpret_cast<int64_t>(src),
119 reinterpret_cast<int64_t>(dest), size, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 // a0 and a1 should point at the first byte after the copied data.
121 CHECK_EQ(src + size, a0_);
122 CHECK_EQ(dest + size, a1_);
123 // Check that we haven't written outside the target area.
124 CHECK(all_zeroes(dest_buffer, dest));
125 CHECK(all_zeroes(dest + size, dest_buffer + data_size));
126 // Check the target area.
127 CHECK_EQ(0, memcmp(src, dest, size));
128 }
129 }
130 }
131
132 // Check that the source data hasn't been clobbered.
133 for (int i = 0; i < data_size; i++) {
134 CHECK(src_buffer[i] == to_non_zero(i));
135 }
136}
137
138
139TEST(LoadConstants) {
140 CcTest::InitializeVM();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 Isolate* isolate = CcTest::i_isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142 HandleScope handles(isolate);
143
144 int64_t refConstants[64];
145 int64_t result[64];
146
147 int64_t mask = 1;
148 for (int i = 0; i < 64; i++) {
149 refConstants[i] = ~(mask << i);
150 }
151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 MacroAssembler assembler(isolate, NULL, 0,
153 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 MacroAssembler* masm = &assembler;
155
156 __ mov(a4, a0);
157 for (int i = 0; i < 64; i++) {
158 // Load constant.
159 __ li(a5, Operand(refConstants[i]));
160 __ sd(a5, MemOperand(a4));
161 __ Daddu(a4, a4, Operand(kPointerSize));
162 }
163
164 __ jr(ra);
165 __ nop();
166
167 CodeDesc desc;
168 masm->GetCode(&desc);
169 Handle<Code> code = isolate->factory()->NewCode(
170 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
171
172 ::F f = FUNCTION_CAST< ::F>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 (void)CALL_GENERATED_CODE(isolate, f, reinterpret_cast<int64_t>(result), 0, 0,
174 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 // Check results.
176 for (int i = 0; i < 64; i++) {
177 CHECK(refConstants[i] == result[i]);
178 }
179}
180
181
182TEST(LoadAddress) {
183 CcTest::InitializeVM();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 Isolate* isolate = CcTest::i_isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 HandleScope handles(isolate);
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 MacroAssembler assembler(isolate, NULL, 0,
188 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 MacroAssembler* masm = &assembler;
190 Label to_jump, skip;
191 __ mov(a4, a0);
192
193 __ Branch(&skip);
194 __ bind(&to_jump);
195 __ nop();
196 __ nop();
197 __ jr(ra);
198 __ nop();
199 __ bind(&skip);
200 __ li(a4, Operand(masm->jump_address(&to_jump)), ADDRESS_LOAD);
201 int check_size = masm->InstructionsGeneratedSince(&skip);
202 CHECK_EQ(check_size, 4);
203 __ jr(a4);
204 __ nop();
205 __ stop("invalid");
206 __ stop("invalid");
207 __ stop("invalid");
208 __ stop("invalid");
209 __ stop("invalid");
210
211
212 CodeDesc desc;
213 masm->GetCode(&desc);
214 Handle<Code> code = isolate->factory()->NewCode(
215 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
216
217 ::F f = FUNCTION_CAST< ::F>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 (void)CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 // Check results.
220}
221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222
223TEST(jump_tables4) {
224 // Similar to test-assembler-mips jump_tables1, with extra test for branch
225 // trampoline required before emission of the dd table (where trampolines are
226 // blocked), and proper transition to long-branch mode.
227 // Regression test for v8:4294.
228 CcTest::InitializeVM();
229 Isolate* isolate = CcTest::i_isolate();
230 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231 MacroAssembler assembler(isolate, nullptr, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 v8::internal::CodeObjectRequired::kYes);
233 MacroAssembler* masm = &assembler;
234
235 const int kNumCases = 512;
236 int values[kNumCases];
237 isolate->random_number_generator()->NextBytes(values, sizeof(values));
238 Label labels[kNumCases];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 Label near_start, end, done;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 __ Push(ra);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 __ mov(v0, zero_reg);
243
244 __ Branch(&end);
245 __ bind(&near_start);
246
247 // Generate slightly less than 32K instructions, which will soon require
248 // trampoline for branch distance fixup.
249 for (int i = 0; i < 32768 - 256; ++i) {
250 __ addiu(v0, v0, 1);
251 }
252
Ben Murdoch097c5b22016-05-18 11:27:45 +0100253 __ GenerateSwitchTable(a0, kNumCases,
254 [&labels](size_t i) { return labels + i; });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255
256 for (int i = 0; i < kNumCases; ++i) {
257 __ bind(&labels[i]);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100258 __ li(v0, values[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 __ Branch(&done);
260 }
261
262 __ bind(&done);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100263 __ Pop(ra);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 __ jr(ra);
265 __ nop();
266
267 __ bind(&end);
268 __ Branch(&near_start);
269
270 CodeDesc desc;
271 masm->GetCode(&desc);
272 Handle<Code> code = isolate->factory()->NewCode(
273 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
274#ifdef OBJECT_PRINT
275 code->Print(std::cout);
276#endif
277 F1 f = FUNCTION_CAST<F1>(code->entry());
278 for (int i = 0; i < kNumCases; ++i) {
279 int64_t res = reinterpret_cast<int64_t>(
280 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
281 ::printf("f(%d) = %" PRId64 "\n", i, res);
282 CHECK_EQ(values[i], res);
283 }
284}
285
286
287TEST(jump_tables5) {
288 if (kArchVariant != kMips64r6) return;
289
290 // Similar to test-assembler-mips jump_tables1, with extra test for emitting a
291 // compact branch instruction before emission of the dd table.
292 CcTest::InitializeVM();
293 Isolate* isolate = CcTest::i_isolate();
294 HandleScope scope(isolate);
295 MacroAssembler assembler(isolate, nullptr, 0,
296 v8::internal::CodeObjectRequired::kYes);
297 MacroAssembler* masm = &assembler;
298
299 const int kNumCases = 512;
300 int values[kNumCases];
301 isolate->random_number_generator()->NextBytes(values, sizeof(values));
302 Label labels[kNumCases];
303 Label done;
304
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 __ Push(ra);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306
Ben Murdoch097c5b22016-05-18 11:27:45 +0100307 // Opposite of Align(8) as we have unaligned number of instructions in the
308 // following block before the first dd().
309 if ((masm->pc_offset() & 7) == 0) {
310 __ nop();
311 }
312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100314 __ BlockTrampolinePoolFor(kNumCases * 2 + 6 + 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 PredictableCodeSizeScope predictable(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100316 masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317
Ben Murdoch097c5b22016-05-18 11:27:45 +0100318 __ addiupc(at, 6 + 1);
319 __ dlsa(at, at, a0, 3);
320 __ ld(at, MemOperand(at));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 __ jalr(at);
322 __ nop(); // Branch delay slot nop.
323 __ bc(&done);
324 // A nop instruction must be generated by the forbidden slot guard
325 // (Assembler::dd(Label*)) so the first label goes to an 8 bytes aligned
326 // location.
327 for (int i = 0; i < kNumCases; ++i) {
328 __ dd(&labels[i]);
329 }
330 }
331
332 for (int i = 0; i < kNumCases; ++i) {
333 __ bind(&labels[i]);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100334 __ li(v0, values[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 __ jr(ra);
336 __ nop();
337 }
338
339 __ bind(&done);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 __ Pop(ra);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 __ jr(ra);
342 __ nop();
343
344 CodeDesc desc;
345 masm->GetCode(&desc);
346 Handle<Code> code = isolate->factory()->NewCode(
347 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
348#ifdef OBJECT_PRINT
349 code->Print(std::cout);
350#endif
351 F1 f = FUNCTION_CAST<F1>(code->entry());
352 for (int i = 0; i < kNumCases; ++i) {
353 int64_t res = reinterpret_cast<int64_t>(
354 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
355 ::printf("f(%d) = %" PRId64 "\n", i, res);
356 CHECK_EQ(values[i], res);
357 }
358}
359
360
361static uint64_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
362 Isolate* isolate = CcTest::i_isolate();
363 HandleScope scope(isolate);
364 MacroAssembler assembler(isolate, nullptr, 0,
365 v8::internal::CodeObjectRequired::kYes);
366 MacroAssembler* masm = &assembler;
367
368 __ Lsa(v0, a0, a1, sa);
369 __ jr(ra);
370 __ nop();
371
372 CodeDesc desc;
373 assembler.GetCode(&desc);
374 Handle<Code> code = isolate->factory()->NewCode(
375 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
376
377 F1 f = FUNCTION_CAST<F1>(code->entry());
378
379 uint64_t res = reinterpret_cast<uint64_t>(
380 CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
381
382 return res;
383}
384
385
386TEST(Lsa) {
387 CcTest::InitializeVM();
388 struct TestCaseLsa {
389 int32_t rt;
390 int32_t rs;
391 uint8_t sa;
392 uint64_t expected_res;
393 };
394
395 struct TestCaseLsa tc[] = {// rt, rs, sa, expected_res
396 {0x4, 0x1, 1, 0x6},
397 {0x4, 0x1, 2, 0x8},
398 {0x4, 0x1, 3, 0xc},
399 {0x4, 0x1, 4, 0x14},
400 {0x4, 0x1, 5, 0x24},
401 {0x0, 0x1, 1, 0x2},
402 {0x0, 0x1, 2, 0x4},
403 {0x0, 0x1, 3, 0x8},
404 {0x0, 0x1, 4, 0x10},
405 {0x0, 0x1, 5, 0x20},
406 {0x4, 0x0, 1, 0x4},
407 {0x4, 0x0, 2, 0x4},
408 {0x4, 0x0, 3, 0x4},
409 {0x4, 0x0, 4, 0x4},
410 {0x4, 0x0, 5, 0x4},
411
412 // Shift overflow.
413 {0x4, INT32_MAX, 1, 0x2},
414 {0x4, INT32_MAX >> 1, 2, 0x0},
415 {0x4, INT32_MAX >> 2, 3, 0xfffffffffffffffc},
416 {0x4, INT32_MAX >> 3, 4, 0xfffffffffffffff4},
417 {0x4, INT32_MAX >> 4, 5, 0xffffffffffffffe4},
418
419 // Signed addition overflow.
420 {INT32_MAX - 1, 0x1, 1, 0xffffffff80000000},
421 {INT32_MAX - 3, 0x1, 2, 0xffffffff80000000},
422 {INT32_MAX - 7, 0x1, 3, 0xffffffff80000000},
423 {INT32_MAX - 15, 0x1, 4, 0xffffffff80000000},
424 {INT32_MAX - 31, 0x1, 5, 0xffffffff80000000},
425
426 // Addition overflow.
427 {-2, 0x1, 1, 0x0},
428 {-4, 0x1, 2, 0x0},
429 {-8, 0x1, 3, 0x0},
430 {-16, 0x1, 4, 0x0},
431 {-32, 0x1, 5, 0x0}};
432
433 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
434 for (size_t i = 0; i < nr_test_cases; ++i) {
435 uint64_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa);
436 PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Lsa(v0, %x, %x, %hhu)\n",
437 tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa);
438 CHECK_EQ(tc[i].expected_res, res);
439 }
440}
441
442
443static uint64_t run_dlsa(uint64_t rt, uint64_t rs, int8_t sa) {
444 Isolate* isolate = CcTest::i_isolate();
445 HandleScope scope(isolate);
446 MacroAssembler assembler(isolate, nullptr, 0,
447 v8::internal::CodeObjectRequired::kYes);
448 MacroAssembler* masm = &assembler;
449
450 __ Dlsa(v0, a0, a1, sa);
451 __ jr(ra);
452 __ nop();
453
454 CodeDesc desc;
455 assembler.GetCode(&desc);
456 Handle<Code> code = isolate->factory()->NewCode(
457 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
458
459 ::F f = FUNCTION_CAST<::F>(code->entry());
460
461 uint64_t res = reinterpret_cast<uint64_t>(
462 CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
463
464 return res;
465}
466
467
468TEST(Dlsa) {
469 CcTest::InitializeVM();
470 struct TestCaseLsa {
471 int64_t rt;
472 int64_t rs;
473 uint8_t sa;
474 uint64_t expected_res;
475 };
476
477 struct TestCaseLsa tc[] = {// rt, rs, sa, expected_res
478 {0x4, 0x1, 1, 0x6},
479 {0x4, 0x1, 2, 0x8},
480 {0x4, 0x1, 3, 0xc},
481 {0x4, 0x1, 4, 0x14},
482 {0x4, 0x1, 5, 0x24},
483 {0x0, 0x1, 1, 0x2},
484 {0x0, 0x1, 2, 0x4},
485 {0x0, 0x1, 3, 0x8},
486 {0x0, 0x1, 4, 0x10},
487 {0x0, 0x1, 5, 0x20},
488 {0x4, 0x0, 1, 0x4},
489 {0x4, 0x0, 2, 0x4},
490 {0x4, 0x0, 3, 0x4},
491 {0x4, 0x0, 4, 0x4},
492 {0x4, 0x0, 5, 0x4},
493
494 // Shift overflow.
495 {0x4, INT64_MAX, 1, 0x2},
496 {0x4, INT64_MAX >> 1, 2, 0x0},
497 {0x4, INT64_MAX >> 2, 3, 0xfffffffffffffffc},
498 {0x4, INT64_MAX >> 3, 4, 0xfffffffffffffff4},
499 {0x4, INT64_MAX >> 4, 5, 0xffffffffffffffe4},
500
501 // Signed addition overflow.
502 {INT64_MAX - 1, 0x1, 1, 0x8000000000000000},
503 {INT64_MAX - 3, 0x1, 2, 0x8000000000000000},
504 {INT64_MAX - 7, 0x1, 3, 0x8000000000000000},
505 {INT64_MAX - 15, 0x1, 4, 0x8000000000000000},
506 {INT64_MAX - 31, 0x1, 5, 0x8000000000000000},
507
508 // Addition overflow.
509 {-2, 0x1, 1, 0x0},
510 {-4, 0x1, 2, 0x0},
511 {-8, 0x1, 3, 0x0},
512 {-16, 0x1, 4, 0x0},
513 {-32, 0x1, 5, 0x0}};
514
515 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
516 for (size_t i = 0; i < nr_test_cases; ++i) {
517 uint64_t res = run_dlsa(tc[i].rt, tc[i].rs, tc[i].sa);
518 PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Dlsa(v0, %" PRIx64 ", %" PRIx64
519 ", %hhu)\n",
520 tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa);
521 CHECK_EQ(tc[i].expected_res, res);
522 }
523}
524
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525#undef __