1 // [AsmJit]
2 // Machine Code Generation for C++.
3 //
4 // [License]
5 // Zlib - See LICENSE.md file in the package.
6
7 #include <setjmp.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "./asmjit.h"
13 #include "./asmjit_test_misc.h"
14
15 using namespace asmjit;
16
17 // ============================================================================
18 // [CmdLine]
19 // ============================================================================
20
21 class CmdLine {
22 public:
CmdLine(int argc,const char * const * argv)23 CmdLine(int argc, const char* const* argv) noexcept
24 : _argc(argc),
25 _argv(argv) {}
26
hasArg(const char * arg)27 bool hasArg(const char* arg) noexcept {
28 for (int i = 1; i < _argc; i++)
29 if (strcmp(_argv[i], arg) == 0)
30 return true;
31 return false;
32 }
33
34 int _argc;
35 const char* const* _argv;
36 };
37
38 // ============================================================================
39 // [SimpleErrorHandler]
40 // ============================================================================
41
42 class SimpleErrorHandler : public ErrorHandler {
43 public:
SimpleErrorHandler()44 SimpleErrorHandler() : _err(kErrorOk) {}
handleError(Error err,const char * message,BaseEmitter * origin)45 virtual void handleError(Error err, const char* message, BaseEmitter* origin) {
46 ASMJIT_UNUSED(origin);
47 _err = err;
48 _message.assignString(message);
49 }
50
51 Error _err;
52 String _message;
53 };
54
55 // ============================================================================
56 // [X86Test]
57 // ============================================================================
58
59 //! Base test interface for testing `x86::Compiler`.
60 class X86Test {
61 public:
X86Test(const char * name=nullptr)62 X86Test(const char* name = nullptr) { _name.assignString(name); }
~X86Test()63 virtual ~X86Test() {}
64
name() const65 inline const char* name() const { return _name.data(); }
66
67 virtual void compile(x86::Compiler& c) = 0;
68 virtual bool run(void* func, String& result, String& expect) = 0;
69
70 String _name;
71 };
72
73 // ============================================================================
74 // [X86TestApp]
75 // ============================================================================
76
77 class X86TestApp {
78 public:
79 Zone _zone;
80 ZoneAllocator _allocator;
81 ZoneVector<X86Test*> _tests;
82
83 unsigned _nFailed;
84 size_t _outputSize;
85
86 bool _verbose;
87 bool _dumpAsm;
88
X86TestApp()89 X86TestApp() noexcept
90 : _zone(8096 - Zone::kBlockOverhead),
91 _allocator(&_zone),
92 _nFailed(0),
93 _outputSize(0),
94 _verbose(false),
95 _dumpAsm(false) {}
96
~X86TestApp()97 ~X86TestApp() noexcept {
98 for (X86Test* test : _tests)
99 delete test;
100 }
101
add(X86Test * test)102 Error add(X86Test* test) noexcept{
103 return _tests.append(&_allocator, test);
104 }
105
106 template<class T>
addT()107 inline void addT() { T::add(*this); }
108
109 int handleArgs(int argc, const char* const* argv);
110 void showInfo();
111 int run();
112 };
113
handleArgs(int argc,const char * const * argv)114 int X86TestApp::handleArgs(int argc, const char* const* argv) {
115 CmdLine cmd(argc, argv);
116
117 if (cmd.hasArg("--verbose")) _verbose = true;
118 if (cmd.hasArg("--dump-asm")) _dumpAsm = true;
119
120 return 0;
121 }
122
showInfo()123 void X86TestApp::showInfo() {
124 printf("AsmJit Compiler Test-Suite v%u.%u.%u [Arch=%s]:\n",
125 unsigned((ASMJIT_LIBRARY_VERSION >> 16) ),
126 unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF),
127 unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF),
128 sizeof(void*) == 8 ? "X64" : "X86");
129 printf(" [%s] Verbose (use --verbose to turn verbose output ON)\n", _verbose ? "x" : " ");
130 printf(" [%s] DumpAsm (use --dump-asm to turn assembler dumps ON)\n", _dumpAsm ? "x" : " ");
131 printf("\n");
132 }
133
run()134 int X86TestApp::run() {
135 #ifndef ASMJIT_NO_LOGGING
136 uint32_t kFormatFlags = FormatOptions::kFlagMachineCode |
137 FormatOptions::kFlagExplainImms |
138 FormatOptions::kFlagRegCasts |
139 FormatOptions::kFlagAnnotations |
140 FormatOptions::kFlagDebugPasses |
141 FormatOptions::kFlagDebugRA ;
142
143 FileLogger fileLogger(stdout);
144 fileLogger.addFlags(kFormatFlags);
145
146 StringLogger stringLogger;
147 stringLogger.addFlags(kFormatFlags);
148 #endif
149
150 for (X86Test* test : _tests) {
151 JitRuntime runtime;
152 CodeHolder code;
153 SimpleErrorHandler errorHandler;
154
155 code.init(runtime.codeInfo());
156 code.setErrorHandler(&errorHandler);
157
158 #ifndef ASMJIT_NO_LOGGING
159 if (_verbose) {
160 code.setLogger(&fileLogger);
161 }
162 else {
163 stringLogger.clear();
164 code.setLogger(&stringLogger);
165 }
166 #endif
167
168 printf("[Test] %s", test->name());
169
170 #ifndef ASMJIT_NO_LOGGING
171 if (_verbose) printf("\n");
172 #endif
173
174 x86::Compiler cc(&code);
175 test->compile(cc);
176
177 Error err = errorHandler._err;
178 if (!err)
179 err = cc.finalize();
180 void* func;
181
182 #ifndef ASMJIT_NO_LOGGING
183 if (_dumpAsm) {
184 if (!_verbose) printf("\n");
185
186 String sb;
187 cc.dump(sb, kFormatFlags);
188 printf("%s", sb.data());
189 }
190 #endif
191
192 if (err == kErrorOk)
193 err = runtime.add(&func, &code);
194
195 if (_verbose)
196 fflush(stdout);
197
198 if (err == kErrorOk) {
199 _outputSize += code.codeSize();
200
201 StringTmp<128> result;
202 StringTmp<128> expect;
203
204 if (test->run(func, result, expect)) {
205 if (!_verbose) printf(" [OK]\n");
206 }
207 else {
208 if (!_verbose) printf(" [FAILED]\n");
209
210 #ifndef ASMJIT_NO_LOGGING
211 if (!_verbose) printf("%s", stringLogger.data());
212 #endif
213
214 printf("[Status]\n");
215 printf(" Returned: %s\n", result.data());
216 printf(" Expected: %s\n", expect.data());
217
218 _nFailed++;
219 }
220
221 if (_dumpAsm)
222 printf("\n");
223
224 runtime.release(func);
225 }
226 else {
227 if (!_verbose) printf(" [FAILED]\n");
228
229 #ifndef ASMJIT_NO_LOGGING
230 if (!_verbose) printf("%s", stringLogger.data());
231 #endif
232
233 printf("[Status]\n");
234 printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data());
235
236 _nFailed++;
237 }
238 }
239
240 if (_nFailed == 0)
241 printf("\n[PASSED] All %u tests passed\n", unsigned(_tests.size()));
242 else
243 printf("\n[FAILED] %u %s of %u failed\n", _nFailed, _nFailed == 1 ? "test" : "tests", unsigned(_tests.size()));
244
245 printf(" OutputSize=%zu\n", _outputSize);
246
247 return _nFailed == 0 ? 0 : 1;
248 }
249
250 // ============================================================================
251 // [X86Test_AlignBase]
252 // ============================================================================
253
254 class X86Test_AlignBase : public X86Test {
255 public:
X86Test_AlignBase(uint32_t argCount,uint32_t alignment,bool preserveFP)256 X86Test_AlignBase(uint32_t argCount, uint32_t alignment, bool preserveFP)
257 : _argCount(argCount),
258 _alignment(alignment),
259 _preserveFP(preserveFP) {
260 _name.assignFormat("AlignBase {NumArgs=%u Alignment=%u PreserveFP=%c}", argCount, alignment, preserveFP ? 'Y' : 'N');
261 }
262
add(X86TestApp & app)263 static void add(X86TestApp& app) {
264 for (uint32_t i = 0; i <= 16; i++) {
265 for (uint32_t a = 16; a <= 32; a += 16) {
266 app.add(new X86Test_AlignBase(i, a, true));
267 app.add(new X86Test_AlignBase(i, a, false));
268 }
269 }
270 }
271
compile(x86::Compiler & cc)272 virtual void compile(x86::Compiler& cc) {
273 uint32_t i;
274 uint32_t argCount = _argCount;
275
276 FuncSignatureBuilder signature(CallConv::kIdHost);
277 signature.setRetT<int>();
278 for (i = 0; i < argCount; i++)
279 signature.addArgT<int>();
280
281 cc.addFunc(signature);
282 if (_preserveFP)
283 cc.func()->frame().setPreservedFP();
284
285 x86::Gp gpVar = cc.newIntPtr("gpVar");
286 x86::Gp gpSum;
287 x86::Mem stack = cc.newStack(_alignment, _alignment);
288
289 // Do a sum of arguments to verify a possible relocation when misaligned.
290 if (argCount) {
291 for (i = 0; i < argCount; i++) {
292 x86::Gp gpArg = cc.newInt32("gpArg%u", i);
293 cc.setArg(i, gpArg);
294
295 if (i == 0)
296 gpSum = gpArg;
297 else
298 cc.add(gpSum, gpArg);
299 }
300 }
301
302 // Check alignment of xmmVar (has to be 16).
303 cc.lea(gpVar, stack);
304 cc.and_(gpVar, _alignment - 1);
305
306 // Add a sum of all arguments to check if they are correct.
307 if (argCount)
308 cc.or_(gpVar.r32(), gpSum);
309
310 cc.ret(gpVar);
311 cc.endFunc();
312 }
313
run(void * _func,String & result,String & expect)314 virtual bool run(void* _func, String& result, String& expect) {
315 typedef unsigned int U;
316
317 typedef U (*Func0)();
318 typedef U (*Func1)(U);
319 typedef U (*Func2)(U, U);
320 typedef U (*Func3)(U, U, U);
321 typedef U (*Func4)(U, U, U, U);
322 typedef U (*Func5)(U, U, U, U, U);
323 typedef U (*Func6)(U, U, U, U, U, U);
324 typedef U (*Func7)(U, U, U, U, U, U, U);
325 typedef U (*Func8)(U, U, U, U, U, U, U, U);
326 typedef U (*Func9)(U, U, U, U, U, U, U, U, U);
327 typedef U (*Func10)(U, U, U, U, U, U, U, U, U, U);
328 typedef U (*Func11)(U, U, U, U, U, U, U, U, U, U, U);
329 typedef U (*Func12)(U, U, U, U, U, U, U, U, U, U, U, U);
330 typedef U (*Func13)(U, U, U, U, U, U, U, U, U, U, U, U, U);
331 typedef U (*Func14)(U, U, U, U, U, U, U, U, U, U, U, U, U, U);
332 typedef U (*Func15)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
333 typedef U (*Func16)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
334
335 unsigned int resultRet = 0;
336 unsigned int expectRet = 0;
337
338 switch (_argCount) {
339 case 0:
340 resultRet = ptr_as_func<Func0>(_func)();
341 expectRet = 0;
342 break;
343 case 1:
344 resultRet = ptr_as_func<Func1>(_func)(1);
345 expectRet = 1;
346 break;
347 case 2:
348 resultRet = ptr_as_func<Func2>(_func)(1, 2);
349 expectRet = 1 + 2;
350 break;
351 case 3:
352 resultRet = ptr_as_func<Func3>(_func)(1, 2, 3);
353 expectRet = 1 + 2 + 3;
354 break;
355 case 4:
356 resultRet = ptr_as_func<Func4>(_func)(1, 2, 3, 4);
357 expectRet = 1 + 2 + 3 + 4;
358 break;
359 case 5:
360 resultRet = ptr_as_func<Func5>(_func)(1, 2, 3, 4, 5);
361 expectRet = 1 + 2 + 3 + 4 + 5;
362 break;
363 case 6:
364 resultRet = ptr_as_func<Func6>(_func)(1, 2, 3, 4, 5, 6);
365 expectRet = 1 + 2 + 3 + 4 + 5 + 6;
366 break;
367 case 7:
368 resultRet = ptr_as_func<Func7>(_func)(1, 2, 3, 4, 5, 6, 7);
369 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7;
370 break;
371 case 8:
372 resultRet = ptr_as_func<Func8>(_func)(1, 2, 3, 4, 5, 6, 7, 8);
373 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8;
374 break;
375 case 9:
376 resultRet = ptr_as_func<Func9>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9);
377 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9;
378 break;
379 case 10:
380 resultRet = ptr_as_func<Func10>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
381 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
382 break;
383 case 11:
384 resultRet = ptr_as_func<Func11>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
385 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
386 break;
387 case 12:
388 resultRet = ptr_as_func<Func12>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
389 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
390 break;
391 case 13:
392 resultRet = ptr_as_func<Func13>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
393 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13;
394 break;
395 case 14:
396 resultRet = ptr_as_func<Func14>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
397 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14;
398 break;
399 case 15:
400 resultRet = ptr_as_func<Func15>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
401 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15;
402 break;
403 case 16:
404 resultRet = ptr_as_func<Func16>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
405 expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
406 break;
407 }
408
409 result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu);
410 expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu);
411
412 return resultRet == expectRet;
413 }
414
415 uint32_t _argCount;
416 uint32_t _alignment;
417 bool _preserveFP;
418 };
419
420 // ============================================================================
421 // [X86Test_NoCode]
422 // ============================================================================
423
424 class X86Test_NoCode : public X86Test {
425 public:
X86Test_NoCode()426 X86Test_NoCode() : X86Test("NoCode") {}
427
add(X86TestApp & app)428 static void add(X86TestApp& app) {
429 app.add(new X86Test_NoCode());
430 }
431
compile(x86::Compiler & cc)432 virtual void compile(x86::Compiler& cc) {
433 cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost));
434 cc.endFunc();
435 }
436
run(void * _func,String & result,String & expect)437 virtual bool run(void* _func, String& result, String& expect) {
438 ASMJIT_UNUSED(result);
439 ASMJIT_UNUSED(expect);
440
441 typedef void(*Func)(void);
442 Func func = ptr_as_func<Func>(_func);
443
444 func();
445 return true;
446 }
447 };
448
449 // ============================================================================
450 // [X86Test_AlignNone]
451 // ============================================================================
452
453 class X86Test_NoAlign : public X86Test {
454 public:
X86Test_NoAlign()455 X86Test_NoAlign() : X86Test("NoAlign") {}
456
add(X86TestApp & app)457 static void add(X86TestApp& app) {
458 app.add(new X86Test_NoAlign());
459 }
460
compile(x86::Compiler & cc)461 virtual void compile(x86::Compiler& cc) {
462 cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost));
463 cc.align(kAlignCode, 0);
464 cc.align(kAlignCode, 1);
465 cc.endFunc();
466 }
467
run(void * _func,String & result,String & expect)468 virtual bool run(void* _func, String& result, String& expect) {
469 ASMJIT_UNUSED(result);
470 ASMJIT_UNUSED(expect);
471
472 typedef void (*Func)(void);
473 Func func = ptr_as_func<Func>(_func);
474
475 func();
476 return true;
477 }
478 };
479
480 // ============================================================================
481 // [X86Test_JumpMerge]
482 // ============================================================================
483
484 class X86Test_JumpMerge : public X86Test {
485 public:
X86Test_JumpMerge()486 X86Test_JumpMerge() : X86Test("JumpMerge") {}
487
add(X86TestApp & app)488 static void add(X86TestApp& app) {
489 app.add(new X86Test_JumpMerge());
490 }
491
compile(x86::Compiler & cc)492 virtual void compile(x86::Compiler& cc) {
493 cc.addFunc(FuncSignatureT<void, int*, int>(CallConv::kIdHost));
494
495 Label L0 = cc.newLabel();
496 Label L1 = cc.newLabel();
497 Label L2 = cc.newLabel();
498 Label LEnd = cc.newLabel();
499
500 x86::Gp dst = cc.newIntPtr("dst");
501 x86::Gp val = cc.newInt32("val");
502
503 cc.setArg(0, dst);
504 cc.setArg(1, val);
505
506 cc.cmp(val, 0);
507 cc.je(L2);
508
509 cc.cmp(val, 1);
510 cc.je(L1);
511
512 cc.cmp(val, 2);
513 cc.je(L0);
514
515 cc.mov(x86::dword_ptr(dst), val);
516 cc.jmp(LEnd);
517
518 // On purpose. This tests whether the CFG constructs a single basic-block
519 // from multiple labels next to each other.
520 cc.bind(L0);
521 cc.bind(L1);
522 cc.bind(L2);
523 cc.mov(x86::dword_ptr(dst), 0);
524
525 cc.bind(LEnd);
526 cc.endFunc();
527 }
528
run(void * _func,String & result,String & expect)529 virtual bool run(void* _func, String& result, String& expect) {
530 typedef void(*Func)(int*, int);
531 Func func = ptr_as_func<Func>(_func);
532
533 int arr[5] = { -1, -1, -1, -1, -1 };
534 int exp[5] = { 0, 0, 0, 3, 4 };
535
536 for (int i = 0; i < 5; i++)
537 func(&arr[i], i);
538
539 result.assignFormat("ret={%d, %d, %d, %d, %d}", arr[0], arr[1], arr[2], arr[3], arr[4]);
540 expect.assignFormat("ret={%d, %d, %d, %d, %d}", exp[0], exp[1], exp[2], exp[3], exp[4]);
541
542 return result == expect;
543 }
544 };
545
546 // ============================================================================
547 // [X86Test_JumpCross]
548 // ============================================================================
549
550 class X86Test_JumpCross : public X86Test {
551 public:
X86Test_JumpCross()552 X86Test_JumpCross() : X86Test("JumpCross") {}
553
add(X86TestApp & app)554 static void add(X86TestApp& app) {
555 app.add(new X86Test_JumpCross());
556 }
557
compile(x86::Compiler & cc)558 virtual void compile(x86::Compiler& cc) {
559 cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost));
560
561 Label L1 = cc.newLabel();
562 Label L2 = cc.newLabel();
563 Label L3 = cc.newLabel();
564
565 cc.jmp(L2);
566
567 cc.bind(L1);
568 cc.jmp(L3);
569
570 cc.bind(L2);
571 cc.jmp(L1);
572
573 cc.bind(L3);
574 cc.endFunc();
575 }
576
run(void * _func,String & result,String & expect)577 virtual bool run(void* _func, String& result, String& expect) {
578 ASMJIT_UNUSED(result);
579 ASMJIT_UNUSED(expect);
580
581 typedef void (*Func)(void);
582 Func func = ptr_as_func<Func>(_func);
583
584 func();
585 return true;
586 }
587 };
588
589 // ============================================================================
590 // [X86Test_JumpMany]
591 // ============================================================================
592
593 class X86Test_JumpMany : public X86Test {
594 public:
X86Test_JumpMany()595 X86Test_JumpMany() : X86Test("JumpMany") {}
596
add(X86TestApp & app)597 static void add(X86TestApp& app) {
598 app.add(new X86Test_JumpMany());
599 }
600
compile(x86::Compiler & cc)601 virtual void compile(x86::Compiler& cc) {
602 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
603 for (uint32_t i = 0; i < 1000; i++) {
604 Label L = cc.newLabel();
605 cc.jmp(L);
606 cc.bind(L);
607 }
608
609 x86::Gp ret = cc.newInt32("ret");
610 cc.xor_(ret, ret);
611 cc.ret(ret);
612 cc.endFunc();
613 }
614
run(void * _func,String & result,String & expect)615 virtual bool run(void* _func, String& result, String& expect) {
616 typedef int (*Func)(void);
617
618 Func func = ptr_as_func<Func>(_func);
619
620 int resultRet = func();
621 int expectRet = 0;
622
623 result.assignFormat("ret={%d}", resultRet);
624 expect.assignFormat("ret={%d}", expectRet);
625
626 return resultRet == expectRet;
627 }
628 };
629
630 // ============================================================================
631 // [X86Test_JumpUnreachable1]
632 // ============================================================================
633
634 class X86Test_JumpUnreachable1 : public X86Test {
635 public:
X86Test_JumpUnreachable1()636 X86Test_JumpUnreachable1() : X86Test("JumpUnreachable1") {}
637
add(X86TestApp & app)638 static void add(X86TestApp& app) {
639 app.add(new X86Test_JumpUnreachable1());
640 }
641
compile(x86::Compiler & cc)642 virtual void compile(x86::Compiler& cc) {
643 cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost));
644
645 Label L_1 = cc.newLabel();
646 Label L_2 = cc.newLabel();
647 Label L_3 = cc.newLabel();
648 Label L_4 = cc.newLabel();
649 Label L_5 = cc.newLabel();
650 Label L_6 = cc.newLabel();
651 Label L_7 = cc.newLabel();
652
653 x86::Gp v0 = cc.newUInt32("v0");
654 x86::Gp v1 = cc.newUInt32("v1");
655
656 cc.bind(L_2);
657 cc.bind(L_3);
658
659 cc.jmp(L_1);
660
661 cc.bind(L_5);
662 cc.mov(v0, 0);
663
664 cc.bind(L_6);
665 cc.jmp(L_3);
666 cc.mov(v1, 1);
667 cc.jmp(L_1);
668
669 cc.bind(L_4);
670 cc.jmp(L_2);
671 cc.bind(L_7);
672 cc.add(v0, v1);
673
674 cc.align(kAlignCode, 16);
675 cc.bind(L_1);
676 cc.ret();
677 cc.endFunc();
678 }
679
run(void * _func,String & result,String & expect)680 virtual bool run(void* _func, String& result, String& expect) {
681 typedef void (*Func)(void);
682 Func func = ptr_as_func<Func>(_func);
683
684 func();
685
686 result.appendString("ret={}");
687 expect.appendString("ret={}");
688
689 return true;
690 }
691 };
692
693 // ============================================================================
694 // [X86Test_JumpUnreachable2]
695 // ============================================================================
696
697 class X86Test_JumpUnreachable2 : public X86Test {
698 public:
X86Test_JumpUnreachable2()699 X86Test_JumpUnreachable2() : X86Test("JumpUnreachable2") {}
700
add(X86TestApp & app)701 static void add(X86TestApp& app) {
702 app.add(new X86Test_JumpUnreachable2());
703 }
704
compile(x86::Compiler & cc)705 virtual void compile(x86::Compiler& cc) {
706 cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost));
707
708 Label L_1 = cc.newLabel();
709 Label L_2 = cc.newLabel();
710
711 x86::Gp v0 = cc.newUInt32("v0");
712 x86::Gp v1 = cc.newUInt32("v1");
713
714 cc.jmp(L_1);
715 cc.bind(L_2);
716 cc.mov(v0, 1);
717 cc.mov(v1, 2);
718 cc.cmp(v0, v1);
719 cc.jz(L_2);
720 cc.jmp(L_1);
721
722 cc.bind(L_1);
723 cc.ret();
724 cc.endFunc();
725 }
726
run(void * _func,String & result,String & expect)727 virtual bool run(void* _func, String& result, String& expect) {
728 typedef void (*Func)(void);
729 Func func = ptr_as_func<Func>(_func);
730
731 func();
732
733 result.appendString("ret={}");
734 expect.appendString("ret={}");
735
736 return true;
737 }
738 };
739
740 // ============================================================================
741 // [X86Test_AllocBase]
742 // ============================================================================
743
744 class X86Test_AllocBase : public X86Test {
745 public:
X86Test_AllocBase()746 X86Test_AllocBase() : X86Test("AllocBase") {}
747
add(X86TestApp & app)748 static void add(X86TestApp& app) {
749 app.add(new X86Test_AllocBase());
750 }
751
compile(x86::Compiler & cc)752 virtual void compile(x86::Compiler& cc) {
753 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
754
755 x86::Gp v0 = cc.newInt32("v0");
756 x86::Gp v1 = cc.newInt32("v1");
757 x86::Gp v2 = cc.newInt32("v2");
758 x86::Gp v3 = cc.newInt32("v3");
759 x86::Gp v4 = cc.newInt32("v4");
760
761 cc.xor_(v0, v0);
762
763 cc.mov(v1, 1);
764 cc.mov(v2, 2);
765 cc.mov(v3, 3);
766 cc.mov(v4, 4);
767
768 cc.add(v0, v1);
769 cc.add(v0, v2);
770 cc.add(v0, v3);
771 cc.add(v0, v4);
772
773 cc.ret(v0);
774 cc.endFunc();
775 }
776
run(void * _func,String & result,String & expect)777 virtual bool run(void* _func, String& result, String& expect) {
778 typedef int (*Func)(void);
779 Func func = ptr_as_func<Func>(_func);
780
781 int resultRet = func();
782 int expectRet = 1 + 2 + 3 + 4;
783
784 result.assignFormat("ret=%d", resultRet);
785 expect.assignFormat("ret=%d", expectRet);
786
787 return resultRet == expectRet;
788 }
789 };
790
791 // ============================================================================
792 // [X86Test_AllocMany1]
793 // ============================================================================
794
795 class X86Test_AllocMany1 : public X86Test {
796 public:
X86Test_AllocMany1()797 X86Test_AllocMany1() : X86Test("AllocMany1") {}
798
799 enum { kCount = 8 };
800
add(X86TestApp & app)801 static void add(X86TestApp& app) {
802 app.add(new X86Test_AllocMany1());
803 }
804
compile(x86::Compiler & cc)805 virtual void compile(x86::Compiler& cc) {
806 cc.addFunc(FuncSignatureT<void, int*, int*>(CallConv::kIdHost));
807
808 x86::Gp a0 = cc.newIntPtr("a0");
809 x86::Gp a1 = cc.newIntPtr("a1");
810
811 cc.setArg(0, a0);
812 cc.setArg(1, a1);
813
814 // Create some variables.
815 x86::Gp t = cc.newInt32("t");
816 x86::Gp x[kCount];
817
818 uint32_t i;
819
820 // Setup variables (use mov with reg/imm to se if register allocator works).
821 for (i = 0; i < kCount; i++) x[i] = cc.newInt32("x%u", i);
822 for (i = 0; i < kCount; i++) cc.mov(x[i], int(i + 1));
823
824 // Make sum (addition).
825 cc.xor_(t, t);
826 for (i = 0; i < kCount; i++) cc.add(t, x[i]);
827
828 // Store result to a given pointer in first argument.
829 cc.mov(x86::dword_ptr(a0), t);
830
831 // Clear t.
832 cc.xor_(t, t);
833
834 // Make sum (subtraction).
835 for (i = 0; i < kCount; i++) cc.sub(t, x[i]);
836
837 // Store result to a given pointer in second argument.
838 cc.mov(x86::dword_ptr(a1), t);
839
840 // End of function.
841 cc.endFunc();
842 }
843
run(void * _func,String & result,String & expect)844 virtual bool run(void* _func, String& result, String& expect) {
845 typedef void (*Func)(int*, int*);
846 Func func = ptr_as_func<Func>(_func);
847
848 int resultX;
849 int resultY;
850
851 int expectX = 36;
852 int expectY = -36;
853
854 func(&resultX, &resultY);
855
856 result.assignFormat("ret={x=%d, y=%d}", resultX, resultY);
857 expect.assignFormat("ret={x=%d, y=%d}", expectX, expectY);
858
859 return resultX == expectX && resultY == expectY;
860 }
861 };
862
863 // ============================================================================
864 // [X86Test_AllocMany2]
865 // ============================================================================
866
867 class X86Test_AllocMany2 : public X86Test {
868 public:
X86Test_AllocMany2()869 X86Test_AllocMany2() : X86Test("AllocMany2") {}
870
add(X86TestApp & app)871 static void add(X86TestApp& app) {
872 app.add(new X86Test_AllocMany2());
873 }
874
compile(x86::Compiler & cc)875 virtual void compile(x86::Compiler& cc) {
876 cc.addFunc(FuncSignatureT<void, uint32_t*>(CallConv::kIdHost));
877
878 x86::Gp a = cc.newIntPtr("a");
879 x86::Gp v[32];
880
881 uint32_t i;
882 cc.setArg(0, a);
883
884 for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i);
885 for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]);
886
887 x86::Gp x = cc.newInt32("x");
888 Label L = cc.newLabel();
889
890 cc.mov(x, 32);
891 cc.bind(L);
892 for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i);
893
894 cc.dec(x);
895 cc.jnz(L);
896 for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]);
897
898 cc.endFunc();
899 }
900
run(void * _func,String & result,String & expect)901 virtual bool run(void* _func, String& result, String& expect) {
902 typedef void (*Func)(uint32_t*);
903 Func func = ptr_as_func<Func>(_func);
904
905 uint32_t i;
906 uint32_t resultBuf[32];
907 uint32_t expectBuf[32];
908
909 for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++)
910 expectBuf[i] = i * 32;
911 func(resultBuf);
912
913 for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) {
914 if (i != 0) {
915 result.appendChar(',');
916 expect.appendChar(',');
917 }
918
919 result.appendFormat("%u", resultBuf[i]);
920 expect.appendFormat("%u", expectBuf[i]);
921 }
922
923 return result == expect;
924 }
925 };
926
927 // ============================================================================
928 // [X86Test_AllocImul1]
929 // ============================================================================
930
931 class X86Test_AllocImul1 : public X86Test {
932 public:
X86Test_AllocImul1()933 X86Test_AllocImul1() : X86Test("AllocImul1") {}
934
add(X86TestApp & app)935 static void add(X86TestApp& app) {
936 app.add(new X86Test_AllocImul1());
937 }
938
compile(x86::Compiler & cc)939 virtual void compile(x86::Compiler& cc) {
940 cc.addFunc(FuncSignatureT<void, int*, int*, int, int>(CallConv::kIdHost));
941
942 x86::Gp dstHi = cc.newIntPtr("dstHi");
943 x86::Gp dstLo = cc.newIntPtr("dstLo");
944
945 x86::Gp vHi = cc.newInt32("vHi");
946 x86::Gp vLo = cc.newInt32("vLo");
947 x86::Gp src = cc.newInt32("src");
948
949 cc.setArg(0, dstHi);
950 cc.setArg(1, dstLo);
951 cc.setArg(2, vLo);
952 cc.setArg(3, src);
953
954 cc.imul(vHi, vLo, src);
955
956 cc.mov(x86::dword_ptr(dstHi), vHi);
957 cc.mov(x86::dword_ptr(dstLo), vLo);
958 cc.endFunc();
959 }
960
run(void * _func,String & result,String & expect)961 virtual bool run(void* _func, String& result, String& expect) {
962 typedef void (*Func)(int*, int*, int, int);
963 Func func = ptr_as_func<Func>(_func);
964
965 int v0 = 4;
966 int v1 = 4;
967
968 int resultHi;
969 int resultLo;
970
971 int expectHi = 0;
972 int expectLo = v0 * v1;
973
974 func(&resultHi, &resultLo, v0, v1);
975
976 result.assignFormat("hi=%d, lo=%d", resultHi, resultLo);
977 expect.assignFormat("hi=%d, lo=%d", expectHi, expectLo);
978
979 return resultHi == expectHi && resultLo == expectLo;
980 }
981 };
982
983 // ============================================================================
984 // [X86Test_AllocImul2]
985 // ============================================================================
986
987 class X86Test_AllocImul2 : public X86Test {
988 public:
X86Test_AllocImul2()989 X86Test_AllocImul2() : X86Test("AllocImul2") {}
990
add(X86TestApp & app)991 static void add(X86TestApp& app) {
992 app.add(new X86Test_AllocImul2());
993 }
994
compile(x86::Compiler & cc)995 virtual void compile(x86::Compiler& cc) {
996 cc.addFunc(FuncSignatureT<void, int*, const int*>(CallConv::kIdHost));
997
998 x86::Gp dst = cc.newIntPtr("dst");
999 x86::Gp src = cc.newIntPtr("src");
1000
1001 cc.setArg(0, dst);
1002 cc.setArg(1, src);
1003
1004 for (unsigned int i = 0; i < 4; i++) {
1005 x86::Gp x = cc.newInt32("x");
1006 x86::Gp y = cc.newInt32("y");
1007 x86::Gp hi = cc.newInt32("hi");
1008
1009 cc.mov(x, x86::dword_ptr(src, 0));
1010 cc.mov(y, x86::dword_ptr(src, 4));
1011
1012 cc.imul(hi, x, y);
1013 cc.add(x86::dword_ptr(dst, 0), hi);
1014 cc.add(x86::dword_ptr(dst, 4), x);
1015 }
1016
1017 cc.endFunc();
1018 }
1019
run(void * _func,String & result,String & expect)1020 virtual bool run(void* _func, String& result, String& expect) {
1021 typedef void (*Func)(int*, const int*);
1022 Func func = ptr_as_func<Func>(_func);
1023
1024 int src[2] = { 4, 9 };
1025 int resultRet[2] = { 0, 0 };
1026 int expectRet[2] = { 0, (4 * 9) * 4 };
1027
1028 func(resultRet, src);
1029
1030 result.assignFormat("ret={%d, %d}", resultRet[0], resultRet[1]);
1031 expect.assignFormat("ret={%d, %d}", expectRet[0], expectRet[1]);
1032
1033 return resultRet[0] == expectRet[0] && resultRet[1] == expectRet[1];
1034 }
1035 };
1036
1037 // ============================================================================
1038 // [X86Test_AllocIdiv1]
1039 // ============================================================================
1040
1041 class X86Test_AllocIdiv1 : public X86Test {
1042 public:
X86Test_AllocIdiv1()1043 X86Test_AllocIdiv1() : X86Test("AllocIdiv1") {}
1044
add(X86TestApp & app)1045 static void add(X86TestApp& app) {
1046 app.add(new X86Test_AllocIdiv1());
1047 }
1048
compile(x86::Compiler & cc)1049 virtual void compile(x86::Compiler& cc) {
1050 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
1051
1052 x86::Gp a = cc.newInt32("a");
1053 x86::Gp b = cc.newInt32("b");
1054 x86::Gp dummy = cc.newInt32("dummy");
1055
1056 cc.setArg(0, a);
1057 cc.setArg(1, b);
1058
1059 cc.xor_(dummy, dummy);
1060 cc.idiv(dummy, a, b);
1061
1062 cc.ret(a);
1063 cc.endFunc();
1064 }
1065
run(void * _func,String & result,String & expect)1066 virtual bool run(void* _func, String& result, String& expect) {
1067 typedef int (*Func)(int, int);
1068 Func func = ptr_as_func<Func>(_func);
1069
1070 int v0 = 2999;
1071 int v1 = 245;
1072
1073 int resultRet = func(v0, v1);
1074 int expectRet = 2999 / 245;
1075
1076 result.assignFormat("result=%d", resultRet);
1077 expect.assignFormat("result=%d", expectRet);
1078
1079 return resultRet == expectRet;
1080 }
1081 };
1082
1083 // ============================================================================
1084 // [X86Test_AllocSetz]
1085 // ============================================================================
1086
1087 class X86Test_AllocSetz : public X86Test {
1088 public:
X86Test_AllocSetz()1089 X86Test_AllocSetz() : X86Test("AllocSetz") {}
1090
add(X86TestApp & app)1091 static void add(X86TestApp& app) {
1092 app.add(new X86Test_AllocSetz());
1093 }
1094
compile(x86::Compiler & cc)1095 virtual void compile(x86::Compiler& cc) {
1096 cc.addFunc(FuncSignatureT<void, int, int, char*>(CallConv::kIdHost));
1097
1098 x86::Gp src0 = cc.newInt32("src0");
1099 x86::Gp src1 = cc.newInt32("src1");
1100 x86::Gp dst0 = cc.newIntPtr("dst0");
1101
1102 cc.setArg(0, src0);
1103 cc.setArg(1, src1);
1104 cc.setArg(2, dst0);
1105
1106 cc.cmp(src0, src1);
1107 cc.setz(x86::byte_ptr(dst0));
1108
1109 cc.endFunc();
1110 }
1111
run(void * _func,String & result,String & expect)1112 virtual bool run(void* _func, String& result, String& expect) {
1113 typedef void (*Func)(int, int, char*);
1114 Func func = ptr_as_func<Func>(_func);
1115
1116 char resultBuf[4];
1117 char expectBuf[4] = { 1, 0, 0, 1 };
1118
1119 func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0).
1120 func(0, 1, &resultBuf[1]); // We are expecting 0 (0 != 1).
1121 func(1, 0, &resultBuf[2]); // We are expecting 0 (1 != 0).
1122 func(1, 1, &resultBuf[3]); // We are expecting 1 (1 == 1).
1123
1124 result.assignFormat("out={%d, %d, %d, %d}", resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3]);
1125 expect.assignFormat("out={%d, %d, %d, %d}", expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3]);
1126
1127 return resultBuf[0] == expectBuf[0] &&
1128 resultBuf[1] == expectBuf[1] &&
1129 resultBuf[2] == expectBuf[2] &&
1130 resultBuf[3] == expectBuf[3] ;
1131 }
1132 };
1133
1134 // ============================================================================
1135 // [X86Test_AllocShlRor]
1136 // ============================================================================
1137
1138 class X86Test_AllocShlRor : public X86Test {
1139 public:
X86Test_AllocShlRor()1140 X86Test_AllocShlRor() : X86Test("AllocShlRor") {}
1141
add(X86TestApp & app)1142 static void add(X86TestApp& app) {
1143 app.add(new X86Test_AllocShlRor());
1144 }
1145
compile(x86::Compiler & cc)1146 virtual void compile(x86::Compiler& cc) {
1147 cc.addFunc(FuncSignatureT<void, int*, int, int, int>(CallConv::kIdHost));
1148
1149 x86::Gp dst = cc.newIntPtr("dst");
1150 x86::Gp var = cc.newInt32("var");
1151 x86::Gp vShlParam = cc.newInt32("vShlParam");
1152 x86::Gp vRorParam = cc.newInt32("vRorParam");
1153
1154 cc.setArg(0, dst);
1155 cc.setArg(1, var);
1156 cc.setArg(2, vShlParam);
1157 cc.setArg(3, vRorParam);
1158
1159 cc.shl(var, vShlParam);
1160 cc.ror(var, vRorParam);
1161
1162 cc.mov(x86::dword_ptr(dst), var);
1163 cc.endFunc();
1164 }
1165
run(void * _func,String & result,String & expect)1166 virtual bool run(void* _func, String& result, String& expect) {
1167 typedef void (*Func)(int*, int, int, int);
1168 Func func = ptr_as_func<Func>(_func);
1169
1170 int v0 = 0x000000FF;
1171
1172 int resultRet;
1173 int expectRet = 0x0000FF00;
1174
1175 func(&resultRet, v0, 16, 8);
1176
1177 result.assignFormat("ret=%d", resultRet);
1178 expect.assignFormat("ret=%d", expectRet);
1179
1180 return resultRet == expectRet;
1181 }
1182 };
1183
1184 // ============================================================================
1185 // [X86Test_AllocGpbLo]
1186 // ============================================================================
1187
1188 class X86Test_AllocGpbLo1 : public X86Test {
1189 public:
X86Test_AllocGpbLo1()1190 X86Test_AllocGpbLo1() : X86Test("AllocGpbLo1") {}
1191
1192 enum { kCount = 32 };
1193
add(X86TestApp & app)1194 static void add(X86TestApp& app) {
1195 app.add(new X86Test_AllocGpbLo1());
1196 }
1197
compile(x86::Compiler & cc)1198 virtual void compile(x86::Compiler& cc) {
1199 cc.addFunc(FuncSignatureT<uint32_t, uint32_t*>(CallConv::kIdHost));
1200
1201 x86::Gp rPtr = cc.newUIntPtr("rPtr");
1202 x86::Gp rSum = cc.newUInt32("rSum");
1203
1204 cc.setArg(0, rPtr);
1205
1206 x86::Gp x[kCount];
1207 uint32_t i;
1208
1209 for (i = 0; i < kCount; i++) {
1210 x[i] = cc.newUInt32("x%u", i);
1211 }
1212
1213 // Init pseudo-regs with values from our array.
1214 for (i = 0; i < kCount; i++) {
1215 cc.mov(x[i], x86::dword_ptr(rPtr, int(i * 4)));
1216 }
1217
1218 for (i = 2; i < kCount; i++) {
1219 // Add and truncate to 8 bit; no purpose, just mess with jit.
1220 cc.add (x[i ], x[i-1]);
1221 cc.movzx(x[i ], x[i ].r8());
1222 cc.movzx(x[i-2], x[i-1].r8());
1223 cc.movzx(x[i-1], x[i-2].r8());
1224 }
1225
1226 // Sum up all computed values.
1227 cc.mov(rSum, 0);
1228 for (i = 0; i < kCount; i++) {
1229 cc.add(rSum, x[i]);
1230 }
1231
1232 // Return the sum.
1233 cc.ret(rSum);
1234 cc.endFunc();
1235 }
1236
run(void * _func,String & result,String & expect)1237 virtual bool run(void* _func, String& result, String& expect) {
1238 typedef uint32_t (*Func)(uint32_t*);
1239 Func func = ptr_as_func<Func>(_func);
1240
1241 uint32_t i;
1242 uint32_t buf[kCount];
1243 uint32_t resultRet;
1244 uint32_t expectRet;
1245
1246 expectRet = 0;
1247 for (i = 0; i < kCount; i++) {
1248 buf[i] = 1;
1249 }
1250
1251 for (i = 2; i < kCount; i++) {
1252 buf[i ]+= buf[i-1];
1253 buf[i ] = buf[i ] & 0xFF;
1254 buf[i-2] = buf[i-1] & 0xFF;
1255 buf[i-1] = buf[i-2] & 0xFF;
1256 }
1257
1258 for (i = 0; i < kCount; i++) {
1259 expectRet += buf[i];
1260 }
1261
1262 for (i = 0; i < kCount; i++) {
1263 buf[i] = 1;
1264 }
1265 resultRet = func(buf);
1266
1267 result.assignFormat("ret=%d", resultRet);
1268 expect.assignFormat("ret=%d", expectRet);
1269
1270 return resultRet == expectRet;
1271 }
1272 };
1273
1274 // ============================================================================
1275 // [X86Test_AllocGpbLo2]
1276 // ============================================================================
1277
1278 class X86Test_AllocGpbLo2 : public X86Test {
1279 public:
X86Test_AllocGpbLo2()1280 X86Test_AllocGpbLo2() : X86Test("AllocGpbLo2") {}
1281
add(X86TestApp & app)1282 static void add(X86TestApp& app) {
1283 app.add(new X86Test_AllocGpbLo2());
1284 }
1285
compile(x86::Compiler & cc)1286 virtual void compile(x86::Compiler& cc) {
1287 cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConv::kIdHost));
1288
1289 x86::Gp v = cc.newUInt32("v");
1290 cc.setArg(0, v);
1291 cc.mov(v.r8(), 0xFF);
1292 cc.ret(v);
1293 cc.endFunc();
1294 }
1295
run(void * _func,String & result,String & expect)1296 virtual bool run(void* _func, String& result, String& expect) {
1297 typedef uint32_t (*Func)(uint32_t);
1298 Func func = ptr_as_func<Func>(_func);
1299
1300 uint32_t resultRet = func(0x12345678u);
1301 uint32_t expectRet = 0x123456FFu;
1302
1303 result.assignFormat("ret=%d", resultRet);
1304 expect.assignFormat("ret=%d", expectRet);
1305
1306 return resultRet == expectRet;
1307 }
1308 };
1309
1310 // ============================================================================
1311 // [X86Test_AllocRepMovsb]
1312 // ============================================================================
1313
1314 class X86Test_AllocRepMovsb : public X86Test {
1315 public:
X86Test_AllocRepMovsb()1316 X86Test_AllocRepMovsb() : X86Test("AllocRepMovsb") {}
1317
add(X86TestApp & app)1318 static void add(X86TestApp& app) {
1319 app.add(new X86Test_AllocRepMovsb());
1320 }
1321
compile(x86::Compiler & cc)1322 virtual void compile(x86::Compiler& cc) {
1323 cc.addFunc(FuncSignatureT<void, void*, void*, size_t>(CallConv::kIdHost));
1324
1325 x86::Gp dst = cc.newIntPtr("dst");
1326 x86::Gp src = cc.newIntPtr("src");
1327 x86::Gp cnt = cc.newIntPtr("cnt");
1328
1329 cc.setArg(0, dst);
1330 cc.setArg(1, src);
1331 cc.setArg(2, cnt);
1332
1333 cc.rep(cnt).movs(x86::byte_ptr(dst), x86::byte_ptr(src));
1334 cc.endFunc();
1335 }
1336
run(void * _func,String & result,String & expect)1337 virtual bool run(void* _func, String& result, String& expect) {
1338 typedef void (*Func)(void*, void*, size_t);
1339 Func func = ptr_as_func<Func>(_func);
1340
1341 char dst[20] = { 0 };
1342 char src[20] = "Hello AsmJit!";
1343 func(dst, src, strlen(src) + 1);
1344
1345 result.assignFormat("ret=\"%s\"", dst);
1346 expect.assignFormat("ret=\"%s\"", src);
1347
1348 return result == expect;
1349 }
1350 };
1351
1352 // ============================================================================
1353 // [X86Test_AllocIfElse1]
1354 // ============================================================================
1355
1356 class X86Test_AllocIfElse1 : public X86Test {
1357 public:
X86Test_AllocIfElse1()1358 X86Test_AllocIfElse1() : X86Test("AllocIfElse1") {}
1359
add(X86TestApp & app)1360 static void add(X86TestApp& app) {
1361 app.add(new X86Test_AllocIfElse1());
1362 }
1363
compile(x86::Compiler & cc)1364 virtual void compile(x86::Compiler& cc) {
1365 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
1366
1367 x86::Gp v1 = cc.newInt32("v1");
1368 x86::Gp v2 = cc.newInt32("v2");
1369
1370 Label L_1 = cc.newLabel();
1371 Label L_2 = cc.newLabel();
1372
1373 cc.setArg(0, v1);
1374 cc.setArg(1, v2);
1375
1376 cc.cmp(v1, v2);
1377 cc.jg(L_1);
1378
1379 cc.mov(v1, 1);
1380 cc.jmp(L_2);
1381
1382 cc.bind(L_1);
1383 cc.mov(v1, 2);
1384
1385 cc.bind(L_2);
1386 cc.ret(v1);
1387 cc.endFunc();
1388 }
1389
run(void * _func,String & result,String & expect)1390 virtual bool run(void* _func, String& result, String& expect) {
1391 typedef int (*Func)(int, int);
1392 Func func = ptr_as_func<Func>(_func);
1393
1394 int a = func(0, 1);
1395 int b = func(1, 0);
1396
1397 result.appendFormat("ret={%d, %d}", a, b);
1398 expect.appendFormat("ret={%d, %d}", 1, 2);
1399
1400 return result == expect;
1401 }
1402 };
1403
1404 // ============================================================================
1405 // [X86Test_AllocIfElse2]
1406 // ============================================================================
1407
1408 class X86Test_AllocIfElse2 : public X86Test {
1409 public:
X86Test_AllocIfElse2()1410 X86Test_AllocIfElse2() : X86Test("AllocIfElse2") {}
1411
add(X86TestApp & app)1412 static void add(X86TestApp& app) {
1413 app.add(new X86Test_AllocIfElse2());
1414 }
1415
compile(x86::Compiler & cc)1416 virtual void compile(x86::Compiler& cc) {
1417 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
1418
1419 x86::Gp v1 = cc.newInt32("v1");
1420 x86::Gp v2 = cc.newInt32("v2");
1421
1422 Label L_1 = cc.newLabel();
1423 Label L_2 = cc.newLabel();
1424 Label L_3 = cc.newLabel();
1425 Label L_4 = cc.newLabel();
1426
1427 cc.setArg(0, v1);
1428 cc.setArg(1, v2);
1429
1430 cc.jmp(L_1);
1431 cc.bind(L_2);
1432 cc.jmp(L_4);
1433 cc.bind(L_1);
1434
1435 cc.cmp(v1, v2);
1436 cc.jg(L_3);
1437
1438 cc.mov(v1, 1);
1439 cc.jmp(L_2);
1440
1441 cc.bind(L_3);
1442 cc.mov(v1, 2);
1443 cc.jmp(L_2);
1444
1445 cc.bind(L_4);
1446
1447 cc.ret(v1);
1448 cc.endFunc();
1449 }
1450
run(void * _func,String & result,String & expect)1451 virtual bool run(void* _func, String& result, String& expect) {
1452 typedef int (*Func)(int, int);
1453 Func func = ptr_as_func<Func>(_func);
1454
1455 int a = func(0, 1);
1456 int b = func(1, 0);
1457
1458 result.appendFormat("ret={%d, %d}", a, b);
1459 expect.appendFormat("ret={%d, %d}", 1, 2);
1460
1461 return result == expect;
1462 }
1463 };
1464
1465 // ============================================================================
1466 // [X86Test_AllocIfElse3]
1467 // ============================================================================
1468
1469 class X86Test_AllocIfElse3 : public X86Test {
1470 public:
X86Test_AllocIfElse3()1471 X86Test_AllocIfElse3() : X86Test("AllocIfElse3") {}
1472
add(X86TestApp & app)1473 static void add(X86TestApp& app) {
1474 app.add(new X86Test_AllocIfElse3());
1475 }
1476
compile(x86::Compiler & cc)1477 virtual void compile(x86::Compiler& cc) {
1478 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
1479
1480 x86::Gp v1 = cc.newInt32("v1");
1481 x86::Gp v2 = cc.newInt32("v2");
1482 x86::Gp counter = cc.newInt32("counter");
1483
1484 Label L_1 = cc.newLabel();
1485 Label L_Loop = cc.newLabel();
1486 Label L_Exit = cc.newLabel();
1487
1488 cc.setArg(0, v1);
1489 cc.setArg(1, v2);
1490
1491 cc.cmp(v1, v2);
1492 cc.jg(L_1);
1493
1494 cc.mov(counter, 0);
1495
1496 cc.bind(L_Loop);
1497 cc.mov(v1, counter);
1498
1499 cc.inc(counter);
1500 cc.cmp(counter, 1);
1501 cc.jle(L_Loop);
1502 cc.jmp(L_Exit);
1503
1504 cc.bind(L_1);
1505 cc.mov(v1, 2);
1506
1507 cc.bind(L_Exit);
1508 cc.ret(v1);
1509 cc.endFunc();
1510 }
1511
run(void * _func,String & result,String & expect)1512 virtual bool run(void* _func, String& result, String& expect) {
1513 typedef int (*Func)(int, int);
1514 Func func = ptr_as_func<Func>(_func);
1515
1516 int a = func(0, 1);
1517 int b = func(1, 0);
1518
1519 result.appendFormat("ret={%d, %d}", a, b);
1520 expect.appendFormat("ret={%d, %d}", 1, 2);
1521
1522 return result == expect;
1523 }
1524 };
1525
1526 // ============================================================================
1527 // [X86Test_AllocIfElse4]
1528 // ============================================================================
1529
1530 class X86Test_AllocIfElse4 : public X86Test {
1531 public:
X86Test_AllocIfElse4()1532 X86Test_AllocIfElse4() : X86Test("AllocIfElse4") {}
1533
add(X86TestApp & app)1534 static void add(X86TestApp& app) {
1535 app.add(new X86Test_AllocIfElse4());
1536 }
1537
compile(x86::Compiler & cc)1538 virtual void compile(x86::Compiler& cc) {
1539 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
1540
1541 x86::Gp v1 = cc.newInt32("v1");
1542 x86::Gp v2 = cc.newInt32("v2");
1543 x86::Gp counter = cc.newInt32("counter");
1544
1545 Label L_1 = cc.newLabel();
1546 Label L_Loop1 = cc.newLabel();
1547 Label L_Loop2 = cc.newLabel();
1548 Label L_Exit = cc.newLabel();
1549
1550 cc.mov(counter, 0);
1551
1552 cc.setArg(0, v1);
1553 cc.setArg(1, v2);
1554
1555 cc.cmp(v1, v2);
1556 cc.jg(L_1);
1557
1558 cc.bind(L_Loop1);
1559 cc.mov(v1, counter);
1560
1561 cc.inc(counter);
1562 cc.cmp(counter, 1);
1563 cc.jle(L_Loop1);
1564 cc.jmp(L_Exit);
1565
1566 cc.bind(L_1);
1567 cc.bind(L_Loop2);
1568 cc.mov(v1, counter);
1569 cc.inc(counter);
1570 cc.cmp(counter, 2);
1571 cc.jle(L_Loop2);
1572
1573 cc.bind(L_Exit);
1574 cc.ret(v1);
1575 cc.endFunc();
1576 }
1577
run(void * _func,String & result,String & expect)1578 virtual bool run(void* _func, String& result, String& expect) {
1579 typedef int (*Func)(int, int);
1580 Func func = ptr_as_func<Func>(_func);
1581
1582 int a = func(0, 1);
1583 int b = func(1, 0);
1584
1585 result.appendFormat("ret={%d, %d}", a, b);
1586 expect.appendFormat("ret={%d, %d}", 1, 2);
1587
1588 return result == expect;
1589 }
1590 };
1591
1592 // ============================================================================
1593 // [X86Test_AllocInt8]
1594 // ============================================================================
1595
1596 class X86Test_AllocInt8 : public X86Test {
1597 public:
X86Test_AllocInt8()1598 X86Test_AllocInt8() : X86Test("AllocInt8") {}
1599
add(X86TestApp & app)1600 static void add(X86TestApp& app) {
1601 app.add(new X86Test_AllocInt8());
1602 }
1603
compile(x86::Compiler & cc)1604 virtual void compile(x86::Compiler& cc) {
1605 x86::Gp x = cc.newInt8("x");
1606 x86::Gp y = cc.newInt32("y");
1607
1608 cc.addFunc(FuncSignatureT<int, char>(CallConv::kIdHost));
1609 cc.setArg(0, x);
1610
1611 cc.movsx(y, x);
1612
1613 cc.ret(y);
1614 cc.endFunc();
1615 }
1616
run(void * _func,String & result,String & expect)1617 virtual bool run(void* _func, String& result, String& expect) {
1618 typedef int (*Func)(char);
1619 Func func = ptr_as_func<Func>(_func);
1620
1621 int resultRet = func(-13);
1622 int expectRet = -13;
1623
1624 result.assignFormat("ret=%d", resultRet);
1625 expect.assignFormat("ret=%d", expectRet);
1626
1627 return result == expect;
1628 }
1629 };
1630
1631 // ============================================================================
1632 // [X86Test_AllocUnhandledArg]
1633 // ============================================================================
1634
1635 class X86Test_AllocUnhandledArg : public X86Test {
1636 public:
X86Test_AllocUnhandledArg()1637 X86Test_AllocUnhandledArg() : X86Test("AllocUnhandledArg") {}
1638
add(X86TestApp & app)1639 static void add(X86TestApp& app) {
1640 app.add(new X86Test_AllocUnhandledArg());
1641 }
1642
compile(x86::Compiler & cc)1643 virtual void compile(x86::Compiler& cc) {
1644 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
1645
1646 x86::Gp x = cc.newInt32("x");
1647 cc.setArg(2, x);
1648 cc.ret(x);
1649
1650 cc.endFunc();
1651 }
1652
run(void * _func,String & result,String & expect)1653 virtual bool run(void* _func, String& result, String& expect) {
1654 typedef int (*Func)(int, int, int);
1655 Func func = ptr_as_func<Func>(_func);
1656
1657 int resultRet = func(42, 155, 199);
1658 int expectRet = 199;
1659
1660 result.assignFormat("ret={%d}", resultRet);
1661 expect.assignFormat("ret={%d}", expectRet);
1662
1663 return result == expect;
1664 }
1665 };
1666
1667 // ============================================================================
1668 // [X86Test_AllocArgsIntPtr]
1669 // ============================================================================
1670
1671 class X86Test_AllocArgsIntPtr : public X86Test {
1672 public:
X86Test_AllocArgsIntPtr()1673 X86Test_AllocArgsIntPtr() : X86Test("AllocArgsIntPtr") {}
1674
add(X86TestApp & app)1675 static void add(X86TestApp& app) {
1676 app.add(new X86Test_AllocArgsIntPtr());
1677 }
1678
compile(x86::Compiler & cc)1679 virtual void compile(x86::Compiler& cc) {
1680 cc.addFunc(FuncSignatureT<void, void*, void*, void*, void*, void*, void*, void*, void*>(CallConv::kIdHost));
1681
1682 uint32_t i;
1683 x86::Gp var[8];
1684
1685 for (i = 0; i < 8; i++) {
1686 var[i] = cc.newIntPtr("var%u", i);
1687 cc.setArg(i, var[i]);
1688 }
1689
1690 for (i = 0; i < 8; i++) {
1691 cc.add(var[i], int(i + 1));
1692 }
1693
1694 // Move some data into buffer provided by arguments so we can verify if it
1695 // really works without looking into assembler output.
1696 for (i = 0; i < 8; i++) {
1697 cc.add(x86::byte_ptr(var[i]), int(i + 1));
1698 }
1699
1700 cc.endFunc();
1701 }
1702
run(void * _func,String & result,String & expect)1703 virtual bool run(void* _func, String& result, String& expect) {
1704 typedef void (*Func)(void*, void*, void*, void*, void*, void*, void*, void*);
1705 Func func = ptr_as_func<Func>(_func);
1706
1707 uint8_t resultBuf[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1708 uint8_t expectBuf[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
1709
1710 func(resultBuf, resultBuf, resultBuf, resultBuf,
1711 resultBuf, resultBuf, resultBuf, resultBuf);
1712
1713 result.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
1714 resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3],
1715 resultBuf[4], resultBuf[5], resultBuf[6], resultBuf[7],
1716 resultBuf[8]);
1717 expect.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
1718 expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3],
1719 expectBuf[4], expectBuf[5], expectBuf[6], expectBuf[7],
1720 expectBuf[8]);
1721
1722 return result == expect;
1723 }
1724 };
1725
1726 // ============================================================================
1727 // [X86Test_AllocArgsFloat]
1728 // ============================================================================
1729
1730 class X86Test_AllocArgsFloat : public X86Test {
1731 public:
X86Test_AllocArgsFloat()1732 X86Test_AllocArgsFloat() : X86Test("AllocArgsFloat") {}
1733
add(X86TestApp & app)1734 static void add(X86TestApp& app) {
1735 app.add(new X86Test_AllocArgsFloat());
1736 }
1737
compile(x86::Compiler & cc)1738 virtual void compile(x86::Compiler& cc) {
1739 cc.addFunc(FuncSignatureT<void, float, float, float, float, float, float, float, void*>(CallConv::kIdHost));
1740
1741 uint32_t i;
1742
1743 x86::Gp p = cc.newIntPtr("p");
1744 x86::Xmm xv[7];
1745
1746 for (i = 0; i < 7; i++) {
1747 xv[i] = cc.newXmmSs("xv%u", i);
1748 cc.setArg(i, xv[i]);
1749 }
1750
1751 cc.setArg(7, p);
1752
1753 cc.addss(xv[0], xv[1]);
1754 cc.addss(xv[0], xv[2]);
1755 cc.addss(xv[0], xv[3]);
1756 cc.addss(xv[0], xv[4]);
1757 cc.addss(xv[0], xv[5]);
1758 cc.addss(xv[0], xv[6]);
1759
1760 cc.movss(x86::ptr(p), xv[0]);
1761 cc.endFunc();
1762 }
1763
run(void * _func,String & result,String & expect)1764 virtual bool run(void* _func, String& result, String& expect) {
1765 typedef void (*Func)(float, float, float, float, float, float, float, float*);
1766 Func func = ptr_as_func<Func>(_func);
1767
1768 float resultRet;
1769 float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f;
1770
1771 func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &resultRet);
1772
1773 result.assignFormat("ret={%g}", resultRet);
1774 expect.assignFormat("ret={%g}", expectRet);
1775
1776 return resultRet == expectRet;
1777 }
1778 };
1779
1780 // ============================================================================
1781 // [X86Test_AllocArgsDouble]
1782 // ============================================================================
1783
1784 class X86Test_AllocArgsDouble : public X86Test {
1785 public:
X86Test_AllocArgsDouble()1786 X86Test_AllocArgsDouble() : X86Test("AllocArgsDouble") {}
1787
add(X86TestApp & app)1788 static void add(X86TestApp& app) {
1789 app.add(new X86Test_AllocArgsDouble());
1790 }
1791
compile(x86::Compiler & cc)1792 virtual void compile(x86::Compiler& cc) {
1793 cc.addFunc(FuncSignatureT<void, double, double, double, double, double, double, double, void*>(CallConv::kIdHost));
1794
1795 uint32_t i;
1796
1797 x86::Gp p = cc.newIntPtr("p");
1798 x86::Xmm xv[7];
1799
1800 for (i = 0; i < 7; i++) {
1801 xv[i] = cc.newXmmSd("xv%u", i);
1802 cc.setArg(i, xv[i]);
1803 }
1804
1805 cc.setArg(7, p);
1806
1807 cc.addsd(xv[0], xv[1]);
1808 cc.addsd(xv[0], xv[2]);
1809 cc.addsd(xv[0], xv[3]);
1810 cc.addsd(xv[0], xv[4]);
1811 cc.addsd(xv[0], xv[5]);
1812 cc.addsd(xv[0], xv[6]);
1813
1814 cc.movsd(x86::ptr(p), xv[0]);
1815 cc.endFunc();
1816 }
1817
run(void * _func,String & result,String & expect)1818 virtual bool run(void* _func, String& result, String& expect) {
1819 typedef void (*Func)(double, double, double, double, double, double, double, double*);
1820 Func func = ptr_as_func<Func>(_func);
1821
1822 double resultRet;
1823 double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0;
1824
1825 func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &resultRet);
1826
1827 result.assignFormat("ret={%g}", resultRet);
1828 expect.assignFormat("ret={%g}", expectRet);
1829
1830 return resultRet == expectRet;
1831 }
1832 };
1833
1834 // ============================================================================
1835 // [X86Test_AllocRetFloat1]
1836 // ============================================================================
1837
1838 class X86Test_AllocRetFloat1 : public X86Test {
1839 public:
X86Test_AllocRetFloat1()1840 X86Test_AllocRetFloat1() : X86Test("AllocRetFloat1") {}
1841
add(X86TestApp & app)1842 static void add(X86TestApp& app) {
1843 app.add(new X86Test_AllocRetFloat1());
1844 }
1845
compile(x86::Compiler & cc)1846 virtual void compile(x86::Compiler& cc) {
1847 cc.addFunc(FuncSignatureT<float, float>(CallConv::kIdHost));
1848
1849 x86::Xmm x = cc.newXmmSs("x");
1850 cc.setArg(0, x);
1851 cc.ret(x);
1852
1853 cc.endFunc();
1854 }
1855
run(void * _func,String & result,String & expect)1856 virtual bool run(void* _func, String& result, String& expect) {
1857 typedef float (*Func)(float);
1858 Func func = ptr_as_func<Func>(_func);
1859
1860 float resultRet = func(42.0f);
1861 float expectRet = 42.0f;
1862
1863 result.assignFormat("ret={%g}", resultRet);
1864 expect.assignFormat("ret={%g}", expectRet);
1865
1866 return resultRet == expectRet;
1867 }
1868 };
1869
1870 // ============================================================================
1871 // [X86Test_AllocRetFloat2]
1872 // ============================================================================
1873
1874 class X86Test_AllocRetFloat2 : public X86Test {
1875 public:
X86Test_AllocRetFloat2()1876 X86Test_AllocRetFloat2() : X86Test("AllocRetFloat2") {}
1877
add(X86TestApp & app)1878 static void add(X86TestApp& app) {
1879 app.add(new X86Test_AllocRetFloat2());
1880 }
1881
compile(x86::Compiler & cc)1882 virtual void compile(x86::Compiler& cc) {
1883 cc.addFunc(FuncSignatureT<float, float, float>(CallConv::kIdHost));
1884
1885 x86::Xmm x = cc.newXmmSs("x");
1886 x86::Xmm y = cc.newXmmSs("y");
1887
1888 cc.setArg(0, x);
1889 cc.setArg(1, y);
1890
1891 cc.addss(x, y);
1892 cc.ret(x);
1893
1894 cc.endFunc();
1895 }
1896
run(void * _func,String & result,String & expect)1897 virtual bool run(void* _func, String& result, String& expect) {
1898 typedef float (*Func)(float, float);
1899 Func func = ptr_as_func<Func>(_func);
1900
1901 float resultRet = func(1.0f, 2.0f);
1902 float expectRet = 1.0f + 2.0f;
1903
1904 result.assignFormat("ret={%g}", resultRet);
1905 expect.assignFormat("ret={%g}", expectRet);
1906
1907 return resultRet == expectRet;
1908 }
1909 };
1910
1911 // ============================================================================
1912 // [X86Test_AllocRetDouble1]
1913 // ============================================================================
1914
1915 class X86Test_AllocRetDouble1 : public X86Test {
1916 public:
X86Test_AllocRetDouble1()1917 X86Test_AllocRetDouble1() : X86Test("AllocRetDouble1") {}
1918
add(X86TestApp & app)1919 static void add(X86TestApp& app) {
1920 app.add(new X86Test_AllocRetDouble1());
1921 }
1922
compile(x86::Compiler & cc)1923 virtual void compile(x86::Compiler& cc) {
1924 cc.addFunc(FuncSignatureT<double, double>(CallConv::kIdHost));
1925
1926 x86::Xmm x = cc.newXmmSd("x");
1927 cc.setArg(0, x);
1928 cc.ret(x);
1929
1930 cc.endFunc();
1931 }
1932
run(void * _func,String & result,String & expect)1933 virtual bool run(void* _func, String& result, String& expect) {
1934 typedef double (*Func)(double);
1935 Func func = ptr_as_func<Func>(_func);
1936
1937 double resultRet = func(42.0);
1938 double expectRet = 42.0;
1939
1940 result.assignFormat("ret={%g}", resultRet);
1941 expect.assignFormat("ret={%g}", expectRet);
1942
1943 return resultRet == expectRet;
1944 }
1945 };
1946 // ============================================================================
1947 // [X86Test_AllocRetDouble2]
1948 // ============================================================================
1949
1950 class X86Test_AllocRetDouble2 : public X86Test {
1951 public:
X86Test_AllocRetDouble2()1952 X86Test_AllocRetDouble2() : X86Test("AllocRetDouble2") {}
1953
add(X86TestApp & app)1954 static void add(X86TestApp& app) {
1955 app.add(new X86Test_AllocRetDouble2());
1956 }
1957
compile(x86::Compiler & cc)1958 virtual void compile(x86::Compiler& cc) {
1959 cc.addFunc(FuncSignatureT<double, double, double>(CallConv::kIdHost));
1960
1961 x86::Xmm x = cc.newXmmSd("x");
1962 x86::Xmm y = cc.newXmmSd("y");
1963
1964 cc.setArg(0, x);
1965 cc.setArg(1, y);
1966
1967 cc.addsd(x, y);
1968 cc.ret(x);
1969
1970 cc.endFunc();
1971 }
1972
run(void * _func,String & result,String & expect)1973 virtual bool run(void* _func, String& result, String& expect) {
1974 typedef double (*Func)(double, double);
1975 Func func = ptr_as_func<Func>(_func);
1976
1977 double resultRet = func(1.0, 2.0);
1978 double expectRet = 1.0 + 2.0;
1979
1980 result.assignFormat("ret={%g}", resultRet);
1981 expect.assignFormat("ret={%g}", expectRet);
1982
1983 return resultRet == expectRet;
1984 }
1985 };
1986
1987 // ============================================================================
1988 // [X86Test_AllocStack]
1989 // ============================================================================
1990
1991 class X86Test_AllocStack : public X86Test {
1992 public:
X86Test_AllocStack()1993 X86Test_AllocStack() : X86Test("AllocStack") {}
1994
1995 enum { kSize = 256 };
1996
add(X86TestApp & app)1997 static void add(X86TestApp& app) {
1998 app.add(new X86Test_AllocStack());
1999 }
2000
compile(x86::Compiler & cc)2001 virtual void compile(x86::Compiler& cc) {
2002 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2003
2004 x86::Mem stack = cc.newStack(kSize, 1);
2005 stack.setSize(1);
2006
2007 x86::Gp i = cc.newIntPtr("i");
2008 x86::Gp a = cc.newInt32("a");
2009 x86::Gp b = cc.newInt32("b");
2010
2011 Label L_1 = cc.newLabel();
2012 Label L_2 = cc.newLabel();
2013
2014 // Fill stack by sequence [0, 1, 2, 3 ... 255].
2015 cc.xor_(i, i);
2016
2017 x86::Mem stackWithIndex = stack.clone();
2018 stackWithIndex.setIndex(i, 0);
2019
2020 cc.bind(L_1);
2021 cc.mov(stackWithIndex, i.r8());
2022 cc.inc(i);
2023 cc.cmp(i, 255);
2024 cc.jle(L_1);
2025
2026 // Sum sequence in stack.
2027 cc.xor_(i, i);
2028 cc.xor_(a, a);
2029
2030 cc.bind(L_2);
2031 cc.movzx(b, stackWithIndex);
2032 cc.add(a, b);
2033 cc.inc(i);
2034 cc.cmp(i, 255);
2035 cc.jle(L_2);
2036
2037 cc.ret(a);
2038 cc.endFunc();
2039 }
2040
run(void * _func,String & result,String & expect)2041 virtual bool run(void* _func, String& result, String& expect) {
2042 typedef int (*Func)(void);
2043 Func func = ptr_as_func<Func>(_func);
2044
2045 int resultRet = func();
2046 int expectRet = 32640;
2047
2048 result.assignInt(resultRet);
2049 expect.assignInt(expectRet);
2050
2051 return resultRet == expectRet;
2052 }
2053 };
2054
2055 // ============================================================================
2056 // [X86Test_AllocMemcpy]
2057 // ============================================================================
2058
2059 class X86Test_AllocMemcpy : public X86Test {
2060 public:
X86Test_AllocMemcpy()2061 X86Test_AllocMemcpy() : X86Test("AllocMemcpy") {}
2062
2063 enum { kCount = 32 };
2064
add(X86TestApp & app)2065 static void add(X86TestApp& app) {
2066 app.add(new X86Test_AllocMemcpy());
2067 }
2068
compile(x86::Compiler & cc)2069 virtual void compile(x86::Compiler& cc) {
2070 x86::Gp dst = cc.newIntPtr("dst");
2071 x86::Gp src = cc.newIntPtr("src");
2072 x86::Gp cnt = cc.newUIntPtr("cnt");
2073
2074 Label L_Loop = cc.newLabel(); // Create base labels we use
2075 Label L_Exit = cc.newLabel(); // in our function.
2076
2077 cc.addFunc(FuncSignatureT<void, uint32_t*, const uint32_t*, size_t>(CallConv::kIdHost));
2078 cc.setArg(0, dst);
2079 cc.setArg(1, src);
2080 cc.setArg(2, cnt);
2081
2082 cc.test(cnt, cnt); // Exit if the size is zero.
2083 cc.jz(L_Exit);
2084
2085 cc.bind(L_Loop); // Bind the loop label here.
2086
2087 x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes).
2088 cc.mov(tmp, x86::dword_ptr(src));
2089 cc.mov(x86::dword_ptr(dst), tmp);
2090
2091 cc.add(src, 4); // Increment dst/src pointers.
2092 cc.add(dst, 4);
2093
2094 cc.dec(cnt); // Loop until cnt isn't zero.
2095 cc.jnz(L_Loop);
2096
2097 cc.bind(L_Exit); // Bind the exit label here.
2098 cc.endFunc(); // End of function.
2099 }
2100
run(void * _func,String & result,String & expect)2101 virtual bool run(void* _func, String& result, String& expect) {
2102 typedef void (*Func)(uint32_t*, const uint32_t*, size_t);
2103 Func func = ptr_as_func<Func>(_func);
2104
2105 uint32_t i;
2106
2107 uint32_t dstBuffer[kCount];
2108 uint32_t srcBuffer[kCount];
2109
2110 for (i = 0; i < kCount; i++) {
2111 dstBuffer[i] = 0;
2112 srcBuffer[i] = i;
2113 }
2114
2115 func(dstBuffer, srcBuffer, kCount);
2116
2117 result.assignString("buf={");
2118 expect.assignString("buf={");
2119
2120 for (i = 0; i < kCount; i++) {
2121 if (i != 0) {
2122 result.appendString(", ");
2123 expect.appendString(", ");
2124 }
2125
2126 result.appendFormat("%u", unsigned(dstBuffer[i]));
2127 expect.appendFormat("%u", unsigned(srcBuffer[i]));
2128 }
2129
2130 result.appendString("}");
2131 expect.appendString("}");
2132
2133 return result == expect;
2134 }
2135 };
2136
2137 // ============================================================================
2138 // [X86Test_AllocExtraBlock]
2139 // ============================================================================
2140
2141 class X86Test_AllocExtraBlock : public X86Test {
2142 public:
X86Test_AllocExtraBlock()2143 X86Test_AllocExtraBlock() : X86Test("AllocExtraBlock") {}
2144
add(X86TestApp & app)2145 static void add(X86TestApp& app) {
2146 app.add(new X86Test_AllocExtraBlock());
2147 }
2148
compile(x86::Compiler & cc)2149 virtual void compile(x86::Compiler& cc) {
2150 x86::Gp cond = cc.newInt32("cond");
2151 x86::Gp ret = cc.newInt32("ret");
2152 x86::Gp a = cc.newInt32("a");
2153 x86::Gp b = cc.newInt32("b");
2154
2155 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
2156 cc.setArg(0, cond);
2157 cc.setArg(1, a);
2158 cc.setArg(2, b);
2159
2160 Label L_Ret = cc.newLabel();
2161 Label L_Extra = cc.newLabel();
2162
2163 cc.test(cond, cond);
2164 cc.jnz(L_Extra);
2165
2166 cc.mov(ret, a);
2167 cc.add(ret, b);
2168
2169 cc.bind(L_Ret);
2170 cc.ret(ret);
2171
2172 // Emit code sequence at the end of the function.
2173 BaseNode* prevCursor = cc.setCursor(cc.func()->endNode()->prev());
2174 cc.bind(L_Extra);
2175 cc.mov(ret, a);
2176 cc.sub(ret, b);
2177 cc.jmp(L_Ret);
2178 cc.setCursor(prevCursor);
2179
2180 cc.endFunc();
2181 }
2182
run(void * _func,String & result,String & expect)2183 virtual bool run(void* _func, String& result, String& expect) {
2184 typedef int (*Func)(int, int, int);
2185 Func func = ptr_as_func<Func>(_func);
2186
2187 int ret1 = func(0, 4, 5);
2188 int ret2 = func(1, 4, 5);
2189
2190 int exp1 = 4 + 5;
2191 int exp2 = 4 - 5;
2192
2193 result.assignFormat("ret={%d, %d}", ret1, ret2);
2194 expect.assignFormat("ret={%d, %d}", exp1, exp2);
2195
2196 return result == expect;
2197 }
2198 };
2199
2200 // ============================================================================
2201 // [X86Test_AllocAlphaBlend]
2202 // ============================================================================
2203
2204 class X86Test_AllocAlphaBlend : public X86Test {
2205 public:
X86Test_AllocAlphaBlend()2206 X86Test_AllocAlphaBlend() : X86Test("AllocAlphaBlend") {}
2207
2208 enum { kCount = 17 };
2209
add(X86TestApp & app)2210 static void add(X86TestApp& app) {
2211 app.add(new X86Test_AllocAlphaBlend());
2212 }
2213
blendSrcOver(uint32_t d,uint32_t s)2214 static uint32_t blendSrcOver(uint32_t d, uint32_t s) {
2215 uint32_t saInv = ~s >> 24;
2216
2217 uint32_t d_20 = (d ) & 0x00FF00FF;
2218 uint32_t d_31 = (d >> 8) & 0x00FF00FF;
2219
2220 d_20 *= saInv;
2221 d_31 *= saInv;
2222
2223 d_20 = ((d_20 + ((d_20 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u) >> 8;
2224 d_31 = ((d_31 + ((d_31 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u);
2225
2226 return d_20 + d_31 + s;
2227 }
2228
compile(x86::Compiler & cc)2229 virtual void compile(x86::Compiler& cc) {
2230 asmtest::generateAlphaBlend(cc);
2231 }
2232
run(void * _func,String & result,String & expect)2233 virtual bool run(void* _func, String& result, String& expect) {
2234 typedef void (*Func)(void*, const void*, size_t);
2235 Func func = ptr_as_func<Func>(_func);
2236
2237 static const uint32_t dstConstData[] = { 0x00000000, 0x10101010, 0x20100804, 0x30200003, 0x40204040, 0x5000004D, 0x60302E2C, 0x706F6E6D, 0x807F4F2F, 0x90349001, 0xA0010203, 0xB03204AB, 0xC023AFBD, 0xD0D0D0C0, 0xE0AABBCC, 0xFFFFFFFF, 0xF8F4F2F1 };
2238 static const uint32_t srcConstData[] = { 0xE0E0E0E0, 0xA0008080, 0x341F1E1A, 0xFEFEFEFE, 0x80302010, 0x49490A0B, 0x998F7798, 0x00000000, 0x01010101, 0xA0264733, 0xBAB0B1B9, 0xFF000000, 0xDAB0A0C1, 0xE0BACFDA, 0x99887766, 0xFFFFFF80, 0xEE0A5FEC };
2239
2240 uint32_t _dstBuffer[kCount + 3];
2241 uint32_t _srcBuffer[kCount + 3];
2242
2243 // Has to be aligned.
2244 uint32_t* dstBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_dstBuffer, 16);
2245 uint32_t* srcBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_srcBuffer, 16);
2246
2247 memcpy(dstBuffer, dstConstData, sizeof(dstConstData));
2248 memcpy(srcBuffer, srcConstData, sizeof(srcConstData));
2249
2250 uint32_t i;
2251 uint32_t expBuffer[kCount];
2252
2253 for (i = 0; i < kCount; i++) {
2254 expBuffer[i] = blendSrcOver(dstBuffer[i], srcBuffer[i]);
2255 }
2256
2257 func(dstBuffer, srcBuffer, kCount);
2258
2259 result.assignString("buf={");
2260 expect.assignString("buf={");
2261
2262 for (i = 0; i < kCount; i++) {
2263 if (i != 0) {
2264 result.appendString(", ");
2265 expect.appendString(", ");
2266 }
2267
2268 result.appendFormat("%08X", unsigned(dstBuffer[i]));
2269 expect.appendFormat("%08X", unsigned(expBuffer[i]));
2270 }
2271
2272 result.appendString("}");
2273 expect.appendString("}");
2274
2275 return result == expect;
2276 }
2277 };
2278
2279 // ============================================================================
2280 // [X86Test_FuncCallBase1]
2281 // ============================================================================
2282
2283 class X86Test_FuncCallBase1 : public X86Test {
2284 public:
X86Test_FuncCallBase1()2285 X86Test_FuncCallBase1() : X86Test("FuncCallBase1") {}
2286
add(X86TestApp & app)2287 static void add(X86TestApp& app) {
2288 app.add(new X86Test_FuncCallBase1());
2289 }
2290
compile(x86::Compiler & cc)2291 virtual void compile(x86::Compiler& cc) {
2292 x86::Gp v0 = cc.newInt32("v0");
2293 x86::Gp v1 = cc.newInt32("v1");
2294 x86::Gp v2 = cc.newInt32("v2");
2295
2296 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
2297 cc.setArg(0, v0);
2298 cc.setArg(1, v1);
2299 cc.setArg(2, v2);
2300
2301 // Just do something.
2302 cc.shl(v0, 1);
2303 cc.shl(v1, 1);
2304 cc.shl(v2, 1);
2305
2306 // Call a function.
2307 FuncCallNode* call = cc.call(imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
2308 call->setArg(0, v2);
2309 call->setArg(1, v1);
2310 call->setArg(2, v0);
2311 call->setRet(0, v0);
2312
2313 cc.ret(v0);
2314 cc.endFunc();
2315 }
2316
run(void * _func,String & result,String & expect)2317 virtual bool run(void* _func, String& result, String& expect) {
2318 typedef int (*Func)(int, int, int);
2319 Func func = ptr_as_func<Func>(_func);
2320
2321 int resultRet = func(3, 2, 1);
2322 int expectRet = 36;
2323
2324 result.assignFormat("ret=%d", resultRet);
2325 expect.assignFormat("ret=%d", expectRet);
2326
2327 return resultRet == expectRet;
2328 }
2329
calledFunc(int a,int b,int c)2330 static int calledFunc(int a, int b, int c) { return (a + b) * c; }
2331 };
2332
2333 // ============================================================================
2334 // [X86Test_FuncCallBase2]
2335 // ============================================================================
2336
2337 class X86Test_FuncCallBase2 : public X86Test {
2338 public:
X86Test_FuncCallBase2()2339 X86Test_FuncCallBase2() : X86Test("FuncCallBase2") {}
2340
2341 enum { kSize = 256 };
2342
add(X86TestApp & app)2343 static void add(X86TestApp& app) {
2344 app.add(new X86Test_FuncCallBase2());
2345 }
2346
compile(x86::Compiler & cc)2347 virtual void compile(x86::Compiler& cc) {
2348 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2349
2350 const int kTokenSize = 32;
2351
2352 x86::Mem s1 = cc.newStack(kTokenSize, 32);
2353 x86::Mem s2 = cc.newStack(kTokenSize, 32);
2354
2355 x86::Gp p1 = cc.newIntPtr("p1");
2356 x86::Gp p2 = cc.newIntPtr("p2");
2357
2358 x86::Gp ret = cc.newInt32("ret");
2359 Label L_Exit = cc.newLabel();
2360
2361 static const char token[kTokenSize] = "-+:|abcdefghijklmnopqrstuvwxyz|";
2362 FuncCallNode* call;
2363
2364 cc.lea(p1, s1);
2365 cc.lea(p2, s2);
2366
2367 // Try to corrupt the stack if wrongly allocated.
2368 call = cc.call(imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdHostCDecl));
2369 call->setArg(0, p1);
2370 call->setArg(1, imm(token));
2371 call->setArg(2, imm(kTokenSize));
2372 call->setRet(0, p1);
2373
2374 call = cc.call(imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdHostCDecl));
2375 call->setArg(0, p2);
2376 call->setArg(1, imm(token));
2377 call->setArg(2, imm(kTokenSize));
2378 call->setRet(0, p2);
2379
2380 call = cc.call(imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConv::kIdHostCDecl));
2381 call->setArg(0, p1);
2382 call->setArg(1, p2);
2383 call->setArg(2, imm(kTokenSize));
2384 call->setRet(0, ret);
2385
2386 // This should be 0 on success, however, if both `p1` and `p2` were
2387 // allocated in the same address this check will still pass.
2388 cc.cmp(ret, 0);
2389 cc.jnz(L_Exit);
2390
2391 // Checks whether `p1` and `p2` are different (must be).
2392 cc.xor_(ret, ret);
2393 cc.cmp(p1, p2);
2394 cc.setz(ret.r8());
2395
2396 cc.bind(L_Exit);
2397 cc.ret(ret);
2398 cc.endFunc();
2399 }
2400
run(void * _func,String & result,String & expect)2401 virtual bool run(void* _func, String& result, String& expect) {
2402 typedef int (*Func)(void);
2403 Func func = ptr_as_func<Func>(_func);
2404
2405 int resultRet = func();
2406 int expectRet = 0; // Must be zero, stack addresses must be different.
2407
2408 result.assignInt(resultRet);
2409 expect.assignInt(expectRet);
2410
2411 return resultRet == expectRet;
2412 }
2413 };
2414
2415 // ============================================================================
2416 // [X86Test_FuncCallStd]
2417 // ============================================================================
2418
2419 class X86Test_FuncCallStd : public X86Test {
2420 public:
X86Test_FuncCallStd()2421 X86Test_FuncCallStd() : X86Test("FuncCallStd") {}
2422
add(X86TestApp & app)2423 static void add(X86TestApp& app) {
2424 app.add(new X86Test_FuncCallStd());
2425 }
2426
compile(x86::Compiler & cc)2427 virtual void compile(x86::Compiler& cc) {
2428 x86::Gp x = cc.newInt32("x");
2429 x86::Gp y = cc.newInt32("y");
2430 x86::Gp z = cc.newInt32("z");
2431
2432 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
2433 cc.setArg(0, x);
2434 cc.setArg(1, y);
2435 cc.setArg(2, z);
2436
2437 FuncCallNode* call = cc.call(
2438 imm((void*)calledFunc),
2439 FuncSignatureT<int, int, int, int>(CallConv::kIdHostStdCall));
2440 call->setArg(0, x);
2441 call->setArg(1, y);
2442 call->setArg(2, z);
2443 call->setRet(0, x);
2444
2445 cc.ret(x);
2446 cc.endFunc();
2447 }
2448
run(void * _func,String & result,String & expect)2449 virtual bool run(void* _func, String& result, String& expect) {
2450 typedef int (*Func)(int, int, int);
2451 Func func = ptr_as_func<Func>(_func);
2452
2453 int resultRet = func(1, 42, 3);
2454 int expectRet = calledFunc(1, 42, 3);
2455
2456 result.assignFormat("ret=%d", resultRet);
2457 expect.assignFormat("ret=%d", expectRet);
2458
2459 return resultRet == expectRet;
2460 }
2461
2462 // STDCALL function that is called inside the generated one.
calledFunc(int a,int b,int c)2463 static int ASMJIT_STDCALL calledFunc(int a, int b, int c) noexcept {
2464 return (a + b) * c;
2465 }
2466 };
2467
2468 // ============================================================================
2469 // [X86Test_FuncCallFast]
2470 // ============================================================================
2471
2472 class X86Test_FuncCallFast : public X86Test {
2473 public:
X86Test_FuncCallFast()2474 X86Test_FuncCallFast() : X86Test("FuncCallFast") {}
2475
add(X86TestApp & app)2476 static void add(X86TestApp& app) {
2477 app.add(new X86Test_FuncCallFast());
2478 }
2479
compile(x86::Compiler & cc)2480 virtual void compile(x86::Compiler& cc) {
2481 x86::Gp var = cc.newInt32("var");
2482
2483 cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost));
2484 cc.setArg(0, var);
2485
2486 FuncCallNode* call;
2487 call = cc.call(
2488 imm((void*)calledFunc),
2489 FuncSignatureT<int, int>(CallConv::kIdHostFastCall));
2490 call->setArg(0, var);
2491 call->setRet(0, var);
2492
2493 call = cc.call(
2494 imm((void*)calledFunc),
2495 FuncSignatureT<int, int>(CallConv::kIdHostFastCall));
2496 call->setArg(0, var);
2497 call->setRet(0, var);
2498
2499 cc.ret(var);
2500 cc.endFunc();
2501 }
2502
run(void * _func,String & result,String & expect)2503 virtual bool run(void* _func, String& result, String& expect) {
2504 typedef int (*Func)(int);
2505 Func func = ptr_as_func<Func>(_func);
2506
2507 int resultRet = func(9);
2508 int expectRet = (9 * 9) * (9 * 9);
2509
2510 result.assignFormat("ret=%d", resultRet);
2511 expect.assignFormat("ret=%d", expectRet);
2512
2513 return resultRet == expectRet;
2514 }
2515
2516 // FASTCALL function that is called inside the generated one.
calledFunc(int a)2517 static int ASMJIT_FASTCALL calledFunc(int a) noexcept {
2518 return a * a;
2519 }
2520 };
2521
2522 // ============================================================================
2523 // [X86Test_FuncCallLight]
2524 // ============================================================================
2525
2526 class X86Test_FuncCallLight : public X86Test {
2527 public:
X86Test_FuncCallLight()2528 X86Test_FuncCallLight() : X86Test("FuncCallLight") {}
2529
add(X86TestApp & app)2530 static void add(X86TestApp& app) {
2531 app.add(new X86Test_FuncCallLight());
2532 }
2533
compile(x86::Compiler & cc)2534 virtual void compile(x86::Compiler& cc) {
2535 FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> funcSig(CallConv::kIdHostCDecl);
2536 FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> fastSig(CallConv::kIdHostLightCall2);
2537
2538 FuncNode* func = cc.newFunc(funcSig);
2539 FuncNode* fast = cc.newFunc(fastSig);
2540
2541 {
2542 x86::Gp aPtr = cc.newIntPtr("aPtr");
2543 x86::Gp bPtr = cc.newIntPtr("bPtr");
2544 x86::Gp cPtr = cc.newIntPtr("cPtr");
2545 x86::Gp dPtr = cc.newIntPtr("dPtr");
2546 x86::Gp pOut = cc.newIntPtr("pOut");
2547
2548 x86::Xmm aXmm = cc.newXmm("aXmm");
2549 x86::Xmm bXmm = cc.newXmm("bXmm");
2550 x86::Xmm cXmm = cc.newXmm("cXmm");
2551 x86::Xmm dXmm = cc.newXmm("dXmm");
2552
2553 cc.addFunc(func);
2554
2555 cc.setArg(0, aPtr);
2556 cc.setArg(1, bPtr);
2557 cc.setArg(2, cPtr);
2558 cc.setArg(3, dPtr);
2559 cc.setArg(4, pOut);
2560
2561 cc.movups(aXmm, x86::ptr(aPtr));
2562 cc.movups(bXmm, x86::ptr(bPtr));
2563 cc.movups(cXmm, x86::ptr(cPtr));
2564 cc.movups(dXmm, x86::ptr(dPtr));
2565
2566 x86::Xmm xXmm = cc.newXmm("xXmm");
2567 x86::Xmm yXmm = cc.newXmm("yXmm");
2568
2569 FuncCallNode* call1 = cc.call(fast->label(), fastSig);
2570 call1->setArg(0, aXmm);
2571 call1->setArg(1, bXmm);
2572 call1->setRet(0, xXmm);
2573
2574 FuncCallNode* call2 = cc.call(fast->label(), fastSig);
2575 call2->setArg(0, cXmm);
2576 call2->setArg(1, dXmm);
2577 call2->setRet(0, yXmm);
2578
2579 cc.pmullw(xXmm, yXmm);
2580 cc.movups(x86::ptr(pOut), xXmm);
2581
2582 cc.endFunc();
2583 }
2584
2585 {
2586 x86::Xmm aXmm = cc.newXmm("aXmm");
2587 x86::Xmm bXmm = cc.newXmm("bXmm");
2588
2589 cc.addFunc(fast);
2590 cc.setArg(0, aXmm);
2591 cc.setArg(1, bXmm);
2592 cc.paddw(aXmm, bXmm);
2593 cc.ret(aXmm);
2594 cc.endFunc();
2595 }
2596 }
2597
run(void * _func,String & result,String & expect)2598 virtual bool run(void* _func, String& result, String& expect) {
2599 typedef void (*Func)(const void*, const void*, const void*, const void*, void*);
2600
2601 Func func = ptr_as_func<Func>(_func);
2602
2603 int16_t a[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
2604 int16_t b[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
2605 int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 };
2606 int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 };
2607
2608 int16_t o[8];
2609 int oExp = 7 * 3;
2610
2611 func(a, b, c, d, o);
2612
2613 result.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7]);
2614 expect.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", oExp, oExp, oExp, oExp, oExp, oExp, oExp, oExp);
2615
2616 return result == expect;
2617 }
2618 };
2619
2620 // ============================================================================
2621 // [X86Test_FuncCallManyArgs]
2622 // ============================================================================
2623
2624 class X86Test_FuncCallManyArgs : public X86Test {
2625 public:
X86Test_FuncCallManyArgs()2626 X86Test_FuncCallManyArgs() : X86Test("FuncCallManyArgs") {}
2627
add(X86TestApp & app)2628 static void add(X86TestApp& app) {
2629 app.add(new X86Test_FuncCallManyArgs());
2630 }
2631
calledFunc(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j)2632 static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
2633 return (a * b * c * d * e) + (f * g * h * i * j);
2634 }
2635
compile(x86::Compiler & cc)2636 virtual void compile(x86::Compiler& cc) {
2637 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2638
2639 // Prepare.
2640 x86::Gp va = cc.newInt32("va");
2641 x86::Gp vb = cc.newInt32("vb");
2642 x86::Gp vc = cc.newInt32("vc");
2643 x86::Gp vd = cc.newInt32("vd");
2644 x86::Gp ve = cc.newInt32("ve");
2645 x86::Gp vf = cc.newInt32("vf");
2646 x86::Gp vg = cc.newInt32("vg");
2647 x86::Gp vh = cc.newInt32("vh");
2648 x86::Gp vi = cc.newInt32("vi");
2649 x86::Gp vj = cc.newInt32("vj");
2650
2651 cc.mov(va, 0x03);
2652 cc.mov(vb, 0x12);
2653 cc.mov(vc, 0xA0);
2654 cc.mov(vd, 0x0B);
2655 cc.mov(ve, 0x2F);
2656 cc.mov(vf, 0x02);
2657 cc.mov(vg, 0x0C);
2658 cc.mov(vh, 0x12);
2659 cc.mov(vi, 0x18);
2660 cc.mov(vj, 0x1E);
2661
2662 // Call function.
2663 FuncCallNode* call = cc.call(
2664 imm((void*)calledFunc),
2665 FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost));
2666 call->setArg(0, va);
2667 call->setArg(1, vb);
2668 call->setArg(2, vc);
2669 call->setArg(3, vd);
2670 call->setArg(4, ve);
2671 call->setArg(5, vf);
2672 call->setArg(6, vg);
2673 call->setArg(7, vh);
2674 call->setArg(8, vi);
2675 call->setArg(9, vj);
2676 call->setRet(0, va);
2677
2678 cc.ret(va);
2679 cc.endFunc();
2680 }
2681
run(void * _func,String & result,String & expect)2682 virtual bool run(void* _func, String& result, String& expect) {
2683 typedef int (*Func)(void);
2684 Func func = ptr_as_func<Func>(_func);
2685
2686 int resultRet = func();
2687 int expectRet = calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
2688
2689 result.assignFormat("ret=%d", resultRet);
2690 expect.assignFormat("ret=%d", expectRet);
2691
2692 return resultRet == expectRet;
2693 }
2694 };
2695
2696 // ============================================================================
2697 // [X86Test_FuncCallDuplicateArgs]
2698 // ============================================================================
2699
2700 class X86Test_FuncCallDuplicateArgs : public X86Test {
2701 public:
X86Test_FuncCallDuplicateArgs()2702 X86Test_FuncCallDuplicateArgs() : X86Test("FuncCallDuplicateArgs") {}
2703
add(X86TestApp & app)2704 static void add(X86TestApp& app) {
2705 app.add(new X86Test_FuncCallDuplicateArgs());
2706 }
2707
calledFunc(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j)2708 static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
2709 return (a * b * c * d * e) + (f * g * h * i * j);
2710 }
2711
compile(x86::Compiler & cc)2712 virtual void compile(x86::Compiler& cc) {
2713 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2714
2715 // Prepare.
2716 x86::Gp a = cc.newInt32("a");
2717 cc.mov(a, 3);
2718
2719 // Call function.
2720 FuncCallNode* call = cc.call(
2721 imm((void*)calledFunc),
2722 FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost));
2723 call->setArg(0, a);
2724 call->setArg(1, a);
2725 call->setArg(2, a);
2726 call->setArg(3, a);
2727 call->setArg(4, a);
2728 call->setArg(5, a);
2729 call->setArg(6, a);
2730 call->setArg(7, a);
2731 call->setArg(8, a);
2732 call->setArg(9, a);
2733 call->setRet(0, a);
2734
2735 cc.ret(a);
2736 cc.endFunc();
2737 }
2738
run(void * _func,String & result,String & expect)2739 virtual bool run(void* _func, String& result, String& expect) {
2740 typedef int (*Func)(void);
2741 Func func = ptr_as_func<Func>(_func);
2742
2743 int resultRet = func();
2744 int expectRet = calledFunc(3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
2745
2746 result.assignFormat("ret=%d", resultRet);
2747 expect.assignFormat("ret=%d", expectRet);
2748
2749 return resultRet == expectRet;
2750 }
2751 };
2752
2753 // ============================================================================
2754 // [X86Test_FuncCallImmArgs]
2755 // ============================================================================
2756
2757 class X86Test_FuncCallImmArgs : public X86Test {
2758 public:
X86Test_FuncCallImmArgs()2759 X86Test_FuncCallImmArgs() : X86Test("FuncCallImmArgs") {}
2760
add(X86TestApp & app)2761 static void add(X86TestApp& app) {
2762 app.add(new X86Test_FuncCallImmArgs());
2763 }
2764
compile(x86::Compiler & cc)2765 virtual void compile(x86::Compiler& cc) {
2766 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2767
2768 // Prepare.
2769 x86::Gp rv = cc.newInt32("rv");
2770
2771 // Call function.
2772 FuncCallNode* call = cc.call(
2773 imm((void*)X86Test_FuncCallManyArgs::calledFunc),
2774 FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost));
2775
2776 call->setArg(0, imm(0x03));
2777 call->setArg(1, imm(0x12));
2778 call->setArg(2, imm(0xA0));
2779 call->setArg(3, imm(0x0B));
2780 call->setArg(4, imm(0x2F));
2781 call->setArg(5, imm(0x02));
2782 call->setArg(6, imm(0x0C));
2783 call->setArg(7, imm(0x12));
2784 call->setArg(8, imm(0x18));
2785 call->setArg(9, imm(0x1E));
2786 call->setRet(0, rv);
2787
2788 cc.ret(rv);
2789 cc.endFunc();
2790 }
2791
run(void * _func,String & result,String & expect)2792 virtual bool run(void* _func, String& result, String& expect) {
2793 typedef int (*Func)(void);
2794 Func func = ptr_as_func<Func>(_func);
2795
2796 int resultRet = func();
2797 int expectRet = X86Test_FuncCallManyArgs::calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
2798
2799 result.assignFormat("ret=%d", resultRet);
2800 expect.assignFormat("ret=%d", expectRet);
2801
2802 return resultRet == expectRet;
2803 }
2804 };
2805
2806 // ============================================================================
2807 // [X86Test_FuncCallPtrArgs]
2808 // ============================================================================
2809
2810 class X86Test_FuncCallPtrArgs : public X86Test {
2811 public:
X86Test_FuncCallPtrArgs()2812 X86Test_FuncCallPtrArgs() : X86Test("FuncCallPtrArgs") {}
2813
add(X86TestApp & app)2814 static void add(X86TestApp& app) {
2815 app.add(new X86Test_FuncCallPtrArgs());
2816 }
2817
calledFunc(void * a,void * b,void * c,void * d,void * e,void * f,void * g,void * h,void * i,void * j)2818 static int calledFunc(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j) {
2819 return int((intptr_t)a) +
2820 int((intptr_t)b) +
2821 int((intptr_t)c) +
2822 int((intptr_t)d) +
2823 int((intptr_t)e) +
2824 int((intptr_t)f) +
2825 int((intptr_t)g) +
2826 int((intptr_t)h) +
2827 int((intptr_t)i) +
2828 int((intptr_t)j) ;
2829 }
2830
compile(x86::Compiler & cc)2831 virtual void compile(x86::Compiler& cc) {
2832 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
2833
2834 // Prepare.
2835 x86::Gp rv = cc.newInt32("rv");
2836
2837 // Call function.
2838 FuncCallNode* call = cc.call(
2839 imm((void*)calledFunc),
2840 FuncSignatureT<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>(CallConv::kIdHost));
2841
2842 call->setArg(0, imm(0x01));
2843 call->setArg(1, imm(0x02));
2844 call->setArg(2, imm(0x03));
2845 call->setArg(3, imm(0x04));
2846 call->setArg(4, imm(0x05));
2847 call->setArg(5, imm(0x06));
2848 call->setArg(6, imm(0x07));
2849 call->setArg(7, imm(0x08));
2850 call->setArg(8, imm(0x09));
2851 call->setArg(9, imm(0x0A));
2852 call->setRet(0, rv);
2853
2854 cc.ret(rv);
2855 cc.endFunc();
2856 }
2857
run(void * _func,String & result,String & expect)2858 virtual bool run(void* _func, String& result, String& expect) {
2859 typedef int (*Func)(void);
2860 Func func = ptr_as_func<Func>(_func);
2861
2862 int resultRet = func();
2863 int expectRet = 55;
2864
2865 result.assignFormat("ret=%d", resultRet);
2866 expect.assignFormat("ret=%d", expectRet);
2867
2868 return resultRet == expectRet;
2869 }
2870 };
2871
2872 // ============================================================================
2873 // [X86Test_FuncCallRefArgs]
2874 // ============================================================================
2875
2876 class X86Test_FuncCallRefArgs : public X86Test {
2877 public:
X86Test_FuncCallRefArgs()2878 X86Test_FuncCallRefArgs() : X86Test("FuncCallRefArgs") {}
2879
add(X86TestApp & app)2880 static void add(X86TestApp& app) {
2881 app.add(new X86Test_FuncCallRefArgs());
2882 }
2883
calledFunc(int & a,int & b,int & c,int & d)2884 static int calledFunc(int& a, int& b, int& c, int& d) {
2885 a += a;
2886 b += b;
2887 c += c;
2888 d += d;
2889 return a + b + c + d;
2890 }
2891
compile(x86::Compiler & cc)2892 virtual void compile(x86::Compiler& cc) {
2893 cc.addFunc(FuncSignatureT<int, int&, int&, int&, int&>(CallConv::kIdHost));
2894
2895 // Prepare.
2896 x86::Gp arg1 = cc.newInt32();
2897 x86::Gp arg2 = cc.newInt32();
2898 x86::Gp arg3 = cc.newInt32();
2899 x86::Gp arg4 = cc.newInt32();
2900 x86::Gp rv = cc.newInt32("rv");
2901
2902 cc.setArg(0, arg1);
2903 cc.setArg(1, arg2);
2904 cc.setArg(2, arg3);
2905 cc.setArg(3, arg4);
2906
2907 // Call function.
2908 FuncCallNode* call = cc.call(
2909 imm((void*)calledFunc),
2910 FuncSignatureT<int, int&, int&, int&, int&>(CallConv::kIdHost));
2911
2912 call->setArg(0, arg1);
2913 call->setArg(1, arg2);
2914 call->setArg(2, arg3);
2915 call->setArg(3, arg4);
2916 call->setRet(0, rv);
2917
2918 cc.ret(rv);
2919 cc.endFunc();
2920 }
2921
run(void * _func,String & result,String & expect)2922 virtual bool run(void* _func, String& result, String& expect) {
2923 typedef int (*Func)(int&, int&, int&, int&);
2924 Func func = ptr_as_func<Func>(_func);
2925
2926 int inputs[4] = { 1, 2, 3, 4 };
2927 int outputs[4] = { 2, 4, 6, 8 };
2928 int resultRet = func(inputs[0], inputs[1], inputs[2], inputs[3]);
2929 int expectRet = 20;
2930
2931 result.assignFormat("ret={%08X %08X %08X %08X %08X}", resultRet, inputs[0], inputs[1], inputs[2], inputs[3]);
2932 expect.assignFormat("ret={%08X %08X %08X %08X %08X}", expectRet, outputs[0], outputs[1], outputs[2], outputs[3]);
2933
2934 return resultRet == expectRet;
2935 }
2936 };
2937
2938 // ============================================================================
2939 // [X86Test_FuncCallFloatAsXmmRet]
2940 // ============================================================================
2941
2942 class X86Test_FuncCallFloatAsXmmRet : public X86Test {
2943 public:
X86Test_FuncCallFloatAsXmmRet()2944 X86Test_FuncCallFloatAsXmmRet() : X86Test("FuncCallFloatAsXmmRet") {}
2945
add(X86TestApp & app)2946 static void add(X86TestApp& app) {
2947 app.add(new X86Test_FuncCallFloatAsXmmRet());
2948 }
2949
calledFunc(float a,float b)2950 static float calledFunc(float a, float b) {
2951 return a * b;
2952 }
2953
compile(x86::Compiler & cc)2954 virtual void compile(x86::Compiler& cc) {
2955 cc.addFunc(FuncSignatureT<float, float, float>(CallConv::kIdHost));
2956
2957 x86::Xmm a = cc.newXmmSs("a");
2958 x86::Xmm b = cc.newXmmSs("b");
2959 x86::Xmm ret = cc.newXmmSs("ret");
2960
2961 cc.setArg(0, a);
2962 cc.setArg(1, b);
2963
2964 // Call function.
2965 FuncCallNode* call = cc.call(
2966 imm((void*)calledFunc),
2967 FuncSignatureT<float, float, float>(CallConv::kIdHost));
2968 call->setArg(0, a);
2969 call->setArg(1, b);
2970 call->setRet(0, ret);
2971
2972 cc.ret(ret);
2973 cc.endFunc();
2974 }
2975
run(void * _func,String & result,String & expect)2976 virtual bool run(void* _func, String& result, String& expect) {
2977 typedef float (*Func)(float, float);
2978 Func func = ptr_as_func<Func>(_func);
2979
2980 float resultRet = func(15.5f, 2.0f);
2981 float expectRet = calledFunc(15.5f, 2.0f);
2982
2983 result.assignFormat("ret=%g", resultRet);
2984 expect.assignFormat("ret=%g", expectRet);
2985
2986 return resultRet == expectRet;
2987 }
2988 };
2989
2990 // ============================================================================
2991 // [X86Test_FuncCallDoubleAsXmmRet]
2992 // ============================================================================
2993
2994 class X86Test_FuncCallDoubleAsXmmRet : public X86Test {
2995 public:
X86Test_FuncCallDoubleAsXmmRet()2996 X86Test_FuncCallDoubleAsXmmRet() : X86Test("FuncCallDoubleAsXmmRet") {}
2997
add(X86TestApp & app)2998 static void add(X86TestApp& app) {
2999 app.add(new X86Test_FuncCallDoubleAsXmmRet());
3000 }
3001
calledFunc(double a,double b)3002 static double calledFunc(double a, double b) {
3003 return a * b;
3004 }
3005
compile(x86::Compiler & cc)3006 virtual void compile(x86::Compiler& cc) {
3007 cc.addFunc(FuncSignatureT<double, double, double>(CallConv::kIdHost));
3008
3009 x86::Xmm a = cc.newXmmSd("a");
3010 x86::Xmm b = cc.newXmmSd("b");
3011 x86::Xmm ret = cc.newXmmSd("ret");
3012
3013 cc.setArg(0, a);
3014 cc.setArg(1, b);
3015
3016 FuncCallNode* call = cc.call(
3017 imm((void*)calledFunc),
3018 FuncSignatureT<double, double, double>(CallConv::kIdHost));
3019 call->setArg(0, a);
3020 call->setArg(1, b);
3021 call->setRet(0, ret);
3022
3023 cc.ret(ret);
3024 cc.endFunc();
3025 }
3026
run(void * _func,String & result,String & expect)3027 virtual bool run(void* _func, String& result, String& expect) {
3028 typedef double (*Func)(double, double);
3029 Func func = ptr_as_func<Func>(_func);
3030
3031 double resultRet = func(15.5, 2.0);
3032 double expectRet = calledFunc(15.5, 2.0);
3033
3034 result.assignFormat("ret=%g", resultRet);
3035 expect.assignFormat("ret=%g", expectRet);
3036
3037 return resultRet == expectRet;
3038 }
3039 };
3040
3041 // ============================================================================
3042 // [X86Test_FuncCallConditional]
3043 // ============================================================================
3044
3045 class X86Test_FuncCallConditional : public X86Test {
3046 public:
X86Test_FuncCallConditional()3047 X86Test_FuncCallConditional() : X86Test("FuncCallConditional") {}
3048
add(X86TestApp & app)3049 static void add(X86TestApp& app) {
3050 app.add(new X86Test_FuncCallConditional());
3051 }
3052
compile(x86::Compiler & cc)3053 virtual void compile(x86::Compiler& cc) {
3054 x86::Gp x = cc.newInt32("x");
3055 x86::Gp y = cc.newInt32("y");
3056 x86::Gp op = cc.newInt32("op");
3057
3058 FuncCallNode* call;
3059 x86::Gp result;
3060
3061 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
3062 cc.setArg(0, x);
3063 cc.setArg(1, y);
3064 cc.setArg(2, op);
3065
3066 Label opAdd = cc.newLabel();
3067 Label opMul = cc.newLabel();
3068
3069 cc.cmp(op, 0);
3070 cc.jz(opAdd);
3071 cc.cmp(op, 1);
3072 cc.jz(opMul);
3073
3074 result = cc.newInt32("result_0");
3075 cc.mov(result, 0);
3076 cc.ret(result);
3077
3078 cc.bind(opAdd);
3079 result = cc.newInt32("result_1");
3080
3081 call = cc.call((uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConv::kIdHost));
3082 call->setArg(0, x);
3083 call->setArg(1, y);
3084 call->setRet(0, result);
3085 cc.ret(result);
3086
3087 cc.bind(opMul);
3088 result = cc.newInt32("result_2");
3089
3090 call = cc.call((uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConv::kIdHost));
3091 call->setArg(0, x);
3092 call->setArg(1, y);
3093 call->setRet(0, result);
3094
3095 cc.ret(result);
3096 cc.endFunc();
3097 }
3098
run(void * _func,String & result,String & expect)3099 virtual bool run(void* _func, String& result, String& expect) {
3100 typedef int (*Func)(int, int, int);
3101 Func func = ptr_as_func<Func>(_func);
3102
3103 int arg1 = 4;
3104 int arg2 = 8;
3105
3106 int resultAdd = func(arg1, arg2, 0);
3107 int expectAdd = calledFuncAdd(arg1, arg2);
3108
3109 int resultMul = func(arg1, arg2, 1);
3110 int expectMul = calledFuncMul(arg1, arg2);
3111
3112 result.assignFormat("ret={add=%d, mul=%d}", resultAdd, resultMul);
3113 expect.assignFormat("ret={add=%d, mul=%d}", expectAdd, expectMul);
3114
3115 return (resultAdd == expectAdd) && (resultMul == expectMul);
3116 }
3117
calledFuncAdd(int x,int y)3118 static int calledFuncAdd(int x, int y) { return x + y; }
calledFuncMul(int x,int y)3119 static int calledFuncMul(int x, int y) { return x * y; }
3120 };
3121
3122 // ============================================================================
3123 // [X86Test_FuncCallMultiple]
3124 // ============================================================================
3125
3126 class X86Test_FuncCallMultiple : public X86Test {
3127 public:
X86Test_FuncCallMultiple()3128 X86Test_FuncCallMultiple() : X86Test("FuncCallMultiple") {}
3129
add(X86TestApp & app)3130 static void add(X86TestApp& app) {
3131 app.add(new X86Test_FuncCallMultiple());
3132 }
3133
calledFunc(int * pInt,int index)3134 static int ASMJIT_FASTCALL calledFunc(int* pInt, int index) {
3135 return pInt[index];
3136 }
3137
compile(x86::Compiler & cc)3138 virtual void compile(x86::Compiler& cc) {
3139 unsigned int i;
3140
3141 x86::Gp buf = cc.newIntPtr("buf");
3142 x86::Gp acc0 = cc.newInt32("acc0");
3143 x86::Gp acc1 = cc.newInt32("acc1");
3144
3145 cc.addFunc(FuncSignatureT<int, int*>(CallConv::kIdHost));
3146 cc.setArg(0, buf);
3147
3148 cc.mov(acc0, 0);
3149 cc.mov(acc1, 0);
3150
3151 for (i = 0; i < 4; i++) {
3152 x86::Gp ret = cc.newInt32("ret");
3153 x86::Gp ptr = cc.newIntPtr("ptr");
3154 x86::Gp idx = cc.newInt32("idx");
3155 FuncCallNode* call;
3156
3157 cc.mov(ptr, buf);
3158 cc.mov(idx, int(i));
3159
3160 call = cc.call((uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdHostFastCall));
3161 call->setArg(0, ptr);
3162 call->setArg(1, idx);
3163 call->setRet(0, ret);
3164
3165 cc.add(acc0, ret);
3166
3167 cc.mov(ptr, buf);
3168 cc.mov(idx, int(i));
3169
3170 call = cc.call((uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdHostFastCall));
3171 call->setArg(0, ptr);
3172 call->setArg(1, idx);
3173 call->setRet(0, ret);
3174
3175 cc.sub(acc1, ret);
3176 }
3177
3178 cc.add(acc0, acc1);
3179 cc.ret(acc0);
3180 cc.endFunc();
3181 }
3182
run(void * _func,String & result,String & expect)3183 virtual bool run(void* _func, String& result, String& expect) {
3184 typedef int (*Func)(int*);
3185 Func func = ptr_as_func<Func>(_func);
3186
3187 int buffer[4] = { 127, 87, 23, 17 };
3188
3189 int resultRet = func(buffer);
3190 int expectRet = 0;
3191
3192 result.assignFormat("ret=%d", resultRet);
3193 expect.assignFormat("ret=%d", expectRet);
3194
3195 return resultRet == expectRet;
3196 }
3197 };
3198
3199 // ============================================================================
3200 // [X86Test_FuncCallRecursive]
3201 // ============================================================================
3202
3203 class X86Test_FuncCallRecursive : public X86Test {
3204 public:
X86Test_FuncCallRecursive()3205 X86Test_FuncCallRecursive() : X86Test("FuncCallRecursive") {}
3206
add(X86TestApp & app)3207 static void add(X86TestApp& app) {
3208 app.add(new X86Test_FuncCallRecursive());
3209 }
3210
compile(x86::Compiler & cc)3211 virtual void compile(x86::Compiler& cc) {
3212 x86::Gp val = cc.newInt32("val");
3213 Label skip = cc.newLabel();
3214
3215 FuncNode* func = cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost));
3216 cc.setArg(0, val);
3217
3218 cc.cmp(val, 1);
3219 cc.jle(skip);
3220
3221 x86::Gp tmp = cc.newInt32("tmp");
3222 cc.mov(tmp, val);
3223 cc.dec(tmp);
3224
3225 FuncCallNode* call = cc.call(func->label(), FuncSignatureT<int, int>(CallConv::kIdHost));
3226 call->setArg(0, tmp);
3227 call->setRet(0, tmp);
3228 cc.mul(cc.newInt32(), val, tmp);
3229
3230 cc.bind(skip);
3231 cc.ret(val);
3232 cc.endFunc();
3233 }
3234
run(void * _func,String & result,String & expect)3235 virtual bool run(void* _func, String& result, String& expect) {
3236 typedef int (*Func)(int);
3237 Func func = ptr_as_func<Func>(_func);
3238
3239 int resultRet = func(5);
3240 int expectRet = 1 * 2 * 3 * 4 * 5;
3241
3242 result.assignFormat("ret=%d", resultRet);
3243 expect.assignFormat("ret=%d", expectRet);
3244
3245 return resultRet == expectRet;
3246 }
3247 };
3248
3249 // ============================================================================
3250 // [X86Test_FuncCallVarArg1]
3251 // ============================================================================
3252
3253 class X86Test_FuncCallVarArg1 : public X86Test {
3254 public:
X86Test_FuncCallVarArg1()3255 X86Test_FuncCallVarArg1() : X86Test("FuncCallVarArg1") {}
3256
add(X86TestApp & app)3257 static void add(X86TestApp& app) {
3258 app.add(new X86Test_FuncCallVarArg1());
3259 }
3260
compile(x86::Compiler & cc)3261 virtual void compile(x86::Compiler& cc) {
3262 cc.addFunc(FuncSignatureT<int, int, int, int, int>(CallConv::kIdHost));
3263
3264 x86::Gp a0 = cc.newInt32("a0");
3265 x86::Gp a1 = cc.newInt32("a1");
3266 x86::Gp a2 = cc.newInt32("a2");
3267 x86::Gp a3 = cc.newInt32("a3");
3268
3269 cc.setArg(0, a0);
3270 cc.setArg(1, a1);
3271 cc.setArg(2, a2);
3272 cc.setArg(3, a3);
3273
3274 // We call `int func(size_t, ...)`
3275 // - The `vaIndex` must be 1 (first argument after size_t).
3276 // - The full signature of varargs (int, int, int, int) must follow.
3277 FuncCallNode* call = cc.call(
3278 imm((void*)calledFunc),
3279 FuncSignatureT<int, size_t, int, int, int, int>(CallConv::kIdHost, 1));
3280 call->setArg(0, imm(4));
3281 call->setArg(1, a0);
3282 call->setArg(2, a1);
3283 call->setArg(3, a2);
3284 call->setArg(4, a3);
3285 call->setRet(0, a0);
3286
3287 cc.ret(a0);
3288 cc.endFunc();
3289 }
3290
run(void * _func,String & result,String & expect)3291 virtual bool run(void* _func, String& result, String& expect) {
3292 typedef int (*Func)(int, int, int, int);
3293 Func func = ptr_as_func<Func>(_func);
3294
3295 int resultRet = func(1, 2, 3, 4);
3296 int expectRet = 1 + 2 + 3 + 4;
3297
3298 result.assignFormat("ret=%d", resultRet);
3299 expect.assignFormat("ret=%d", expectRet);
3300
3301 return resultRet == expectRet;
3302 }
3303
calledFunc(size_t n,...)3304 static int calledFunc(size_t n, ...) {
3305 int sum = 0;
3306 va_list ap;
3307 va_start(ap, n);
3308 for (size_t i = 0; i < n; i++) {
3309 int arg = va_arg(ap, int);
3310 sum += arg;
3311 }
3312 va_end(ap);
3313 return sum;
3314 }
3315 };
3316
3317 // ============================================================================
3318 // [X86Test_FuncCallVarArg2]
3319 // ============================================================================
3320
3321 class X86Test_FuncCallVarArg2 : public X86Test {
3322 public:
X86Test_FuncCallVarArg2()3323 X86Test_FuncCallVarArg2() : X86Test("FuncCallVarArg2") {}
3324
add(X86TestApp & app)3325 static void add(X86TestApp& app) {
3326 app.add(new X86Test_FuncCallVarArg2());
3327 }
3328
compile(x86::Compiler & cc)3329 virtual void compile(x86::Compiler& cc) {
3330 cc.addFunc(FuncSignatureT<double, double, double, double, double>(CallConv::kIdHost));
3331
3332 x86::Xmm a0 = cc.newXmmSd("a0");
3333 x86::Xmm a1 = cc.newXmmSd("a1");
3334 x86::Xmm a2 = cc.newXmmSd("a2");
3335 x86::Xmm a3 = cc.newXmmSd("a3");
3336
3337 cc.setArg(0, a0);
3338 cc.setArg(1, a1);
3339 cc.setArg(2, a2);
3340 cc.setArg(3, a3);
3341
3342 // We call `double func(size_t, ...)`
3343 // - The `vaIndex` must be 1 (first argument after size_t).
3344 // - The full signature of varargs (double, double, double, double) must follow.
3345 FuncCallNode* call = cc.call(
3346 imm((void*)calledFunc),
3347 FuncSignatureT<double, size_t, double, double, double, double>(CallConv::kIdHost, 1));
3348 call->setArg(0, imm(4));
3349 call->setArg(1, a0);
3350 call->setArg(2, a1);
3351 call->setArg(3, a2);
3352 call->setArg(4, a3);
3353 call->setRet(0, a0);
3354
3355 cc.ret(a0);
3356 cc.endFunc();
3357 }
3358
run(void * _func,String & result,String & expect)3359 virtual bool run(void* _func, String& result, String& expect) {
3360 typedef double (*Func)(double, double, double, double);
3361 Func func = ptr_as_func<Func>(_func);
3362
3363 double resultRet = func(1.0, 2.0, 3.0, 4.0);
3364 double expectRet = 1.0 + 2.0 + 3.0 + 4.0;
3365
3366 result.assignFormat("ret=%f", resultRet);
3367 expect.assignFormat("ret=%f", expectRet);
3368
3369 return resultRet == expectRet;
3370 }
3371
calledFunc(size_t n,...)3372 static double calledFunc(size_t n, ...) {
3373 double sum = 0;
3374 va_list ap;
3375 va_start(ap, n);
3376 for (size_t i = 0; i < n; i++) {
3377 double arg = va_arg(ap, double);
3378 sum += arg;
3379 }
3380 va_end(ap);
3381 return sum;
3382 }
3383 };
3384
3385 // ============================================================================
3386 // [X86Test_FuncCallMisc1]
3387 // ============================================================================
3388
3389 class X86Test_FuncCallMisc1 : public X86Test {
3390 public:
X86Test_FuncCallMisc1()3391 X86Test_FuncCallMisc1() : X86Test("FuncCallMisc1") {}
3392
add(X86TestApp & app)3393 static void add(X86TestApp& app) {
3394 app.add(new X86Test_FuncCallMisc1());
3395 }
3396
dummy(int,int)3397 static void dummy(int, int) {}
3398
compile(x86::Compiler & cc)3399 virtual void compile(x86::Compiler& cc) {
3400 cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
3401
3402 x86::Gp a = cc.newInt32("a");
3403 x86::Gp b = cc.newInt32("b");
3404 x86::Gp r = cc.newInt32("r");
3405
3406 cc.setArg(0, a);
3407 cc.setArg(1, b);
3408
3409 FuncCallNode* call = cc.call(
3410 imm((void*)dummy),
3411 FuncSignatureT<void, int, int>(CallConv::kIdHost));
3412 call->setArg(0, a);
3413 call->setArg(1, b);
3414
3415 cc.lea(r, x86::ptr(a, b));
3416 cc.ret(r);
3417
3418 cc.endFunc();
3419 }
3420
run(void * _func,String & result,String & expect)3421 virtual bool run(void* _func, String& result, String& expect) {
3422 typedef int (*Func)(int, int);
3423 Func func = ptr_as_func<Func>(_func);
3424
3425 int resultRet = func(44, 199);
3426 int expectRet = 243;
3427
3428 result.assignFormat("ret=%d", resultRet);
3429 expect.assignFormat("ret=%d", expectRet);
3430
3431 return resultRet == expectRet;
3432 }
3433 };
3434
3435 // ============================================================================
3436 // [X86Test_FuncCallMisc2]
3437 // ============================================================================
3438
3439 class X86Test_FuncCallMisc2 : public X86Test {
3440 public:
X86Test_FuncCallMisc2()3441 X86Test_FuncCallMisc2() : X86Test("FuncCallMisc2") {}
3442
add(X86TestApp & app)3443 static void add(X86TestApp& app) {
3444 app.add(new X86Test_FuncCallMisc2());
3445 }
3446
compile(x86::Compiler & cc)3447 virtual void compile(x86::Compiler& cc) {
3448 cc.addFunc(FuncSignatureT<double, const double*>(CallConv::kIdHost));
3449
3450 x86::Gp p = cc.newIntPtr("p");
3451 x86::Xmm arg = cc.newXmmSd("arg");
3452 x86::Xmm ret = cc.newXmmSd("ret");
3453
3454 cc.setArg(0, p);
3455 cc.movsd(arg, x86::ptr(p));
3456
3457 FuncCallNode* call = cc.call(
3458 imm((void*)op),
3459 FuncSignatureT<double, double>(CallConv::kIdHost));
3460 call->setArg(0, arg);
3461 call->setRet(0, ret);
3462
3463 cc.ret(ret);
3464 cc.endFunc();
3465 }
3466
run(void * _func,String & result,String & expect)3467 virtual bool run(void* _func, String& result, String& expect) {
3468 typedef double (*Func)(const double*);
3469 Func func = ptr_as_func<Func>(_func);
3470
3471 double arg = 2;
3472
3473 double resultRet = func(&arg);
3474 double expectRet = op(arg);
3475
3476 result.assignFormat("ret=%g", resultRet);
3477 expect.assignFormat("ret=%g", expectRet);
3478
3479 return resultRet == expectRet;
3480 }
3481
op(double a)3482 static double op(double a) { return a * a; }
3483 };
3484
3485 // ============================================================================
3486 // [X86Test_FuncCallMisc3]
3487 // ============================================================================
3488
3489 class X86Test_FuncCallMisc3 : public X86Test {
3490 public:
X86Test_FuncCallMisc3()3491 X86Test_FuncCallMisc3() : X86Test("FuncCallMisc3") {}
3492
add(X86TestApp & app)3493 static void add(X86TestApp& app) {
3494 app.add(new X86Test_FuncCallMisc3());
3495 }
3496
compile(x86::Compiler & cc)3497 virtual void compile(x86::Compiler& cc) {
3498 cc.addFunc(FuncSignatureT<double, const double*>(CallConv::kIdHost));
3499
3500 x86::Gp p = cc.newIntPtr("p");
3501 x86::Xmm arg = cc.newXmmSd("arg");
3502 x86::Xmm ret = cc.newXmmSd("ret");
3503
3504 cc.setArg(0, p);
3505 cc.movsd(arg, x86::ptr(p));
3506
3507 FuncCallNode* call = cc.call(
3508 imm((void*)op),
3509 FuncSignatureT<double, double>(CallConv::kIdHost));
3510 call->setArg(0, arg);
3511 call->setRet(0, ret);
3512
3513 cc.xorps(arg, arg);
3514 cc.subsd(arg, ret);
3515
3516 cc.ret(arg);
3517 cc.endFunc();
3518 }
3519
run(void * _func,String & result,String & expect)3520 virtual bool run(void* _func, String& result, String& expect) {
3521 typedef double (*Func)(const double*);
3522 Func func = ptr_as_func<Func>(_func);
3523
3524 double arg = 2;
3525
3526 double resultRet = func(&arg);
3527 double expectRet = -op(arg);
3528
3529 result.assignFormat("ret=%g", resultRet);
3530 expect.assignFormat("ret=%g", expectRet);
3531
3532 return resultRet == expectRet;
3533 }
3534
op(double a)3535 static double op(double a) { return a * a; }
3536 };
3537
3538 // ============================================================================
3539 // [X86Test_FuncCallMisc4]
3540 // ============================================================================
3541
3542 class X86Test_FuncCallMisc4 : public X86Test {
3543 public:
X86Test_FuncCallMisc4()3544 X86Test_FuncCallMisc4() : X86Test("FuncCallMisc4") {}
3545
add(X86TestApp & app)3546 static void add(X86TestApp& app) {
3547 app.add(new X86Test_FuncCallMisc4());
3548 }
3549
compile(x86::Compiler & cc)3550 virtual void compile(x86::Compiler& cc) {
3551 FuncSignatureBuilder funcPrototype;
3552 funcPrototype.setCallConv(CallConv::kIdHost);
3553 funcPrototype.setRet(Type::kIdF64);
3554 cc.addFunc(funcPrototype);
3555
3556 FuncSignatureBuilder callPrototype;
3557 callPrototype.setCallConv(CallConv::kIdHost);
3558 callPrototype.setRet(Type::kIdF64);
3559 FuncCallNode* call = cc.call(imm((void*)calledFunc), callPrototype);
3560
3561 x86::Xmm ret = cc.newXmmSd("ret");
3562 call->setRet(0, ret);
3563 cc.ret(ret);
3564
3565 cc.endFunc();
3566 }
3567
run(void * _func,String & result,String & expect)3568 virtual bool run(void* _func, String& result, String& expect) {
3569 typedef double (*Func)(void);
3570 Func func = ptr_as_func<Func>(_func);
3571
3572 double resultRet = func();
3573 double expectRet = 3.14;
3574
3575 result.assignFormat("ret=%g", resultRet);
3576 expect.assignFormat("ret=%g", expectRet);
3577
3578 return resultRet == expectRet;
3579 }
3580
calledFunc()3581 static double calledFunc() { return 3.14; }
3582 };
3583
3584 // ============================================================================
3585 // [X86Test_FuncCallMisc5]
3586 // ============================================================================
3587
3588 // The register allocator should clobber the register used by the `call` itself.
3589 class X86Test_FuncCallMisc5 : public X86Test {
3590 public:
X86Test_FuncCallMisc5()3591 X86Test_FuncCallMisc5() : X86Test("FuncCallMisc5") {}
3592
add(X86TestApp & app)3593 static void add(X86TestApp& app) {
3594 app.add(new X86Test_FuncCallMisc5());
3595 }
3596
compile(x86::Compiler & cc)3597 virtual void compile(x86::Compiler& cc) {
3598 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
3599
3600 x86::Gp pFn = cc.newIntPtr("pFn");
3601 x86::Gp vars[16];
3602
3603 uint32_t i, regCount = cc.gpCount();
3604 ASMJIT_ASSERT(regCount <= ASMJIT_ARRAY_SIZE(vars));
3605
3606 cc.mov(pFn, imm((void*)calledFunc));
3607
3608 for (i = 0; i < regCount; i++) {
3609 if (i == x86::Gp::kIdBp || i == x86::Gp::kIdSp)
3610 continue;
3611
3612 vars[i] = cc.newInt32("%%%u", unsigned(i));
3613 cc.mov(vars[i], 1);
3614 }
3615
3616 cc.call(pFn, FuncSignatureT<void>(CallConv::kIdHost));
3617 for (i = 1; i < regCount; i++)
3618 if (vars[i].isValid())
3619 cc.add(vars[0], vars[i]);
3620 cc.ret(vars[0]);
3621
3622 cc.endFunc();
3623 }
3624
run(void * _func,String & result,String & expect)3625 virtual bool run(void* _func, String& result, String& expect) {
3626 typedef int (*Func)(void);
3627 Func func = ptr_as_func<Func>(_func);
3628
3629 int resultRet = func();
3630 int expectRet = sizeof(void*) == 4 ? 6 : 14;
3631
3632 result.assignFormat("ret=%d", resultRet);
3633 expect.assignFormat("ret=%d", expectRet);
3634
3635 return resultRet == expectRet;
3636 }
3637
calledFunc()3638 static void calledFunc() {}
3639 };
3640
3641 // ============================================================================
3642 // [X86Test_MiscLocalConstPool]
3643 // ============================================================================
3644
3645 class X86Test_MiscLocalConstPool : public X86Test {
3646 public:
X86Test_MiscLocalConstPool()3647 X86Test_MiscLocalConstPool() : X86Test("MiscLocalConstPool") {}
3648
add(X86TestApp & app)3649 static void add(X86TestApp& app) {
3650 app.add(new X86Test_MiscLocalConstPool());
3651 }
3652
compile(x86::Compiler & cc)3653 virtual void compile(x86::Compiler& cc) {
3654 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
3655
3656 x86::Gp v0 = cc.newInt32("v0");
3657 x86::Gp v1 = cc.newInt32("v1");
3658
3659 x86::Mem c0 = cc.newInt32Const(ConstPool::kScopeLocal, 200);
3660 x86::Mem c1 = cc.newInt32Const(ConstPool::kScopeLocal, 33);
3661
3662 cc.mov(v0, c0);
3663 cc.mov(v1, c1);
3664 cc.add(v0, v1);
3665
3666 cc.ret(v0);
3667 cc.endFunc();
3668 }
3669
run(void * _func,String & result,String & expect)3670 virtual bool run(void* _func, String& result, String& expect) {
3671 typedef int (*Func)(void);
3672 Func func = ptr_as_func<Func>(_func);
3673
3674 int resultRet = func();
3675 int expectRet = 233;
3676
3677 result.assignFormat("ret=%d", resultRet);
3678 expect.assignFormat("ret=%d", expectRet);
3679
3680 return resultRet == expectRet;
3681 }
3682 };
3683
3684 // ============================================================================
3685 // [X86Test_MiscGlobalConstPool]
3686 // ============================================================================
3687
3688 class X86Test_MiscGlobalConstPool : public X86Test {
3689 public:
X86Test_MiscGlobalConstPool()3690 X86Test_MiscGlobalConstPool() : X86Test("MiscGlobalConstPool") {}
3691
add(X86TestApp & app)3692 static void add(X86TestApp& app) {
3693 app.add(new X86Test_MiscGlobalConstPool());
3694 }
3695
compile(x86::Compiler & cc)3696 virtual void compile(x86::Compiler& cc) {
3697 cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost));
3698
3699 x86::Gp v0 = cc.newInt32("v0");
3700 x86::Gp v1 = cc.newInt32("v1");
3701
3702 x86::Mem c0 = cc.newInt32Const(ConstPool::kScopeGlobal, 200);
3703 x86::Mem c1 = cc.newInt32Const(ConstPool::kScopeGlobal, 33);
3704
3705 cc.mov(v0, c0);
3706 cc.mov(v1, c1);
3707 cc.add(v0, v1);
3708
3709 cc.ret(v0);
3710 cc.endFunc();
3711 }
3712
run(void * _func,String & result,String & expect)3713 virtual bool run(void* _func, String& result, String& expect) {
3714 typedef int (*Func)(void);
3715 Func func = ptr_as_func<Func>(_func);
3716
3717 int resultRet = func();
3718 int expectRet = 233;
3719
3720 result.assignFormat("ret=%d", resultRet);
3721 expect.assignFormat("ret=%d", expectRet);
3722
3723 return resultRet == expectRet;
3724 }
3725 };
3726
3727 // ============================================================================
3728 // [X86Test_MiscMultiRet]
3729 // ============================================================================
3730
3731 struct X86Test_MiscMultiRet : public X86Test {
X86Test_MiscMultiRetX86Test_MiscMultiRet3732 X86Test_MiscMultiRet() : X86Test("MiscMultiRet") {}
3733
addX86Test_MiscMultiRet3734 static void add(X86TestApp& app) {
3735 app.add(new X86Test_MiscMultiRet());
3736 }
3737
compileX86Test_MiscMultiRet3738 virtual void compile(x86::Compiler& cc) {
3739 cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost));
3740
3741 x86::Gp op = cc.newInt32("op");
3742 x86::Gp a = cc.newInt32("a");
3743 x86::Gp b = cc.newInt32("b");
3744
3745 Label L_Zero = cc.newLabel();
3746 Label L_Add = cc.newLabel();
3747 Label L_Sub = cc.newLabel();
3748 Label L_Mul = cc.newLabel();
3749 Label L_Div = cc.newLabel();
3750
3751 cc.setArg(0, op);
3752 cc.setArg(1, a);
3753 cc.setArg(2, b);
3754
3755 cc.cmp(op, 0);
3756 cc.jz(L_Add);
3757
3758 cc.cmp(op, 1);
3759 cc.jz(L_Sub);
3760
3761 cc.cmp(op, 2);
3762 cc.jz(L_Mul);
3763
3764 cc.cmp(op, 3);
3765 cc.jz(L_Div);
3766
3767 cc.bind(L_Zero);
3768 cc.xor_(a, a);
3769 cc.ret(a);
3770
3771 cc.bind(L_Add);
3772 cc.add(a, b);
3773 cc.ret(a);
3774
3775 cc.bind(L_Sub);
3776 cc.sub(a, b);
3777 cc.ret(a);
3778
3779 cc.bind(L_Mul);
3780 cc.imul(a, b);
3781 cc.ret(a);
3782
3783 cc.bind(L_Div);
3784 cc.cmp(b, 0);
3785 cc.jz(L_Zero);
3786
3787 x86::Gp zero = cc.newInt32("zero");
3788 cc.xor_(zero, zero);
3789 cc.idiv(zero, a, b);
3790 cc.ret(a);
3791
3792 cc.endFunc();
3793 }
3794
runX86Test_MiscMultiRet3795 virtual bool run(void* _func, String& result, String& expect) {
3796 typedef int (*Func)(int, int, int);
3797
3798 Func func = ptr_as_func<Func>(_func);
3799
3800 int a = 44;
3801 int b = 3;
3802
3803 int r0 = func(0, a, b);
3804 int r1 = func(1, a, b);
3805 int r2 = func(2, a, b);
3806 int r3 = func(3, a, b);
3807 int e0 = a + b;
3808 int e1 = a - b;
3809 int e2 = a * b;
3810 int e3 = a / b;
3811
3812 result.assignFormat("ret={%d %d %d %d}", r0, r1, r2, r3);
3813 expect.assignFormat("ret={%d %d %d %d}", e0, e1, e2, e3);
3814
3815 return result.eq(expect);
3816 }
3817 };
3818
3819 // ============================================================================
3820 // [X86Test_MiscMultiFunc]
3821 // ============================================================================
3822
3823 class X86Test_MiscMultiFunc : public X86Test {
3824 public:
X86Test_MiscMultiFunc()3825 X86Test_MiscMultiFunc() : X86Test("MiscMultiFunc") {}
3826
add(X86TestApp & app)3827 static void add(X86TestApp& app) {
3828 app.add(new X86Test_MiscMultiFunc());
3829 }
3830
compile(x86::Compiler & cc)3831 virtual void compile(x86::Compiler& cc) {
3832 FuncNode* f1 = cc.newFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
3833 FuncNode* f2 = cc.newFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost));
3834
3835 {
3836 x86::Gp a = cc.newInt32("a");
3837 x86::Gp b = cc.newInt32("b");
3838
3839 cc.addFunc(f1);
3840 cc.setArg(0, a);
3841 cc.setArg(1, b);
3842
3843 FuncCallNode* call = cc.call(f2->label(), FuncSignatureT<int, int, int>(CallConv::kIdHost));
3844 call->setArg(0, a);
3845 call->setArg(1, b);
3846 call->setRet(0, a);
3847
3848 cc.ret(a);
3849 cc.endFunc();
3850 }
3851
3852 {
3853 x86::Gp a = cc.newInt32("a");
3854 x86::Gp b = cc.newInt32("b");
3855
3856 cc.addFunc(f2);
3857 cc.setArg(0, a);
3858 cc.setArg(1, b);
3859
3860 cc.add(a, b);
3861 cc.ret(a);
3862 cc.endFunc();
3863 }
3864 }
3865
run(void * _func,String & result,String & expect)3866 virtual bool run(void* _func, String& result, String& expect) {
3867 typedef int (*Func)(int, int);
3868
3869 Func func = ptr_as_func<Func>(_func);
3870
3871 int resultRet = func(56, 22);
3872 int expectRet = 56 + 22;
3873
3874 result.assignFormat("ret=%d", resultRet);
3875 expect.assignFormat("ret=%d", expectRet);
3876
3877 return result.eq(expect);
3878 }
3879 };
3880
3881 // ============================================================================
3882 // [X86Test_MiscUnfollow]
3883 // ============================================================================
3884
3885 // Global (I didn't find a better way to test this).
3886 static jmp_buf globalJmpBuf;
3887
3888 class X86Test_MiscUnfollow : public X86Test {
3889 public:
X86Test_MiscUnfollow()3890 X86Test_MiscUnfollow() : X86Test("MiscUnfollow") {}
3891
add(X86TestApp & app)3892 static void add(X86TestApp& app) {
3893 app.add(new X86Test_MiscUnfollow());
3894 }
3895
compile(x86::Compiler & cc)3896 virtual void compile(x86::Compiler& cc) {
3897 // NOTE: Fastcall calling convention is the most appropriate here, as all
3898 // arguments will be passed by registers and there won't be any stack
3899 // misalignment when we call the `handler()`. This was failing on OSX
3900 // when targeting 32-bit.
3901 cc.addFunc(FuncSignatureT<int, int, void*>(CallConv::kIdHostFastCall));
3902
3903 x86::Gp a = cc.newInt32("a");
3904 x86::Gp b = cc.newIntPtr("b");
3905 Label tramp = cc.newLabel();
3906
3907 cc.setArg(0, a);
3908 cc.setArg(1, b);
3909
3910 cc.cmp(a, 0);
3911 cc.jz(tramp);
3912
3913 cc.ret(a);
3914
3915 cc.bind(tramp);
3916 cc.unfollow().jmp(b);
3917
3918 cc.endFunc();
3919 }
3920
run(void * _func,String & result,String & expect)3921 virtual bool run(void* _func, String& result, String& expect) {
3922 typedef int (ASMJIT_FASTCALL *Func)(int, void*);
3923
3924 Func func = ptr_as_func<Func>(_func);
3925
3926 int resultRet = 0;
3927 int expectRet = 1;
3928
3929 if (!setjmp(globalJmpBuf))
3930 resultRet = func(0, (void*)handler);
3931 else
3932 resultRet = 1;
3933
3934 result.assignFormat("ret={%d}", resultRet);
3935 expect.assignFormat("ret={%d}", expectRet);
3936
3937 return resultRet == expectRet;
3938 }
3939
handler()3940 static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); }
3941 };
3942
3943 // ============================================================================
3944 // [Main]
3945 // ============================================================================
3946
main(int argc,char * argv[])3947 int main(int argc, char* argv[]) {
3948 X86TestApp app;
3949
3950 app.handleArgs(argc, argv);
3951 app.showInfo();
3952
3953 // Base tests.
3954 app.addT<X86Test_NoCode>();
3955 app.addT<X86Test_NoAlign>();
3956 app.addT<X86Test_AlignBase>();
3957
3958 // Jump tests.
3959 app.addT<X86Test_JumpMerge>();
3960 app.addT<X86Test_JumpCross>();
3961 app.addT<X86Test_JumpMany>();
3962 app.addT<X86Test_JumpUnreachable1>();
3963 app.addT<X86Test_JumpUnreachable2>();
3964
3965 // Alloc tests.
3966 app.addT<X86Test_AllocBase>();
3967 app.addT<X86Test_AllocMany1>();
3968 app.addT<X86Test_AllocMany2>();
3969 app.addT<X86Test_AllocImul1>();
3970 app.addT<X86Test_AllocImul2>();
3971 app.addT<X86Test_AllocIdiv1>();
3972 app.addT<X86Test_AllocSetz>();
3973 app.addT<X86Test_AllocShlRor>();
3974 app.addT<X86Test_AllocGpbLo1>();
3975 app.addT<X86Test_AllocGpbLo2>();
3976 app.addT<X86Test_AllocRepMovsb>();
3977 app.addT<X86Test_AllocIfElse1>();
3978 app.addT<X86Test_AllocIfElse2>();
3979 app.addT<X86Test_AllocIfElse3>();
3980 app.addT<X86Test_AllocIfElse4>();
3981 app.addT<X86Test_AllocInt8>();
3982 app.addT<X86Test_AllocUnhandledArg>();
3983 app.addT<X86Test_AllocArgsIntPtr>();
3984 app.addT<X86Test_AllocArgsFloat>();
3985 app.addT<X86Test_AllocArgsDouble>();
3986 app.addT<X86Test_AllocRetFloat1>();
3987 app.addT<X86Test_AllocRetFloat2>();
3988 app.addT<X86Test_AllocRetDouble1>();
3989 app.addT<X86Test_AllocRetDouble2>();
3990 app.addT<X86Test_AllocStack>();
3991 app.addT<X86Test_AllocMemcpy>();
3992 app.addT<X86Test_AllocExtraBlock>();
3993 app.addT<X86Test_AllocAlphaBlend>();
3994
3995 // Function call tests.
3996 app.addT<X86Test_FuncCallBase1>();
3997 app.addT<X86Test_FuncCallBase2>();
3998 app.addT<X86Test_FuncCallStd>();
3999 app.addT<X86Test_FuncCallFast>();
4000 app.addT<X86Test_FuncCallLight>();
4001 app.addT<X86Test_FuncCallManyArgs>();
4002 app.addT<X86Test_FuncCallDuplicateArgs>();
4003 app.addT<X86Test_FuncCallImmArgs>();
4004 app.addT<X86Test_FuncCallPtrArgs>();
4005 app.addT<X86Test_FuncCallRefArgs>();
4006 app.addT<X86Test_FuncCallFloatAsXmmRet>();
4007 app.addT<X86Test_FuncCallDoubleAsXmmRet>();
4008 app.addT<X86Test_FuncCallConditional>();
4009 app.addT<X86Test_FuncCallMultiple>();
4010 app.addT<X86Test_FuncCallRecursive>();
4011 app.addT<X86Test_FuncCallVarArg1>();
4012 app.addT<X86Test_FuncCallVarArg2>();
4013 app.addT<X86Test_FuncCallMisc1>();
4014 app.addT<X86Test_FuncCallMisc2>();
4015 app.addT<X86Test_FuncCallMisc3>();
4016 app.addT<X86Test_FuncCallMisc4>();
4017 app.addT<X86Test_FuncCallMisc5>();
4018
4019 // Miscellaneous tests.
4020 app.addT<X86Test_MiscLocalConstPool>();
4021 app.addT<X86Test_MiscGlobalConstPool>();
4022 app.addT<X86Test_MiscMultiRet>();
4023 app.addT<X86Test_MiscMultiFunc>();
4024 app.addT<X86Test_MiscUnfollow>();
4025
4026 return app.run();
4027 }
4028