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