odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

asmjit_test_compiler_x86.cpp (124653B)


      1 // This file is part of AsmJit project <https://asmjit.com>
      2 //
      3 // See <asmjit/core.h> or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #include <asmjit/core.h>
      7 #if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_COMPILER)
      8 
      9 #include <asmjit/x86.h>
     10 #include <setjmp.h>
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <string.h>
     14 
     15 #if ASMJIT_ARCH_X86
     16   // Required for function tests that pass / return XMM registers.
     17   #include <emmintrin.h>
     18 #endif
     19 
     20 #include "asmjit_test_misc.h"
     21 #include "asmjit_test_compiler.h"
     22 
     23 #ifdef _MSC_VER
     24 // Interaction between '_setjmp' and C++ object destruction is non-portable.
     25 #pragma warning(disable: 4611)
     26 #endif
     27 
     28 using namespace asmjit;
     29 
     30 // x86::Compiler - X86TestCase
     31 // ===========================
     32 
     33 class X86TestCase : public TestCase {
     34 public:
     35   X86TestCase(const char* name = nullptr)
     36     : TestCase(name, Arch::kHost == Arch::kX86 ? Arch::kX86 : Arch::kX64) {}
     37 
     38   void compile(BaseCompiler& cc) override {
     39     compile(static_cast<x86::Compiler&>(cc));
     40   }
     41 
     42   virtual void compile(x86::Compiler& cc) = 0;
     43 };
     44 
     45 // x86::Compiler - X86Test_AlignBase
     46 // =================================
     47 
     48 class X86Test_AlignBase : public X86TestCase {
     49 public:
     50   X86Test_AlignBase(uint32_t arg_count, uint32_t alignment, bool preserve_fp)
     51     : _arg_count(arg_count),
     52       _alignment(alignment),
     53       _preserve_fp(preserve_fp) {
     54     _name.assign_format("AlignBase {NumArgs=%u Alignment=%u PreserveFP=%c}", arg_count, alignment, preserve_fp ? 'Y' : 'N');
     55   }
     56 
     57   static void add(TestApp& app) {
     58     for (uint32_t i = 0; i <= 16; i++) {
     59       for (uint32_t a = 16; a <= 32; a += 16) {
     60         app.add(new X86Test_AlignBase(i, a, true));
     61         app.add(new X86Test_AlignBase(i, a, false));
     62       }
     63     }
     64   }
     65 
     66   void compile(x86::Compiler& cc) override {
     67     uint32_t arg_count = _arg_count;
     68 
     69     FuncSignature signature(CallConvId::kCDecl);
     70     signature.set_ret_t<int>();
     71     for (uint32_t i = 0; i < arg_count; i++) {
     72       signature.add_arg_t<int>();
     73     }
     74 
     75     FuncNode* func_node = cc.add_func(signature);
     76     if (_preserve_fp)
     77       func_node->frame().set_preserved_fp();
     78 
     79     x86::Gp gp_var = cc.new_gp_ptr("gp_var");
     80     x86::Gp gp_sum;
     81     x86::Mem stack = cc.new_stack(_alignment, _alignment);
     82 
     83     // Do a sum of arguments to verify a possible relocation when misaligned.
     84     if (arg_count) {
     85       for (uint32_t i = 0; i < arg_count; i++) {
     86         x86::Gp gp_arg = cc.new_gp32("gp_arg%u", i);
     87         func_node->set_arg(i, gp_arg);
     88 
     89         if (i == 0)
     90           gp_sum = gp_arg;
     91         else
     92           cc.add(gp_sum, gp_arg);
     93       }
     94     }
     95 
     96     // Check alignment of the stack (has to be 16).
     97     cc.lea(gp_var, stack);
     98     cc.and_(gp_var, _alignment - 1);
     99 
    100     // Add a sum of all arguments to check if they are correct.
    101     if (arg_count)
    102       cc.or_(gp_var.r32(), gp_sum);
    103 
    104     cc.ret(gp_var);
    105     cc.end_func();
    106   }
    107 
    108   bool run(void* _func, String& result, String& expect) override {
    109     using U = unsigned int;
    110 
    111     using Func0 = U (*)();
    112     using Func1 = U (*)(U);
    113     using Func2 = U (*)(U, U);
    114     using Func3 = U (*)(U, U, U);
    115     using Func4 = U (*)(U, U, U, U);
    116     using Func5 = U (*)(U, U, U, U, U);
    117     using Func6 = U (*)(U, U, U, U, U, U);
    118     using Func7 = U (*)(U, U, U, U, U, U, U);
    119     using Func8 = U (*)(U, U, U, U, U, U, U, U);
    120     using Func9 = U (*)(U, U, U, U, U, U, U, U, U);
    121     using Func10 = U (*)(U, U, U, U, U, U, U, U, U, U);
    122     using Func11 = U (*)(U, U, U, U, U, U, U, U, U, U, U);
    123     using Func12 = U (*)(U, U, U, U, U, U, U, U, U, U, U, U);
    124     using Func13 = U (*)(U, U, U, U, U, U, U, U, U, U, U, U, U);
    125     using Func14 = U (*)(U, U, U, U, U, U, U, U, U, U, U, U, U, U);
    126     using Func15 = U (*)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
    127     using Func16 = U (*)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
    128 
    129     unsigned int result_ret = 0;
    130     unsigned int expect_ret = 0;
    131 
    132     switch (_arg_count) {
    133       case 0:
    134         result_ret = ptr_as_func<Func0>(_func)();
    135         expect_ret = 0;
    136         break;
    137       case 1:
    138         result_ret = ptr_as_func<Func1>(_func)(1);
    139         expect_ret = 1;
    140         break;
    141       case 2:
    142         result_ret = ptr_as_func<Func2>(_func)(1, 2);
    143         expect_ret = 1 + 2;
    144         break;
    145       case 3:
    146         result_ret = ptr_as_func<Func3>(_func)(1, 2, 3);
    147         expect_ret = 1 + 2 + 3;
    148         break;
    149       case 4:
    150         result_ret = ptr_as_func<Func4>(_func)(1, 2, 3, 4);
    151         expect_ret = 1 + 2 + 3 + 4;
    152         break;
    153       case 5:
    154         result_ret = ptr_as_func<Func5>(_func)(1, 2, 3, 4, 5);
    155         expect_ret = 1 + 2 + 3 + 4 + 5;
    156         break;
    157       case 6:
    158         result_ret = ptr_as_func<Func6>(_func)(1, 2, 3, 4, 5, 6);
    159         expect_ret = 1 + 2 + 3 + 4 + 5 + 6;
    160         break;
    161       case 7:
    162         result_ret = ptr_as_func<Func7>(_func)(1, 2, 3, 4, 5, 6, 7);
    163         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7;
    164         break;
    165       case 8:
    166         result_ret = ptr_as_func<Func8>(_func)(1, 2, 3, 4, 5, 6, 7, 8);
    167         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8;
    168         break;
    169       case 9:
    170         result_ret = ptr_as_func<Func9>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9);
    171         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9;
    172         break;
    173       case 10:
    174         result_ret = ptr_as_func<Func10>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    175         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
    176         break;
    177       case 11:
    178         result_ret = ptr_as_func<Func11>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
    179         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
    180         break;
    181       case 12:
    182         result_ret = ptr_as_func<Func12>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
    183         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
    184         break;
    185       case 13:
    186         result_ret = ptr_as_func<Func13>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
    187         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13;
    188         break;
    189       case 14:
    190         result_ret = ptr_as_func<Func14>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
    191         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14;
    192         break;
    193       case 15:
    194         result_ret = ptr_as_func<Func15>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
    195         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15;
    196         break;
    197       case 16:
    198         result_ret = ptr_as_func<Func16>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    199         expect_ret = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
    200         break;
    201     }
    202 
    203     result.assign_format("ret={%u, %u}", result_ret >> 28, result_ret & 0x0FFFFFFFu);
    204     expect.assign_format("ret={%u, %u}", expect_ret >> 28, expect_ret & 0x0FFFFFFFu);
    205 
    206     return result == expect;
    207   }
    208 
    209   uint32_t _arg_count;
    210   uint32_t _alignment;
    211   bool _preserve_fp;
    212 };
    213 
    214 // x86::Compiler - X86Test_NoCode
    215 // ==============================
    216 
    217 class X86Test_NoCode : public X86TestCase {
    218 public:
    219   X86Test_NoCode() : X86TestCase("NoCode") {}
    220 
    221   static void add(TestApp& app) {
    222     app.add(new X86Test_NoCode());
    223   }
    224 
    225   void compile(x86::Compiler& cc) override {
    226     cc.add_func(FuncSignature::build<void>());
    227     cc.end_func();
    228   }
    229 
    230   bool run(void* _func, String& result, String& expect) override {
    231     Support::maybe_unused(result, expect);
    232 
    233     using Func = void (*)(void);
    234     Func func = ptr_as_func<Func>(_func);
    235 
    236     func();
    237     return true;
    238   }
    239 };
    240 
    241 // x86::Compiler - X86Test_NoAlign
    242 // ===============================
    243 
    244 class X86Test_NoAlign : public X86TestCase {
    245 public:
    246   X86Test_NoAlign() : X86TestCase("NoAlign") {}
    247 
    248   static void add(TestApp& app) {
    249     app.add(new X86Test_NoAlign());
    250   }
    251 
    252   void compile(x86::Compiler& cc) override {
    253     cc.add_func(FuncSignature::build<void>());
    254     cc.align(AlignMode::kCode, 0);
    255     cc.align(AlignMode::kCode, 1);
    256     cc.end_func();
    257   }
    258 
    259   bool run(void* _func, String& result, String& expect) override {
    260     Support::maybe_unused(result, expect);
    261 
    262     using Func = void (*)(void);
    263     Func func = ptr_as_func<Func>(_func);
    264 
    265     func();
    266     return true;
    267   }
    268 };
    269 
    270 // x86::Compiler - X86Test_IndirectBranchProtection
    271 // ================================================
    272 
    273 class X86Test_IndirectBranchProtection : public X86TestCase {
    274 public:
    275   X86Test_IndirectBranchProtection() : X86TestCase("IndirectBranchProtection") {}
    276 
    277   static void add(TestApp& app) {
    278     app.add(new X86Test_IndirectBranchProtection());
    279   }
    280 
    281   void compile(x86::Compiler& cc) override {
    282     FuncNode* func = cc.add_func(FuncSignature::build<void>());
    283     func->add_attributes(FuncAttributes::kIndirectBranchProtection);
    284     cc.end_func();
    285   }
    286 
    287   bool run(void* _func, String& result, String& expect) override {
    288     Support::maybe_unused(result, expect);
    289 
    290     using Func = void (*)(void);
    291     Func func = ptr_as_func<Func>(_func);
    292 
    293     func();
    294     return true;
    295   }
    296 };
    297 
    298 
    299 // x86::Compiler - X86Test_JumpMerge
    300 // =================================
    301 
    302 class X86Test_JumpMerge : public X86TestCase {
    303 public:
    304   X86Test_JumpMerge() : X86TestCase("JumpMerge") {}
    305 
    306   static void add(TestApp& app) {
    307     app.add(new X86Test_JumpMerge());
    308   }
    309 
    310   void compile(x86::Compiler& cc) override {
    311     Label L0 = cc.new_label();
    312     Label L1 = cc.new_label();
    313     Label L2 = cc.new_label();
    314     Label LEnd = cc.new_label();
    315 
    316     x86::Gp dst = cc.new_gp_ptr("dst");
    317     x86::Gp val = cc.new_gp32("val");
    318 
    319     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int*, int>());
    320     func_node->set_arg(0, dst);
    321     func_node->set_arg(1, val);
    322 
    323     cc.cmp(val, 0);
    324     cc.je(L2);
    325 
    326     cc.cmp(val, 1);
    327     cc.je(L1);
    328 
    329     cc.cmp(val, 2);
    330     cc.je(L0);
    331 
    332     cc.mov(x86::dword_ptr(dst), val);
    333     cc.jmp(LEnd);
    334 
    335     // On purpose. This tests whether the CFG constructs a single basic-block
    336     // from multiple labels next to each other.
    337     cc.bind(L0);
    338     cc.bind(L1);
    339     cc.bind(L2);
    340     cc.mov(x86::dword_ptr(dst), 0);
    341 
    342     cc.bind(LEnd);
    343     cc.end_func();
    344   }
    345 
    346   bool run(void* _func, String& result, String& expect) override {
    347     using Func = void (*)(int*, int);
    348     Func func = ptr_as_func<Func>(_func);
    349 
    350     int arr[5] = { -1, -1, -1, -1, -1 };
    351     int exp[5] = {  0,  0,  0,  3,  4 };
    352 
    353     for (int i = 0; i < 5; i++)
    354       func(&arr[i], i);
    355 
    356     result.assign_format("ret={%d, %d, %d, %d, %d}", arr[0], arr[1], arr[2], arr[3], arr[4]);
    357     expect.assign_format("ret={%d, %d, %d, %d, %d}", exp[0], exp[1], exp[2], exp[3], exp[4]);
    358 
    359     return result == expect;
    360   }
    361 };
    362 
    363 // x86::Compiler - X86Test_JumpCross
    364 // =================================
    365 
    366 class X86Test_JumpCross : public X86TestCase {
    367 public:
    368   X86Test_JumpCross() : X86TestCase("JumpCross") {}
    369 
    370   static void add(TestApp& app) {
    371     app.add(new X86Test_JumpCross());
    372   }
    373 
    374   void compile(x86::Compiler& cc) override {
    375     cc.add_func(FuncSignature::build<void>());
    376 
    377     Label L1 = cc.new_label();
    378     Label L2 = cc.new_label();
    379     Label L3 = cc.new_label();
    380 
    381     cc.jmp(L2);
    382 
    383     cc.bind(L1);
    384     cc.jmp(L3);
    385 
    386     cc.bind(L2);
    387     cc.jmp(L1);
    388 
    389     cc.bind(L3);
    390     cc.end_func();
    391   }
    392 
    393   bool run(void* _func, String& result, String& expect) override {
    394     Support::maybe_unused(result, expect);
    395 
    396     using Func = void (*)(void);
    397     Func func = ptr_as_func<Func>(_func);
    398 
    399     func();
    400     return true;
    401   }
    402 };
    403 
    404 // x86::Compiler - X86Test_JumpMany
    405 // ================================
    406 
    407 class X86Test_JumpMany : public X86TestCase {
    408 public:
    409   X86Test_JumpMany() : X86TestCase("JumpMany") {}
    410 
    411   static void add(TestApp& app) {
    412     app.add(new X86Test_JumpMany());
    413   }
    414 
    415   void compile(x86::Compiler& cc) override {
    416     cc.add_func(FuncSignature::build<int>());
    417     for (uint32_t i = 0; i < 1000; i++) {
    418       Label L = cc.new_label();
    419       cc.jmp(L);
    420       cc.bind(L);
    421     }
    422 
    423     x86::Gp ret = cc.new_gp32("ret");
    424     cc.xor_(ret, ret);
    425     cc.ret(ret);
    426     cc.end_func();
    427   }
    428 
    429   bool run(void* _func, String& result, String& expect) override {
    430     using Func = int (*)(void);
    431 
    432     Func func = ptr_as_func<Func>(_func);
    433 
    434     int result_ret = func();
    435     int expect_ret = 0;
    436 
    437     result.assign_format("ret={%d}", result_ret);
    438     expect.assign_format("ret={%d}", expect_ret);
    439 
    440     return result == expect;
    441   }
    442 };
    443 
    444 // x86::Compiler - X86Test_JumpUnreachable1
    445 // ========================================
    446 
    447 class X86Test_JumpUnreachable1 : public X86TestCase {
    448 public:
    449   X86Test_JumpUnreachable1() : X86TestCase("JumpUnreachable1") {}
    450 
    451   static void add(TestApp& app) {
    452     app.add(new X86Test_JumpUnreachable1());
    453   }
    454 
    455   void compile(x86::Compiler& cc) override {
    456     cc.add_func(FuncSignature::build<void>());
    457 
    458     Label L_1 = cc.new_label();
    459     Label L_2 = cc.new_label();
    460     Label L_3 = cc.new_label();
    461     Label L_4 = cc.new_label();
    462     Label L_5 = cc.new_label();
    463     Label L_6 = cc.new_label();
    464     Label L_7 = cc.new_label();
    465 
    466     x86::Gp v0 = cc.new_gp32("v0");
    467     x86::Gp v1 = cc.new_gp32("v1");
    468 
    469     cc.bind(L_2);
    470     cc.bind(L_3);
    471 
    472     cc.jmp(L_1);
    473 
    474     cc.bind(L_5);
    475     cc.mov(v0, 0);
    476 
    477     cc.bind(L_6);
    478     cc.jmp(L_3);
    479     cc.mov(v1, 1);
    480     cc.jmp(L_1);
    481 
    482     cc.bind(L_4);
    483     cc.jmp(L_2);
    484     cc.bind(L_7);
    485     cc.add(v0, v1);
    486 
    487     cc.align(AlignMode::kCode, 16);
    488     cc.bind(L_1);
    489     cc.ret();
    490     cc.end_func();
    491   }
    492 
    493   bool run(void* _func, String& result, String& expect) override {
    494     using Func = void (*)(void);
    495     Func func = ptr_as_func<Func>(_func);
    496 
    497     func();
    498 
    499     result.append("ret={}");
    500     expect.append("ret={}");
    501 
    502     return true;
    503   }
    504 };
    505 
    506 // x86::Compiler - X86Test_JumpUnreachable2
    507 // ========================================
    508 
    509 class X86Test_JumpUnreachable2 : public X86TestCase {
    510 public:
    511   X86Test_JumpUnreachable2() : X86TestCase("JumpUnreachable2") {}
    512 
    513   static void add(TestApp& app) {
    514     app.add(new X86Test_JumpUnreachable2());
    515   }
    516 
    517   void compile(x86::Compiler& cc) override {
    518     cc.add_func(FuncSignature::build<void>());
    519 
    520     Label L_1 = cc.new_label();
    521     Label L_2 = cc.new_label();
    522 
    523     x86::Gp v0 = cc.new_gp32("v0");
    524     x86::Gp v1 = cc.new_gp32("v1");
    525 
    526     cc.jmp(L_1);
    527     cc.bind(L_2);
    528     cc.mov(v0, 1);
    529     cc.mov(v1, 2);
    530     cc.cmp(v0, v1);
    531     cc.jz(L_2);
    532     cc.jmp(L_1);
    533 
    534     cc.bind(L_1);
    535     cc.ret();
    536     cc.end_func();
    537   }
    538 
    539   bool run(void* _func, String& result, String& expect) override {
    540     using Func = void (*)(void);
    541     Func func = ptr_as_func<Func>(_func);
    542 
    543     func();
    544 
    545     result.append("ret={}");
    546     expect.append("ret={}");
    547 
    548     return true;
    549   }
    550 };
    551 
    552 // x86::Compiler - X86Test_JumpTable1
    553 // ==================================
    554 
    555 class X86Test_JumpTable1 : public X86TestCase {
    556 public:
    557   bool _annotated;
    558 
    559   X86Test_JumpTable1(bool annotated)
    560     : X86TestCase("X86Test_JumpTable1"),
    561       _annotated(annotated) {
    562     _name.assign_format("JumpTable {%s}", annotated ? "Annotated" : "Unknown Reg/Mem");
    563   }
    564 
    565   enum Operator {
    566     kOperatorAdd = 0,
    567     kOperatorSub = 1,
    568     kOperatorMul = 2,
    569     kOperatorDiv = 3
    570   };
    571 
    572   static void add(TestApp& app) {
    573     app.add(new X86Test_JumpTable1(false));
    574     app.add(new X86Test_JumpTable1(true));
    575   }
    576 
    577   void compile(x86::Compiler& cc) override {
    578     x86::Vec a = cc.new_xmm_ss("a");
    579     x86::Vec b = cc.new_xmm_ss("b");
    580     x86::Gp op = cc.new_gp32("op");
    581     x86::Gp target = cc.new_gp_ptr("target");
    582     x86::Gp offset = cc.new_gp_ptr("offset");
    583 
    584     Label L_Table = cc.new_label();
    585     Label L_Add = cc.new_label();
    586     Label L_Sub = cc.new_label();
    587     Label L_Mul = cc.new_label();
    588     Label L_Div = cc.new_label();
    589     Label L_End = cc.new_label();
    590 
    591     FuncNode* func_node = cc.add_func(FuncSignature::build<float, float, float, uint32_t>());
    592     func_node->set_arg(0, a);
    593     func_node->set_arg(1, b);
    594     func_node->set_arg(2, op);
    595 
    596     cc.lea(offset, x86::ptr(L_Table));
    597     if (cc.is_64bit())
    598       cc.movsxd(target, x86::dword_ptr(offset, op.clone_as(offset), 2));
    599     else
    600       cc.mov(target, x86::dword_ptr(offset, op.clone_as(offset), 2));
    601     cc.add(target, offset);
    602 
    603     // JumpAnnotation allows to annotate all possible jump targets of
    604     // instructions where it cannot be deduced from operands.
    605     if (_annotated) {
    606       JumpAnnotation* annotation = cc.new_jump_annotation();
    607       annotation->add_label(L_Add);
    608       annotation->add_label(L_Sub);
    609       annotation->add_label(L_Mul);
    610       annotation->add_label(L_Div);
    611       cc.jmp(target, annotation);
    612     }
    613     else {
    614       cc.jmp(target);
    615     }
    616 
    617     cc.bind(L_Add);
    618     cc.addss(a, b);
    619     cc.jmp(L_End);
    620 
    621     cc.bind(L_Sub);
    622     cc.subss(a, b);
    623     cc.jmp(L_End);
    624 
    625     cc.bind(L_Mul);
    626     cc.mulss(a, b);
    627     cc.jmp(L_End);
    628 
    629     cc.bind(L_Div);
    630     cc.divss(a, b);
    631 
    632     cc.bind(L_End);
    633     cc.ret(a);
    634 
    635     cc.end_func();
    636 
    637     cc.bind(L_Table);
    638     cc.embed_label_delta(L_Add, L_Table, 4);
    639     cc.embed_label_delta(L_Sub, L_Table, 4);
    640     cc.embed_label_delta(L_Mul, L_Table, 4);
    641     cc.embed_label_delta(L_Div, L_Table, 4);
    642   }
    643 
    644   bool run(void* _func, String& result, String& expect) override {
    645     using Func = float (*)(float, float, uint32_t);
    646     Func func = ptr_as_func<Func>(_func);
    647 
    648     float results[4];
    649     float expected[4];
    650 
    651     results[0] = func(33.0f, 14.0f, kOperatorAdd);
    652     results[1] = func(33.0f, 14.0f, kOperatorSub);
    653     results[2] = func(10.0f, 6.0f, kOperatorMul);
    654     results[3] = func(80.0f, 8.0f, kOperatorDiv);
    655 
    656     expected[0] = 47.0f;
    657     expected[1] = 19.0f;
    658     expected[2] = 60.0f;
    659     expected[3] = 10.0f;
    660 
    661     result.assign_format("ret={%f, %f, %f, %f}", double(results[0]), double(results[1]), double(results[2]), double(results[3]));
    662     expect.assign_format("ret={%f, %f, %f, %f}", double(expected[0]), double(expected[1]), double(expected[2]), double(expected[3]));
    663 
    664     return result == expect;
    665   }
    666 };
    667 
    668 // x86::Compiler - X86Test_JumpTable2
    669 // ==================================
    670 
    671 class X86Test_JumpTable2 : public X86TestCase {
    672 public:
    673   X86Test_JumpTable2()
    674     : X86TestCase("JumpTable {Jumping to Begin}") {}
    675 
    676   static void add(TestApp& app) {
    677     app.add(new X86Test_JumpTable2());
    678   }
    679 
    680   void compile(x86::Compiler& cc) override {
    681     x86::Gp result = cc.new_gp32("result");
    682     x86::Gp value = cc.new_gp32("value");
    683     x86::Gp target = cc.new_gp_ptr("target");
    684     x86::Gp offset = cc.new_gp_ptr("offset");
    685 
    686     Label L_Table = cc.new_label();
    687     Label L_Begin = cc.new_label();
    688     Label L_Case0 = cc.new_label();
    689     Label L_Case1 = cc.new_label();
    690     Label L_End = cc.new_label();
    691 
    692     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int>());
    693     func_node->set_arg(0, value);
    694 
    695     cc.bind(L_Begin);
    696     cc.lea(offset, x86::ptr(L_Table));
    697     if (cc.is_64bit())
    698       cc.movsxd(target, x86::dword_ptr(offset, value.clone_as(offset), 2));
    699     else
    700       cc.mov(target, x86::dword_ptr(offset, value.clone_as(offset), 2));
    701     cc.add(target, offset);
    702 
    703     {
    704       JumpAnnotation* annotation = cc.new_jump_annotation();
    705       annotation->add_label(L_Case0);
    706       annotation->add_label(L_Case1);
    707       annotation->add_label(L_Begin); // Never used, just for the purpose of the test.
    708       cc.jmp(target, annotation);
    709 
    710       cc.bind(L_Case0);
    711       cc.mov(result, 0);
    712       cc.jmp(L_End);
    713 
    714       cc.bind(L_Case1);
    715       cc.mov(result, 1);
    716       cc.jmp(L_End);
    717     }
    718 
    719     cc.bind(L_End);
    720     cc.ret(result);
    721 
    722     cc.end_func();
    723 
    724     cc.bind(L_Table);
    725     cc.embed_label_delta(L_Case0, L_Table, 4);
    726     cc.embed_label_delta(L_Case1, L_Table, 4);
    727   }
    728 
    729   bool run(void* _func, String& result, String& expect) override {
    730     using Func = int (*)(int);
    731     Func func = ptr_as_func<Func>(_func);
    732 
    733     int results[2];
    734     int expected[2];
    735 
    736     results[0] = func(0);
    737     results[1] = func(1);
    738 
    739     expected[0] = 0;
    740     expected[1] = 1;
    741 
    742     result.assign_format("ret={%d, %d}", results[0], results[1]);
    743     expect.assign_format("ret={%d, %d}", expected[0], expected[1]);
    744 
    745     return result == expect;
    746   }
    747 };
    748 
    749 // x86::Compiler - X86Test_JumpTable3
    750 // ==================================
    751 
    752 class X86Test_JumpTable3 : public X86TestCase {
    753 public:
    754   X86Test_JumpTable3()
    755     : X86TestCase("JumpTable {Jumping to a single label}") {}
    756 
    757   static void add(TestApp& app) {
    758     app.add(new X86Test_JumpTable3());
    759   }
    760 
    761   void compile(x86::Compiler& cc) override {
    762     cc.add_func(FuncSignature::build<int>());
    763 
    764     Label L_Target = cc.new_label();
    765     x86::Gp target = cc.new_gp_ptr("target");
    766     x86::Gp result = cc.new_gp32("result");
    767 
    768     JumpAnnotation* annotation = cc.new_jump_annotation();
    769     annotation->add_label(L_Target);
    770 
    771     cc.lea(target, x86::ptr(L_Target));
    772     cc.jmp(target, annotation);
    773 
    774     cc.bind(L_Target);
    775     cc.mov(result, 1234);
    776     cc.ret(result);
    777     cc.end_func();
    778   }
    779 
    780   bool run(void* _func, String& result, String& expect) override {
    781     using Func = int (*)(void);
    782     Func func = ptr_as_func<Func>(_func);
    783 
    784     int out = func();
    785     int expected = 1234;
    786 
    787     result.assign_format("ret=%d", out);
    788     expect.assign_format("ret=%d", expected);
    789 
    790     return result == expect;
    791   }
    792 };
    793 
    794 // x86::Compiler - X86Test_JumpTable4
    795 // ==================================
    796 
    797 class X86Test_JumpTable4 : public X86TestCase {
    798 public:
    799   X86Test_JumpTable4()
    800     : X86TestCase("JumpTable {Jumping to a single label and multiple labels}") {}
    801 
    802   static void add(TestApp& app) {
    803     app.add(new X86Test_JumpTable4());
    804   }
    805 
    806   void compile(x86::Compiler& cc) override {
    807     x86::Gp result = cc.new_gp32("result");
    808     x86::Gp condition = cc.new_gp32("condition");
    809 
    810     FuncNode* func = cc.add_func(FuncSignature::build<int, int>());
    811     func->set_arg(0, condition);
    812 
    813     Label L_NonZero = cc.new_label();
    814     cc.test(condition, condition);
    815     cc.jnz(L_NonZero);
    816 
    817     {
    818       JumpAnnotation* annotation = cc.new_jump_annotation();
    819       Label L_Target = cc.new_label();
    820       annotation->add_label(L_Target);
    821 
    822       x86::Gp target = cc.new_gp_ptr("target");
    823       cc.lea(target, x86::ptr(L_Target));
    824       cc.jmp(target, annotation);
    825       cc.bind(L_Target);
    826       cc.mov(result, 1234);
    827       cc.ret(result);
    828     }
    829 
    830     {
    831       JumpAnnotation* annotation = cc.new_jump_annotation();
    832       Label L_Target1 = cc.new_label();
    833       Label L_Target2 = cc.new_label();
    834       annotation->add_label(L_Target1);
    835       annotation->add_label(L_Target2);
    836 
    837       cc.bind(L_NonZero);
    838       x86::Gp target = cc.new_gp_ptr("target");
    839       cc.lea(target, x86::ptr(L_Target1));
    840       cc.jmp(target, annotation);
    841 
    842       cc.bind(L_Target1);
    843       cc.mov(result, 4321);
    844       cc.ret(result);
    845 
    846       // Never executed.
    847       cc.bind(L_Target2);
    848       cc.mov(result, 0);
    849       cc.ret(result);
    850     }
    851 
    852     cc.end_func();
    853   }
    854 
    855   bool run(void* _func, String& result, String& expect) override {
    856     using Func = int (*)(int);
    857     Func func = ptr_as_func<Func>(_func);
    858 
    859     int results[2] = { func(0), func(1) };
    860     int expected[2] = { 1234, 4321 };
    861 
    862     result.assign_format("ret={%d, %d}", results[0], results[1]);
    863     expect.assign_format("ret={%d, %d}", expected[0], expected[1]);
    864 
    865     return result == expect;
    866   }
    867 };
    868 
    869 // x86::Compiler - X86Test_AllocBase
    870 // =================================
    871 
    872 class X86Test_AllocBase : public X86TestCase {
    873 public:
    874   X86Test_AllocBase() : X86TestCase("AllocBase") {}
    875 
    876   static void add(TestApp& app) {
    877     app.add(new X86Test_AllocBase());
    878   }
    879 
    880   void compile(x86::Compiler& cc) override {
    881     cc.add_func(FuncSignature::build<int>());
    882 
    883     x86::Gp v0 = cc.new_gp32("v0");
    884     x86::Gp v1 = cc.new_gp32("v1");
    885     x86::Gp v2 = cc.new_gp32("v2");
    886     x86::Gp v3 = cc.new_gp32("v3");
    887     x86::Gp v4 = cc.new_gp32("v4");
    888 
    889     cc.xor_(v0, v0);
    890 
    891     cc.mov(v1, 1);
    892     cc.mov(v2, 2);
    893     cc.mov(v3, 3);
    894     cc.mov(v4, 4);
    895 
    896     cc.add(v0, v1);
    897     cc.add(v0, v2);
    898     cc.add(v0, v3);
    899     cc.add(v0, v4);
    900 
    901     cc.ret(v0);
    902     cc.end_func();
    903   }
    904 
    905   bool run(void* _func, String& result, String& expect) override {
    906     using Func = int (*)(void);
    907     Func func = ptr_as_func<Func>(_func);
    908 
    909     int result_ret = func();
    910     int expect_ret = 1 + 2 + 3 + 4;
    911 
    912     result.assign_format("ret=%d", result_ret);
    913     expect.assign_format("ret=%d", expect_ret);
    914 
    915     return result == expect;
    916   }
    917 };
    918 
    919 // x86::Compiler - X86Test_AllocMany1
    920 // ==================================
    921 
    922 class X86Test_AllocMany1 : public X86TestCase {
    923 public:
    924   X86Test_AllocMany1() : X86TestCase("AllocMany1") {}
    925 
    926   static inline constexpr uint32_t kCount = 8;
    927 
    928   static void add(TestApp& app) {
    929     app.add(new X86Test_AllocMany1());
    930   }
    931 
    932   void compile(x86::Compiler& cc) override {
    933     x86::Gp a0 = cc.new_gp_ptr("a0");
    934     x86::Gp a1 = cc.new_gp_ptr("a1");
    935 
    936     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int*, int*>());
    937     func_node->set_arg(0, a0);
    938     func_node->set_arg(1, a1);
    939 
    940     // Create some variables.
    941     x86::Gp t = cc.new_gp32("t");
    942     x86::Gp x[kCount];
    943 
    944     uint32_t i;
    945 
    946     // Setup variables (use mov with reg/imm to se if register allocator works).
    947     for (i = 0; i < kCount; i++) x[i] = cc.new_gp32("x%u", i);
    948     for (i = 0; i < kCount; i++) cc.mov(x[i], int(i + 1));
    949 
    950     // Make sum (addition).
    951     cc.xor_(t, t);
    952     for (i = 0; i < kCount; i++) cc.add(t, x[i]);
    953 
    954     // Store result to a given pointer in first argument.
    955     cc.mov(x86::dword_ptr(a0), t);
    956 
    957     // Clear t.
    958     cc.xor_(t, t);
    959 
    960     // Make sum (subtraction).
    961     for (i = 0; i < kCount; i++) cc.sub(t, x[i]);
    962 
    963     // Store result to a given pointer in second argument.
    964     cc.mov(x86::dword_ptr(a1), t);
    965 
    966     // End of function.
    967     cc.end_func();
    968   }
    969 
    970   bool run(void* _func, String& result, String& expect) override {
    971     using Func = void (*)(int*, int*);
    972     Func func = ptr_as_func<Func>(_func);
    973 
    974     int result_x = 0;
    975     int result_y = 0;
    976 
    977     int expect_x =  36;
    978     int expect_y = -36;
    979 
    980     func(&result_x, &result_y);
    981 
    982     result.assign_format("ret={x=%d, y=%d}", result_x, result_y);
    983     expect.assign_format("ret={x=%d, y=%d}", expect_x, expect_y);
    984 
    985     return result_x == expect_x && result_y == expect_y;
    986   }
    987 };
    988 
    989 // x86::Compiler - X86Test_AllocMany2
    990 // ==================================
    991 
    992 class X86Test_AllocMany2 : public X86TestCase {
    993 public:
    994   X86Test_AllocMany2() : X86TestCase("AllocMany2") {}
    995 
    996   static void add(TestApp& app) {
    997     app.add(new X86Test_AllocMany2());
    998   }
    999 
   1000   void compile(x86::Compiler& cc) override {
   1001     x86::Gp a = cc.new_gp_ptr("a");
   1002     x86::Gp v[32];
   1003 
   1004     FuncNode* func_node = cc.add_func(FuncSignature::build<void, uint32_t*>());
   1005     func_node->set_arg(0, a);
   1006 
   1007     for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.new_gp32("v%d", i);
   1008     for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]);
   1009 
   1010     x86::Gp x = cc.new_gp32("x");
   1011     Label L = cc.new_label();
   1012 
   1013     cc.mov(x, 32);
   1014     cc.bind(L);
   1015     for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i);
   1016 
   1017     cc.dec(x);
   1018     cc.jnz(L);
   1019     for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]);
   1020 
   1021     cc.end_func();
   1022   }
   1023 
   1024   bool run(void* _func, String& result, String& expect) override {
   1025     using Func = void (*)(uint32_t*);
   1026     Func func = ptr_as_func<Func>(_func);
   1027 
   1028     uint32_t i;
   1029     uint32_t result_buf[32] {};
   1030     uint32_t expect_buf[32] {};
   1031 
   1032     for (i = 0; i < ASMJIT_ARRAY_SIZE(result_buf); i++)
   1033       expect_buf[i] = i * 32;
   1034     func(result_buf);
   1035 
   1036     for (i = 0; i < ASMJIT_ARRAY_SIZE(result_buf); i++) {
   1037       if (i != 0) {
   1038         result.append(',');
   1039         expect.append(',');
   1040       }
   1041 
   1042       result.append_format("%u", result_buf[i]);
   1043       expect.append_format("%u", expect_buf[i]);
   1044     }
   1045 
   1046     return result == expect;
   1047   }
   1048 };
   1049 
   1050 // x86::Compiler - X86Test_AllocInt8
   1051 // =================================
   1052 
   1053 class X86Test_AllocInt8 : public X86TestCase {
   1054 public:
   1055   X86Test_AllocInt8() : X86TestCase("AllocInt8") {}
   1056 
   1057   static void add(TestApp& app) {
   1058     app.add(new X86Test_AllocInt8());
   1059   }
   1060 
   1061   void compile(x86::Compiler& cc) override {
   1062     x86::Gp x = cc.new_gp8("x");
   1063     x86::Gp y = cc.new_gp32("y");
   1064 
   1065     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int8_t>());
   1066     func_node->set_arg(0, x);
   1067 
   1068     cc.movsx(y, x);
   1069 
   1070     cc.ret(y);
   1071     cc.end_func();
   1072   }
   1073 
   1074   bool run(void* _func, String& result, String& expect) override {
   1075     using Func = int (*)(int8_t);
   1076     Func func = ptr_as_func<Func>(_func);
   1077 
   1078     int result_ret = func(int8_t(-13));
   1079     int expect_ret = -13;
   1080 
   1081     result.assign_format("ret=%d", result_ret);
   1082     expect.assign_format("ret=%d", expect_ret);
   1083 
   1084     return result == expect;
   1085   }
   1086 };
   1087 
   1088 // x86::Compiler - X86Test_AllocUnhandledArg
   1089 // =========================================
   1090 
   1091 class X86Test_AllocUnhandledArg : public X86TestCase {
   1092 public:
   1093   X86Test_AllocUnhandledArg() : X86TestCase("AllocUnhandledArg") {}
   1094 
   1095   static void add(TestApp& app) {
   1096     app.add(new X86Test_AllocUnhandledArg());
   1097   }
   1098 
   1099   void compile(x86::Compiler& cc) override {
   1100     x86::Gp x = cc.new_gp32("x");
   1101 
   1102     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   1103     func_node->set_arg(2, x);
   1104 
   1105     cc.ret(x);
   1106     cc.end_func();
   1107   }
   1108 
   1109   bool run(void* _func, String& result, String& expect) override {
   1110     using Func = int (*)(int, int, int);
   1111     Func func = ptr_as_func<Func>(_func);
   1112 
   1113     int result_ret = func(42, 155, 199);
   1114     int expect_ret = 199;
   1115 
   1116     result.assign_format("ret={%d}", result_ret);
   1117     expect.assign_format("ret={%d}", expect_ret);
   1118 
   1119     return result == expect;
   1120   }
   1121 };
   1122 
   1123 // x86::Compiler - X86Test_AllocArgsIntPtr
   1124 // =======================================
   1125 
   1126 class X86Test_AllocArgsIntPtr : public X86TestCase {
   1127 public:
   1128   X86Test_AllocArgsIntPtr() : X86TestCase("AllocArgsIntPtr") {}
   1129 
   1130   static void add(TestApp& app) {
   1131     app.add(new X86Test_AllocArgsIntPtr());
   1132   }
   1133 
   1134   void compile(x86::Compiler& cc) override {
   1135     FuncNode* func_node = cc.add_func(FuncSignature::build<void, void*, void*, void*, void*, void*, void*, void*, void*>());
   1136     x86::Gp var[8];
   1137 
   1138     for (uint32_t i = 0; i < 8; i++) {
   1139       var[i] = cc.new_gp_ptr("var%u", i);
   1140       func_node->set_arg(i, var[i]);
   1141     }
   1142 
   1143     for (uint32_t i = 0; i < 8; i++) {
   1144       cc.add(var[i], int(i + 1));
   1145     }
   1146 
   1147     // Move some data into buffer provided by arguments so we can verify if it
   1148     // really works without looking into assembler output.
   1149     for (uint32_t i = 0; i < 8; i++) {
   1150       cc.add(x86::byte_ptr(var[i]), int(i + 1));
   1151     }
   1152 
   1153     cc.end_func();
   1154   }
   1155 
   1156   bool run(void* _func, String& result, String& expect) override {
   1157     using Func = void (*)(void*, void*, void*, void*, void*, void*, void*, void*);
   1158     Func func = ptr_as_func<Func>(_func);
   1159 
   1160     uint8_t result_buf[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   1161     uint8_t expect_buf[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
   1162 
   1163     func(result_buf, result_buf, result_buf, result_buf,
   1164          result_buf, result_buf, result_buf, result_buf);
   1165 
   1166     result.assign_format("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
   1167       result_buf[0], result_buf[1], result_buf[2], result_buf[3],
   1168       result_buf[4], result_buf[5], result_buf[6], result_buf[7],
   1169       result_buf[8]);
   1170 
   1171     expect.assign_format("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
   1172       expect_buf[0], expect_buf[1], expect_buf[2], expect_buf[3],
   1173       expect_buf[4], expect_buf[5], expect_buf[6], expect_buf[7],
   1174       expect_buf[8]);
   1175 
   1176     return result == expect;
   1177   }
   1178 };
   1179 
   1180 // x86::Compiler - X86Test_AllocArgsFloat
   1181 // ======================================
   1182 
   1183 class X86Test_AllocArgsFloat : public X86TestCase {
   1184 public:
   1185   X86Test_AllocArgsFloat() : X86TestCase("AllocArgsFloat") {}
   1186 
   1187   static void add(TestApp& app) {
   1188     app.add(new X86Test_AllocArgsFloat());
   1189   }
   1190 
   1191   void compile(x86::Compiler& cc) override {
   1192     FuncNode* func_node = cc.add_func(FuncSignature::build<void, float, float, float, float, float, float, float, void*>());
   1193 
   1194     x86::Gp p = cc.new_gp_ptr("p");
   1195     x86::Vec xv[7];
   1196 
   1197     for (uint32_t i = 0; i < 7; i++) {
   1198       xv[i] = cc.new_xmm_ss("xv%u", i);
   1199       func_node->set_arg(i, xv[i]);
   1200     }
   1201 
   1202     func_node->set_arg(7, p);
   1203 
   1204     cc.addss(xv[0], xv[1]);
   1205     cc.addss(xv[0], xv[2]);
   1206     cc.addss(xv[0], xv[3]);
   1207     cc.addss(xv[0], xv[4]);
   1208     cc.addss(xv[0], xv[5]);
   1209     cc.addss(xv[0], xv[6]);
   1210 
   1211     cc.movss(x86::ptr(p), xv[0]);
   1212     cc.end_func();
   1213   }
   1214 
   1215   bool run(void* _func, String& result, String& expect) override {
   1216     using Func = void (*)(float, float, float, float, float, float, float, float*);
   1217     Func func = ptr_as_func<Func>(_func);
   1218 
   1219     float result_ret = 0;
   1220     float expect_ret = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f;
   1221 
   1222     func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &result_ret);
   1223 
   1224     result.assign_format("ret={%g}", double(result_ret));
   1225     expect.assign_format("ret={%g}", double(expect_ret));
   1226 
   1227     return result == expect;
   1228   }
   1229 };
   1230 
   1231 // x86::Compiler - X86Test_AllocArgsDouble
   1232 // =======================================
   1233 
   1234 class X86Test_AllocArgsDouble : public X86TestCase {
   1235 public:
   1236   X86Test_AllocArgsDouble() : X86TestCase("AllocArgsDouble") {}
   1237 
   1238   static void add(TestApp& app) {
   1239     app.add(new X86Test_AllocArgsDouble());
   1240   }
   1241 
   1242   void compile(x86::Compiler& cc) override {
   1243     FuncNode* func_node = cc.add_func(FuncSignature::build<void, double, double, double, double, double, double, double, void*>());
   1244 
   1245     x86::Gp p = cc.new_gp_ptr("p");
   1246     x86::Vec xv[7];
   1247 
   1248     for (uint32_t i = 0; i < 7; i++) {
   1249       xv[i] = cc.new_xmm_sd("xv%u", i);
   1250       func_node->set_arg(i, xv[i]);
   1251     }
   1252 
   1253     func_node->set_arg(7, p);
   1254 
   1255     cc.addsd(xv[0], xv[1]);
   1256     cc.addsd(xv[0], xv[2]);
   1257     cc.addsd(xv[0], xv[3]);
   1258     cc.addsd(xv[0], xv[4]);
   1259     cc.addsd(xv[0], xv[5]);
   1260     cc.addsd(xv[0], xv[6]);
   1261 
   1262     cc.movsd(x86::ptr(p), xv[0]);
   1263     cc.end_func();
   1264   }
   1265 
   1266   bool run(void* _func, String& result, String& expect) override {
   1267     using Func = void (*)(double, double, double, double, double, double, double, double*);
   1268     Func func = ptr_as_func<Func>(_func);
   1269 
   1270     double result_ret = 0;
   1271     double expect_ret = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0;
   1272 
   1273     func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &result_ret);
   1274 
   1275     result.assign_format("ret={%g}", result_ret);
   1276     expect.assign_format("ret={%g}", expect_ret);
   1277 
   1278     return result == expect;
   1279   }
   1280 };
   1281 
   1282 // x86::Compiler - X86Test_AllocArgsVec
   1283 // ====================================
   1284 
   1285 #if ASMJIT_ARCH_X86
   1286 class X86Test_AllocArgsVec : public X86TestCase {
   1287 public:
   1288   X86Test_AllocArgsVec() : X86TestCase("AllocArgsVec") {}
   1289 
   1290   static void add(TestApp& app) {
   1291     // Not supported on Windows.
   1292 #ifndef _WIN32
   1293     app.add(new X86Test_AllocArgsVec());
   1294 #else
   1295     Support::maybe_unused(app);
   1296 #endif
   1297   }
   1298 
   1299   void compile(x86::Compiler& cc) override {
   1300     x86::Vec a = cc.new_xmm("xmm_a");
   1301     x86::Vec b = cc.new_xmm("xmm_b");
   1302 
   1303     FuncNode* func_node = cc.add_func(FuncSignature::build<Type::Vec128, Type::Vec128, Type::Vec128>());
   1304     func_node->set_arg(0, a);
   1305     func_node->set_arg(1, b);
   1306 
   1307     cc.paddb(a, b);
   1308     cc.ret(a);
   1309 
   1310     cc.end_func();
   1311   }
   1312 
   1313   bool run(void* _func, String& result, String& expect) override {
   1314     using Func = __m128i (*)(__m128i, __m128i);
   1315     Func func = ptr_as_func<Func>(_func);
   1316 
   1317     uint8_t a_data[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
   1318     uint8_t b_data[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
   1319 
   1320     uint8_t r_data[16] {};
   1321     uint8_t e_data[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
   1322 
   1323     __m128i a_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(a_data));
   1324     __m128i b_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(b_data));
   1325 
   1326     __m128i r_vec = func(a_vec, b_vec);
   1327     _mm_storeu_si128(reinterpret_cast<__m128i*>(r_data), r_vec);
   1328 
   1329     result.append_hex(r_data, 16);
   1330     expect.append_hex(e_data, 16);
   1331 
   1332     return result == expect;
   1333   }
   1334 };
   1335 #endif // ASMJIT_ARCH_X86
   1336 
   1337 // x86::Compiler - X86Test_AllocRetFloat1
   1338 // ======================================
   1339 
   1340 class X86Test_AllocRetFloat1 : public X86TestCase {
   1341 public:
   1342   X86Test_AllocRetFloat1() : X86TestCase("AllocRetFloat1") {}
   1343 
   1344   static void add(TestApp& app) {
   1345     app.add(new X86Test_AllocRetFloat1());
   1346   }
   1347 
   1348   void compile(x86::Compiler& cc) override {
   1349     x86::Vec x = cc.new_xmm_ss("x");
   1350 
   1351     FuncNode* func_node = cc.add_func(FuncSignature::build<float, float>());
   1352     func_node->set_arg(0, x);
   1353 
   1354     cc.ret(x);
   1355     cc.end_func();
   1356   }
   1357 
   1358   bool run(void* _func, String& result, String& expect) override {
   1359     using Func = float (*)(float);
   1360     Func func = ptr_as_func<Func>(_func);
   1361 
   1362     float result_ret = func(42.0f);
   1363     float expect_ret = 42.0f;
   1364 
   1365     result.assign_format("ret={%g}", double(result_ret));
   1366     expect.assign_format("ret={%g}", double(expect_ret));
   1367 
   1368     return result == expect;
   1369   }
   1370 };
   1371 
   1372 // x86::Compiler - X86Test_AllocRetFloat2
   1373 // ======================================
   1374 
   1375 class X86Test_AllocRetFloat2 : public X86TestCase {
   1376 public:
   1377   X86Test_AllocRetFloat2() : X86TestCase("AllocRetFloat2") {}
   1378 
   1379   static void add(TestApp& app) {
   1380     app.add(new X86Test_AllocRetFloat2());
   1381   }
   1382 
   1383   void compile(x86::Compiler& cc) override {
   1384     x86::Vec x = cc.new_xmm_ss("x");
   1385     x86::Vec y = cc.new_xmm_ss("y");
   1386 
   1387     FuncNode* func_node = cc.add_func(FuncSignature::build<float, float, float>());
   1388     func_node->set_arg(0, x);
   1389     func_node->set_arg(1, y);
   1390 
   1391     cc.addss(x, y);
   1392     cc.ret(x);
   1393 
   1394     cc.end_func();
   1395   }
   1396 
   1397   bool run(void* _func, String& result, String& expect) override {
   1398     using Func = float (*)(float, float);
   1399     Func func = ptr_as_func<Func>(_func);
   1400 
   1401     float result_ret = func(1.0f, 2.0f);
   1402     float expect_ret = 1.0f + 2.0f;
   1403 
   1404     result.assign_format("ret={%g}", double(result_ret));
   1405     expect.assign_format("ret={%g}", double(expect_ret));
   1406 
   1407     return result == expect;
   1408   }
   1409 };
   1410 
   1411 // x86::Compiler - X86Test_AllocRetDouble1
   1412 // =======================================
   1413 
   1414 class X86Test_AllocRetDouble1 : public X86TestCase {
   1415 public:
   1416   X86Test_AllocRetDouble1() : X86TestCase("AllocRetDouble1") {}
   1417 
   1418   static void add(TestApp& app) {
   1419     app.add(new X86Test_AllocRetDouble1());
   1420   }
   1421 
   1422   void compile(x86::Compiler& cc) override {
   1423     x86::Vec x = cc.new_xmm_sd("x");
   1424 
   1425     FuncNode* func_node = cc.add_func(FuncSignature::build<double, double>());
   1426     func_node->set_arg(0, x);
   1427 
   1428     cc.ret(x);
   1429     cc.end_func();
   1430   }
   1431 
   1432   bool run(void* _func, String& result, String& expect) override {
   1433     using Func = double (*)(double);
   1434     Func func = ptr_as_func<Func>(_func);
   1435 
   1436     double result_ret = func(42.0);
   1437     double expect_ret = 42.0;
   1438 
   1439     result.assign_format("ret={%g}", result_ret);
   1440     expect.assign_format("ret={%g}", expect_ret);
   1441 
   1442     return result == expect;
   1443   }
   1444 };
   1445 
   1446 // x86::Compiler - X86Test_AllocRetDouble2
   1447 // =======================================
   1448 
   1449 class X86Test_AllocRetDouble2 : public X86TestCase {
   1450 public:
   1451   X86Test_AllocRetDouble2() : X86TestCase("AllocRetDouble2") {}
   1452 
   1453   static void add(TestApp& app) {
   1454     app.add(new X86Test_AllocRetDouble2());
   1455   }
   1456 
   1457   void compile(x86::Compiler& cc) override {
   1458     x86::Vec x = cc.new_xmm_sd("x");
   1459     x86::Vec y = cc.new_xmm_sd("y");
   1460 
   1461     FuncNode* func_node = cc.add_func(FuncSignature::build<double, double, double>());
   1462     func_node->set_arg(0, x);
   1463     func_node->set_arg(1, y);
   1464 
   1465     cc.addsd(x, y);
   1466     cc.ret(x);
   1467 
   1468     cc.end_func();
   1469   }
   1470 
   1471   bool run(void* _func, String& result, String& expect) override {
   1472     using Func = double (*)(double, double);
   1473     Func func = ptr_as_func<Func>(_func);
   1474 
   1475     double result_ret = func(1.0, 2.0);
   1476     double expect_ret = 1.0 + 2.0;
   1477 
   1478     result.assign_format("ret={%g}", result_ret);
   1479     expect.assign_format("ret={%g}", expect_ret);
   1480 
   1481     return result == expect;
   1482   }
   1483 };
   1484 
   1485 // x86::Compiler - X86Test_AllocStack
   1486 // ==================================
   1487 
   1488 class X86Test_AllocStack : public X86TestCase {
   1489 public:
   1490   X86Test_AllocStack() : X86TestCase("AllocStack") {}
   1491 
   1492   static inline constexpr uint32_t kSize = 256u;
   1493 
   1494   static void add(TestApp& app) {
   1495     app.add(new X86Test_AllocStack());
   1496   }
   1497 
   1498   void compile(x86::Compiler& cc) override {
   1499     cc.add_func(FuncSignature::build<int>());
   1500 
   1501     x86::Mem stack = cc.new_stack(kSize, 1);
   1502     stack.set_size(1);
   1503 
   1504     x86::Gp i = cc.new_gp_ptr("i");
   1505     x86::Gp a = cc.new_gp32("a");
   1506     x86::Gp b = cc.new_gp32("b");
   1507 
   1508     Label L_1 = cc.new_label();
   1509     Label L_2 = cc.new_label();
   1510 
   1511     // Fill stack by sequence [0, 1, 2, 3 ... 255].
   1512     cc.xor_(i, i);
   1513 
   1514     x86::Mem stack_with_index = stack.clone();
   1515     stack_with_index.set_index(i, 0);
   1516 
   1517     cc.bind(L_1);
   1518     cc.mov(stack_with_index, i.r8());
   1519     cc.inc(i);
   1520     cc.cmp(i, 255);
   1521     cc.jle(L_1);
   1522 
   1523     // Sum sequence in stack.
   1524     cc.xor_(i, i);
   1525     cc.xor_(a, a);
   1526 
   1527     cc.bind(L_2);
   1528     cc.movzx(b, stack_with_index);
   1529     cc.add(a, b);
   1530     cc.inc(i);
   1531     cc.cmp(i, 255);
   1532     cc.jle(L_2);
   1533 
   1534     cc.ret(a);
   1535     cc.end_func();
   1536   }
   1537 
   1538   bool run(void* _func, String& result, String& expect) override {
   1539     using Func = int (*)(void);
   1540     Func func = ptr_as_func<Func>(_func);
   1541 
   1542     int result_ret = func();
   1543     int expect_ret = 32640;
   1544 
   1545     result.assign_int(result_ret);
   1546     expect.assign_int(expect_ret);
   1547 
   1548     return result == expect;
   1549   }
   1550 };
   1551 
   1552 // x86::Compiler - X86Test_Imul1
   1553 // =============================
   1554 
   1555 class X86Test_Imul1 : public X86TestCase {
   1556 public:
   1557   X86Test_Imul1() : X86TestCase("Imul1") {}
   1558 
   1559   static void add(TestApp& app) {
   1560     app.add(new X86Test_Imul1());
   1561   }
   1562 
   1563   void compile(x86::Compiler& cc) override {
   1564     x86::Gp dst_hi = cc.new_gp_ptr("dst_hi");
   1565     x86::Gp dst_lo = cc.new_gp_ptr("dst_lo");
   1566 
   1567     x86::Gp v_hi = cc.new_gp32("v_hi");
   1568     x86::Gp v_lo = cc.new_gp32("v_lo");
   1569     x86::Gp src = cc.new_gp32("src");
   1570 
   1571     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int*, int*, int, int>());
   1572     func_node->set_arg(0, dst_hi);
   1573     func_node->set_arg(1, dst_lo);
   1574     func_node->set_arg(2, v_lo);
   1575     func_node->set_arg(3, src);
   1576 
   1577     cc.imul(v_hi, v_lo, src);
   1578     cc.mov(x86::dword_ptr(dst_hi), v_hi);
   1579     cc.mov(x86::dword_ptr(dst_lo), v_lo);
   1580     cc.end_func();
   1581   }
   1582 
   1583   bool run(void* _func, String& result, String& expect) override {
   1584     using Func = void (*)(int*, int*, int, int);
   1585     Func func = ptr_as_func<Func>(_func);
   1586 
   1587     int v0 = 4;
   1588     int v1 = 4;
   1589 
   1590     int result_hi = 0;
   1591     int result_lo = 0;
   1592 
   1593     int expect_hi = 0;
   1594     int expect_lo = v0 * v1;
   1595 
   1596     func(&result_hi, &result_lo, v0, v1);
   1597 
   1598     result.assign_format("hi=%d, lo=%d", result_hi, result_lo);
   1599     expect.assign_format("hi=%d, lo=%d", expect_hi, expect_lo);
   1600 
   1601     return result_hi == expect_hi && result_lo == expect_lo;
   1602   }
   1603 };
   1604 
   1605 // x86::Compiler - X86Test_Imul2
   1606 // =============================
   1607 
   1608 class X86Test_Imul2 : public X86TestCase {
   1609 public:
   1610   X86Test_Imul2() : X86TestCase("Imul2") {}
   1611 
   1612   static void add(TestApp& app) {
   1613     app.add(new X86Test_Imul2());
   1614   }
   1615 
   1616   void compile(x86::Compiler& cc) override {
   1617     x86::Gp dst = cc.new_gp_ptr("dst");
   1618     x86::Gp src = cc.new_gp_ptr("src");
   1619 
   1620     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int*, const int*>());
   1621     func_node->set_arg(0, dst);
   1622     func_node->set_arg(1, src);
   1623 
   1624     for (unsigned int i = 0; i < 4; i++) {
   1625       x86::Gp x  = cc.new_gp32("x");
   1626       x86::Gp y  = cc.new_gp32("y");
   1627       x86::Gp hi = cc.new_gp32("hi");
   1628 
   1629       cc.mov(x, x86::dword_ptr(src, 0));
   1630       cc.mov(y, x86::dword_ptr(src, 4));
   1631 
   1632       cc.imul(hi, x, y);
   1633       cc.add(x86::dword_ptr(dst, 0), hi);
   1634       cc.add(x86::dword_ptr(dst, 4), x);
   1635     }
   1636 
   1637     cc.end_func();
   1638   }
   1639 
   1640   bool run(void* _func, String& result, String& expect) override {
   1641     using Func = void (*)(int*, const int*);
   1642     Func func = ptr_as_func<Func>(_func);
   1643 
   1644     int src[2] = { 4, 9 };
   1645     int result_ret[2] = { 0, 0 };
   1646     int expect_ret[2] = { 0, (4 * 9) * 4 };
   1647 
   1648     func(result_ret, src);
   1649 
   1650     result.assign_format("ret={%d, %d}", result_ret[0], result_ret[1]);
   1651     expect.assign_format("ret={%d, %d}", expect_ret[0], expect_ret[1]);
   1652 
   1653     return result_ret[0] == expect_ret[0] && result_ret[1] == expect_ret[1];
   1654   }
   1655 };
   1656 
   1657 // x86::Compiler - X86Test_Idiv1
   1658 // =============================
   1659 
   1660 class X86Test_Idiv1 : public X86TestCase {
   1661 public:
   1662   X86Test_Idiv1() : X86TestCase("Idiv1") {}
   1663 
   1664   static void add(TestApp& app) {
   1665     app.add(new X86Test_Idiv1());
   1666   }
   1667 
   1668   void compile(x86::Compiler& cc) override {
   1669     x86::Gp a = cc.new_gp32("a");
   1670     x86::Gp b = cc.new_gp32("b");
   1671     x86::Gp dummy = cc.new_gp32("dummy");
   1672 
   1673     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   1674     func_node->set_arg(0, a);
   1675     func_node->set_arg(1, b);
   1676 
   1677     cc.xor_(dummy, dummy);
   1678     cc.idiv(dummy, a, b);
   1679 
   1680     cc.ret(a);
   1681     cc.end_func();
   1682   }
   1683 
   1684   bool run(void* _func, String& result, String& expect) override {
   1685     using Func = int (*)(int, int);
   1686     Func func = ptr_as_func<Func>(_func);
   1687 
   1688     int v0 = 2999;
   1689     int v1 = 245;
   1690 
   1691     int result_ret = func(v0, v1);
   1692     int expect_ret = 2999 / 245;
   1693 
   1694     result.assign_format("result=%d", result_ret);
   1695     expect.assign_format("result=%d", expect_ret);
   1696 
   1697     return result == expect;
   1698   }
   1699 };
   1700 
   1701 // x86::Compiler - X86Test_Setz
   1702 // ============================
   1703 
   1704 class X86Test_Setz : public X86TestCase {
   1705 public:
   1706   X86Test_Setz() : X86TestCase("Setz") {}
   1707 
   1708   static void add(TestApp& app) {
   1709     app.add(new X86Test_Setz());
   1710   }
   1711 
   1712   void compile(x86::Compiler& cc) override {
   1713     x86::Gp src0 = cc.new_gp32("src0");
   1714     x86::Gp src1 = cc.new_gp32("src1");
   1715     x86::Gp dst0 = cc.new_gp_ptr("dst0");
   1716 
   1717     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int, int, char*>());
   1718     func_node->set_arg(0, src0);
   1719     func_node->set_arg(1, src1);
   1720     func_node->set_arg(2, dst0);
   1721 
   1722     cc.cmp(src0, src1);
   1723     cc.setz(x86::byte_ptr(dst0));
   1724 
   1725     cc.end_func();
   1726   }
   1727 
   1728   bool run(void* _func, String& result, String& expect) override {
   1729     using Func = void (*)(int, int, char*);
   1730     Func func = ptr_as_func<Func>(_func);
   1731 
   1732     char result_buf[4] {};
   1733     char expect_buf[4] = { 1, 0, 0, 1 };
   1734 
   1735     func(0, 0, &result_buf[0]); // We are expecting 1 (0 == 0).
   1736     func(0, 1, &result_buf[1]); // We are expecting 0 (0 != 1).
   1737     func(1, 0, &result_buf[2]); // We are expecting 0 (1 != 0).
   1738     func(1, 1, &result_buf[3]); // We are expecting 1 (1 == 1).
   1739 
   1740     result.assign_format("out={%d, %d, %d, %d}", result_buf[0], result_buf[1], result_buf[2], result_buf[3]);
   1741     expect.assign_format("out={%d, %d, %d, %d}", expect_buf[0], expect_buf[1], expect_buf[2], expect_buf[3]);
   1742 
   1743     return result_buf[0] == expect_buf[0] &&
   1744            result_buf[1] == expect_buf[1] &&
   1745            result_buf[2] == expect_buf[2] &&
   1746            result_buf[3] == expect_buf[3] ;
   1747   }
   1748 };
   1749 
   1750 // x86::Compiler - X86Test_ShlRor
   1751 // ==============================
   1752 
   1753 class X86Test_ShlRor : public X86TestCase {
   1754 public:
   1755   X86Test_ShlRor() : X86TestCase("ShlRor") {}
   1756 
   1757   static void add(TestApp& app) {
   1758     app.add(new X86Test_ShlRor());
   1759   }
   1760 
   1761   void compile(x86::Compiler& cc) override {
   1762     x86::Gp dst = cc.new_gp_ptr("dst");
   1763     x86::Gp var = cc.new_gp32("var");
   1764     x86::Gp v_shl_param = cc.new_gp32("v_shl_param");
   1765     x86::Gp v_ror_param = cc.new_gp32("v_ror_param");
   1766 
   1767     FuncNode* func_node = cc.add_func(FuncSignature::build<void, int*, int, int, int>());
   1768     func_node->set_arg(0, dst);
   1769     func_node->set_arg(1, var);
   1770     func_node->set_arg(2, v_shl_param);
   1771     func_node->set_arg(3, v_ror_param);
   1772 
   1773     cc.shl(var, v_shl_param);
   1774     cc.ror(var, v_ror_param);
   1775     cc.mov(x86::dword_ptr(dst), var);
   1776     cc.end_func();
   1777   }
   1778 
   1779   bool run(void* _func, String& result, String& expect) override {
   1780     using Func = void (*)(int*, int, int, int);
   1781     Func func = ptr_as_func<Func>(_func);
   1782 
   1783     int v0 = 0x000000FF;
   1784 
   1785     int result_ret = 0;
   1786     int expect_ret = 0x0000FF00;
   1787 
   1788     func(&result_ret, v0, 16, 8);
   1789 
   1790     result.assign_format("ret=%d", result_ret);
   1791     expect.assign_format("ret=%d", expect_ret);
   1792 
   1793     return result == expect;
   1794   }
   1795 };
   1796 
   1797 // x86::Compiler - X86Test_GpbLo
   1798 // =============================
   1799 
   1800 class X86Test_GpbLo1 : public X86TestCase {
   1801 public:
   1802   X86Test_GpbLo1() : X86TestCase("GpbLo1") {}
   1803 
   1804   static inline constexpr uint32_t kCount = 32u;
   1805 
   1806   static void add(TestApp& app) {
   1807     app.add(new X86Test_GpbLo1());
   1808   }
   1809 
   1810   void compile(x86::Compiler& cc) override {
   1811     x86::Gp reg_Ptr = cc.new_gp_ptr("reg_Ptr");
   1812     x86::Gp sum = cc.new_gp32("sum");
   1813     x86::Gp x[kCount];
   1814 
   1815     FuncNode* func_node = cc.add_func(FuncSignature::build<uint32_t, uint32_t*>());
   1816     func_node->set_arg(0, reg_Ptr);
   1817 
   1818     for (uint32_t i = 0; i < kCount; i++) {
   1819       x[i] = cc.new_gp32("x%u", i);
   1820     }
   1821 
   1822     // Init pseudo-regs with values from our array.
   1823     for (uint32_t i = 0; i < kCount; i++) {
   1824       cc.mov(x[i], x86::dword_ptr(reg_Ptr, int(i * 4)));
   1825     }
   1826 
   1827     for (uint32_t i = 2; i < kCount; i++) {
   1828       // Add and truncate to 8 bit; no purpose, just mess with jit.
   1829       cc.add  (x[i  ], x[i-1]);
   1830       cc.movzx(x[i  ], x[i  ].r8());
   1831       cc.movzx(x[i-2], x[i-1].r8());
   1832       cc.movzx(x[i-1], x[i-2].r8());
   1833     }
   1834 
   1835     // Sum up all computed values.
   1836     cc.mov(sum, 0);
   1837     for (uint32_t i = 0; i < kCount; i++) {
   1838       cc.add(sum, x[i]);
   1839     }
   1840 
   1841     // Return the sum.
   1842     cc.ret(sum);
   1843     cc.end_func();
   1844   }
   1845 
   1846   bool run(void* _func, String& result, String& expect) override {
   1847     using Func = uint32_t (*)(uint32_t*);
   1848     Func func = ptr_as_func<Func>(_func);
   1849 
   1850     uint32_t i;
   1851     uint32_t buf[kCount];
   1852     uint32_t result_ret = 0;
   1853     uint32_t expect_ret = 0;
   1854 
   1855     for (i = 0; i < kCount; i++) {
   1856       buf[i] = 1;
   1857     }
   1858 
   1859     for (i = 2; i < kCount; i++) {
   1860       buf[i  ]+= buf[i-1];
   1861       buf[i  ] = buf[i  ] & 0xFF;
   1862       buf[i-2] = buf[i-1] & 0xFF;
   1863       buf[i-1] = buf[i-2] & 0xFF;
   1864     }
   1865 
   1866     for (i = 0; i < kCount; i++) {
   1867       expect_ret += buf[i];
   1868     }
   1869 
   1870     for (i = 0; i < kCount; i++) {
   1871       buf[i] = 1;
   1872     }
   1873     result_ret = func(buf);
   1874 
   1875     result.assign_format("ret=%d", result_ret);
   1876     expect.assign_format("ret=%d", expect_ret);
   1877 
   1878     return result == expect;
   1879   }
   1880 };
   1881 
   1882 // x86::Compiler - X86Test_GpbLo2
   1883 // ==============================
   1884 
   1885 class X86Test_GpbLo2 : public X86TestCase {
   1886 public:
   1887   X86Test_GpbLo2() : X86TestCase("GpbLo2") {}
   1888 
   1889   static void add(TestApp& app) {
   1890     app.add(new X86Test_GpbLo2());
   1891   }
   1892 
   1893   void compile(x86::Compiler& cc) override {
   1894     x86::Gp v = cc.new_gp32("v");
   1895 
   1896     FuncNode* func_node = cc.add_func(FuncSignature::build<uint32_t, uint32_t>());
   1897     func_node->set_arg(0, v);
   1898 
   1899     cc.mov(v.r8(), 0xFF);
   1900     cc.ret(v);
   1901     cc.end_func();
   1902   }
   1903 
   1904   bool run(void* _func, String& result, String& expect) override {
   1905     using Func = uint32_t (*)(uint32_t);
   1906     Func func = ptr_as_func<Func>(_func);
   1907 
   1908     uint32_t result_ret = func(0x12345678u);
   1909     uint32_t expect_ret = 0x123456FFu;
   1910 
   1911     result.assign_format("ret=%d", result_ret);
   1912     expect.assign_format("ret=%d", expect_ret);
   1913 
   1914     return result == expect;
   1915   }
   1916 };
   1917 
   1918 // x86::Compiler - X86Test_RepMovsb
   1919 // ================================
   1920 
   1921 class X86Test_RepMovsb : public X86TestCase {
   1922 public:
   1923   X86Test_RepMovsb() : X86TestCase("RepMovsb") {}
   1924 
   1925   static void add(TestApp& app) {
   1926     app.add(new X86Test_RepMovsb());
   1927   }
   1928 
   1929   void compile(x86::Compiler& cc) override {
   1930     x86::Gp dst = cc.new_gp_ptr("dst");
   1931     x86::Gp src = cc.new_gp_ptr("src");
   1932     x86::Gp cnt = cc.new_gp_ptr("cnt");
   1933 
   1934     FuncNode* func_node = cc.add_func(FuncSignature::build<void, void*, void*, size_t>());
   1935     func_node->set_arg(0, dst);
   1936     func_node->set_arg(1, src);
   1937     func_node->set_arg(2, cnt);
   1938 
   1939     cc.rep(cnt).movs(x86::byte_ptr(dst), x86::byte_ptr(src));
   1940     cc.end_func();
   1941   }
   1942 
   1943   bool run(void* _func, String& result, String& expect) override {
   1944     using Func = void (*)(void*, void*, size_t);
   1945     Func func = ptr_as_func<Func>(_func);
   1946 
   1947     char dst[20] = { 0 };
   1948     char src[20] = "Hello AsmJit!";
   1949     func(dst, src, strlen(src) + 1);
   1950 
   1951     result.assign_format("ret=\"%s\"", dst);
   1952     expect.assign_format("ret=\"%s\"", src);
   1953 
   1954     return result == expect;
   1955   }
   1956 };
   1957 
   1958 // x86::Compiler - X86Test_IfElse1
   1959 // ===============================
   1960 
   1961 class X86Test_IfElse1 : public X86TestCase {
   1962 public:
   1963   X86Test_IfElse1() : X86TestCase("IfElse1") {}
   1964 
   1965   static void add(TestApp& app) {
   1966     app.add(new X86Test_IfElse1());
   1967   }
   1968 
   1969   void compile(x86::Compiler& cc) override {
   1970     x86::Gp v1 = cc.new_gp32("v1");
   1971     x86::Gp v2 = cc.new_gp32("v2");
   1972 
   1973     Label L_1 = cc.new_label();
   1974     Label L_2 = cc.new_label();
   1975 
   1976     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   1977     func_node->set_arg(0, v1);
   1978     func_node->set_arg(1, v2);
   1979 
   1980     cc.cmp(v1, v2);
   1981     cc.jg(L_1);
   1982 
   1983     cc.mov(v1, 1);
   1984     cc.jmp(L_2);
   1985 
   1986     cc.bind(L_1);
   1987     cc.mov(v1, 2);
   1988 
   1989     cc.bind(L_2);
   1990     cc.ret(v1);
   1991     cc.end_func();
   1992   }
   1993 
   1994   bool run(void* _func, String& result, String& expect) override {
   1995     using Func = int (*)(int, int);
   1996     Func func = ptr_as_func<Func>(_func);
   1997 
   1998     int a = func(0, 1);
   1999     int b = func(1, 0);
   2000 
   2001     result.append_format("ret={%d, %d}", a, b);
   2002     expect.append_format("ret={%d, %d}", 1, 2);
   2003 
   2004     return result == expect;
   2005   }
   2006 };
   2007 
   2008 // x86::Compiler - X86Test_IfElse2
   2009 // ===============================
   2010 
   2011 class X86Test_IfElse2 : public X86TestCase {
   2012 public:
   2013   X86Test_IfElse2() : X86TestCase("IfElse2") {}
   2014 
   2015   static void add(TestApp& app) {
   2016     app.add(new X86Test_IfElse2());
   2017   }
   2018 
   2019   void compile(x86::Compiler& cc) override {
   2020     x86::Gp v1 = cc.new_gp32("v1");
   2021     x86::Gp v2 = cc.new_gp32("v2");
   2022 
   2023     Label L_1 = cc.new_label();
   2024     Label L_2 = cc.new_label();
   2025     Label L_3 = cc.new_label();
   2026     Label L_4 = cc.new_label();
   2027 
   2028     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   2029     func_node->set_arg(0, v1);
   2030     func_node->set_arg(1, v2);
   2031 
   2032     cc.jmp(L_1);
   2033     cc.bind(L_2);
   2034     cc.jmp(L_4);
   2035     cc.bind(L_1);
   2036 
   2037     cc.cmp(v1, v2);
   2038     cc.jg(L_3);
   2039 
   2040     cc.mov(v1, 1);
   2041     cc.jmp(L_2);
   2042 
   2043     cc.bind(L_3);
   2044     cc.mov(v1, 2);
   2045     cc.jmp(L_2);
   2046 
   2047     cc.bind(L_4);
   2048 
   2049     cc.ret(v1);
   2050     cc.end_func();
   2051   }
   2052 
   2053   bool run(void* _func, String& result, String& expect) override {
   2054     using Func = int (*)(int, int);
   2055     Func func = ptr_as_func<Func>(_func);
   2056 
   2057     int a = func(0, 1);
   2058     int b = func(1, 0);
   2059 
   2060     result.append_format("ret={%d, %d}", a, b);
   2061     expect.append_format("ret={%d, %d}", 1, 2);
   2062 
   2063     return result == expect;
   2064   }
   2065 };
   2066 
   2067 // x86::Compiler - X86Test_IfElse3
   2068 // ===============================
   2069 
   2070 class X86Test_IfElse3 : public X86TestCase {
   2071 public:
   2072   X86Test_IfElse3() : X86TestCase("IfElse3") {}
   2073 
   2074   static void add(TestApp& app) {
   2075     app.add(new X86Test_IfElse3());
   2076   }
   2077 
   2078   void compile(x86::Compiler& cc) override {
   2079     x86::Gp v1 = cc.new_gp32("v1");
   2080     x86::Gp v2 = cc.new_gp32("v2");
   2081     x86::Gp counter = cc.new_gp32("counter");
   2082 
   2083     Label L_1 = cc.new_label();
   2084     Label L_Loop = cc.new_label();
   2085     Label L_Exit = cc.new_label();
   2086 
   2087     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   2088     func_node->set_arg(0, v1);
   2089     func_node->set_arg(1, v2);
   2090 
   2091     cc.cmp(v1, v2);
   2092     cc.jg(L_1);
   2093 
   2094     cc.mov(counter, 0);
   2095 
   2096     cc.bind(L_Loop);
   2097     cc.mov(v1, counter);
   2098 
   2099     cc.inc(counter);
   2100     cc.cmp(counter, 1);
   2101     cc.jle(L_Loop);
   2102     cc.jmp(L_Exit);
   2103 
   2104     cc.bind(L_1);
   2105     cc.mov(v1, 2);
   2106 
   2107     cc.bind(L_Exit);
   2108     cc.ret(v1);
   2109     cc.end_func();
   2110   }
   2111 
   2112   bool run(void* _func, String& result, String& expect) override {
   2113     using Func = int (*)(int, int);
   2114     Func func = ptr_as_func<Func>(_func);
   2115 
   2116     int a = func(0, 1);
   2117     int b = func(1, 0);
   2118 
   2119     result.append_format("ret={%d, %d}", a, b);
   2120     expect.append_format("ret={%d, %d}", 1, 2);
   2121 
   2122     return result == expect;
   2123   }
   2124 };
   2125 
   2126 // x86::Compiler - X86Test_IfElse4
   2127 // ===============================
   2128 
   2129 class X86Test_IfElse4 : public X86TestCase {
   2130 public:
   2131   X86Test_IfElse4() : X86TestCase("IfElse4") {}
   2132 
   2133   static void add(TestApp& app) {
   2134     app.add(new X86Test_IfElse4());
   2135   }
   2136 
   2137   void compile(x86::Compiler& cc) override {
   2138     x86::Gp v1 = cc.new_gp32("v1");
   2139     x86::Gp v2 = cc.new_gp32("v2");
   2140     x86::Gp counter = cc.new_gp32("counter");
   2141 
   2142     Label L_1 = cc.new_label();
   2143     Label L_Loop1 = cc.new_label();
   2144     Label L_Loop2 = cc.new_label();
   2145     Label L_Exit = cc.new_label();
   2146 
   2147     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   2148     func_node->set_arg(0, v1);
   2149     func_node->set_arg(1, v2);
   2150 
   2151     cc.mov(counter, 0);
   2152     cc.cmp(v1, v2);
   2153     cc.jg(L_1);
   2154 
   2155     cc.bind(L_Loop1);
   2156     cc.mov(v1, counter);
   2157 
   2158     cc.inc(counter);
   2159     cc.cmp(counter, 1);
   2160     cc.jle(L_Loop1);
   2161     cc.jmp(L_Exit);
   2162 
   2163     cc.bind(L_1);
   2164     cc.bind(L_Loop2);
   2165     cc.mov(v1, counter);
   2166     cc.inc(counter);
   2167     cc.cmp(counter, 2);
   2168     cc.jle(L_Loop2);
   2169 
   2170     cc.bind(L_Exit);
   2171     cc.ret(v1);
   2172     cc.end_func();
   2173   }
   2174 
   2175   bool run(void* _func, String& result, String& expect) override {
   2176     using Func = int (*)(int, int);
   2177     Func func = ptr_as_func<Func>(_func);
   2178 
   2179     int a = func(0, 1);
   2180     int b = func(1, 0);
   2181 
   2182     result.append_format("ret={%d, %d}", a, b);
   2183     expect.append_format("ret={%d, %d}", 1, 2);
   2184 
   2185     return result == expect;
   2186   }
   2187 };
   2188 
   2189 // x86::Compiler - X86Test_Memcpy
   2190 // ==============================
   2191 
   2192 class X86Test_Memcpy : public X86TestCase {
   2193 public:
   2194   X86Test_Memcpy() : X86TestCase("Memcpy") {}
   2195 
   2196   static inline constexpr uint32_t kCount = 32u;
   2197 
   2198   static void add(TestApp& app) {
   2199     app.add(new X86Test_Memcpy());
   2200   }
   2201 
   2202   void compile(x86::Compiler& cc) override {
   2203     x86::Gp dst = cc.new_gp_ptr("dst");
   2204     x86::Gp src = cc.new_gp_ptr("src");
   2205     x86::Gp cnt = cc.new_gp_ptr("cnt");
   2206 
   2207     Label L_Loop = cc.new_label();                   // Create base labels we use
   2208     Label L_Exit = cc.new_label();                   // in our function.
   2209 
   2210     FuncNode* func_node = cc.add_func(FuncSignature::build<void, uint32_t*, const uint32_t*, size_t>());
   2211     func_node->set_arg(0, dst);
   2212     func_node->set_arg(1, src);
   2213     func_node->set_arg(2, cnt);
   2214 
   2215     cc.test(cnt, cnt);                              // Exit if the size is zero.
   2216     cc.jz(L_Exit);
   2217 
   2218     cc.bind(L_Loop);                                // Bind the loop label here.
   2219 
   2220     x86::Gp tmp = cc.new_gp32("tmp");               // Copy a single dword (4 bytes).
   2221     cc.mov(tmp, x86::dword_ptr(src));
   2222     cc.mov(x86::dword_ptr(dst), tmp);
   2223 
   2224     cc.add(src, 4);                                 // Increment dst/src pointers.
   2225     cc.add(dst, 4);
   2226 
   2227     cc.dec(cnt);                                    // Loop until cnt isn't zero.
   2228     cc.jnz(L_Loop);
   2229 
   2230     cc.bind(L_Exit);                                // Bind the exit label here.
   2231     cc.end_func();                                   // End of function.
   2232   }
   2233 
   2234   bool run(void* _func, String& result, String& expect) override {
   2235     using Func = void (*)(uint32_t*, const uint32_t*, size_t);
   2236     Func func = ptr_as_func<Func>(_func);
   2237 
   2238     uint32_t i;
   2239 
   2240     uint32_t dst_buffer[kCount];
   2241     uint32_t src_buffer[kCount];
   2242 
   2243     for (i = 0; i < kCount; i++) {
   2244       dst_buffer[i] = 0;
   2245       src_buffer[i] = i;
   2246     }
   2247 
   2248     func(dst_buffer, src_buffer, kCount);
   2249 
   2250     result.assign("buf={");
   2251     expect.assign("buf={");
   2252 
   2253     for (i = 0; i < kCount; i++) {
   2254       if (i != 0) {
   2255         result.append(", ");
   2256         expect.append(", ");
   2257       }
   2258 
   2259       result.append_format("%u", unsigned(dst_buffer[i]));
   2260       expect.append_format("%u", unsigned(src_buffer[i]));
   2261     }
   2262 
   2263     result.append("}");
   2264     expect.append("}");
   2265 
   2266     return result == expect;
   2267   }
   2268 };
   2269 
   2270 // x86::Compiler - X86Test_ExtraBlock
   2271 // ==================================
   2272 
   2273 class X86Test_ExtraBlock : public X86TestCase {
   2274 public:
   2275   X86Test_ExtraBlock() : X86TestCase("ExtraBlock") {}
   2276 
   2277   static void add(TestApp& app) {
   2278     app.add(new X86Test_ExtraBlock());
   2279   }
   2280 
   2281   void compile(x86::Compiler& cc) override {
   2282     x86::Gp cond = cc.new_gp32("cond");
   2283     x86::Gp ret = cc.new_gp32("ret");
   2284     x86::Gp a = cc.new_gp32("a");
   2285     x86::Gp b = cc.new_gp32("b");
   2286 
   2287     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   2288     func_node->set_arg(0, cond);
   2289     func_node->set_arg(1, a);
   2290     func_node->set_arg(2, b);
   2291 
   2292     Label L_Ret = cc.new_label();
   2293     Label L_Extra = cc.new_label();
   2294 
   2295     cc.test(cond, cond);
   2296     cc.jnz(L_Extra);
   2297 
   2298     cc.mov(ret, a);
   2299     cc.add(ret, b);
   2300 
   2301     cc.bind(L_Ret);
   2302     cc.ret(ret);
   2303 
   2304     // Emit code sequence at the end of the function.
   2305     BaseNode* prev_cursor = cc.set_cursor(func_node->end_node()->prev());
   2306     cc.bind(L_Extra);
   2307     cc.mov(ret, a);
   2308     cc.sub(ret, b);
   2309     cc.jmp(L_Ret);
   2310     cc.set_cursor(prev_cursor);
   2311 
   2312     cc.end_func();
   2313   }
   2314 
   2315   bool run(void* _func, String& result, String& expect) override {
   2316     using Func = int (*)(int, int, int);
   2317     Func func = ptr_as_func<Func>(_func);
   2318 
   2319     int ret1 = func(0, 4, 5);
   2320     int ret2 = func(1, 4, 5);
   2321 
   2322     int exp1 = 4 + 5;
   2323     int exp2 = 4 - 5;
   2324 
   2325     result.assign_format("ret={%d, %d}", ret1, ret2);
   2326     expect.assign_format("ret={%d, %d}", exp1, exp2);
   2327 
   2328     return result == expect;
   2329   }
   2330 };
   2331 
   2332 // x86::Compiler - X86Test_AlphaBlend
   2333 // ==================================
   2334 
   2335 class X86Test_AlphaBlend : public X86TestCase {
   2336 public:
   2337   X86Test_AlphaBlend() : X86TestCase("AlphaBlend") {}
   2338 
   2339   static inline constexpr uint32_t kCount = 17u;
   2340 
   2341   static void add(TestApp& app) {
   2342     app.add(new X86Test_AlphaBlend());
   2343   }
   2344 
   2345   static uint32_t blend_src_over(uint32_t d, uint32_t s) {
   2346     uint32_t sa_inv = ~s >> 24;
   2347 
   2348     uint32_t d_20 = (d     ) & 0x00FF00FF;
   2349     uint32_t d_31 = (d >> 8) & 0x00FF00FF;
   2350 
   2351     d_20 *= sa_inv;
   2352     d_31 *= sa_inv;
   2353 
   2354     d_20 = ((d_20 + ((d_20 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u) >> 8;
   2355     d_31 = ((d_31 + ((d_31 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u);
   2356 
   2357     return d_20 + d_31 + s;
   2358   }
   2359 
   2360   void compile(x86::Compiler& cc) override {
   2361     asmtest::generate_sse_alpha_blend(cc, true);
   2362   }
   2363 
   2364   bool run(void* _func, String& result, String& expect) override {
   2365     using Func = void (*)(void*, const void*, size_t);
   2366     Func func = ptr_as_func<Func>(_func);
   2367 
   2368     static const uint32_t dst_const_data[] = { 0x00000000, 0x10101010, 0x20100804, 0x30200003, 0x40204040, 0x5000004D, 0x60302E2C, 0x706F6E6D, 0x807F4F2F, 0x90349001, 0xA0010203, 0xB03204AB, 0xC023AFBD, 0xD0D0D0C0, 0xE0AABBCC, 0xFFFFFFFF, 0xF8F4F2F1 };
   2369     static const uint32_t src_const_data[] = { 0xE0E0E0E0, 0xA0008080, 0x341F1E1A, 0xFEFEFEFE, 0x80302010, 0x49490A0B, 0x998F7798, 0x00000000, 0x01010101, 0xA0264733, 0xBAB0B1B9, 0xFF000000, 0xDAB0A0C1, 0xE0BACFDA, 0x99887766, 0xFFFFFF80, 0xEE0A5FEC };
   2370 
   2371     uint32_t dst_buffer_storage[kCount + 3];
   2372     uint32_t src_buffer_storage[kCount + 3];
   2373 
   2374     // Has to be aligned.
   2375     uint32_t* dst_buffer = (uint32_t*)Support::align_up<intptr_t>((intptr_t)dst_buffer_storage, 16);
   2376     uint32_t* src_buffer = (uint32_t*)Support::align_up<intptr_t>((intptr_t)src_buffer_storage, 16);
   2377 
   2378     memcpy(dst_buffer, dst_const_data, sizeof(dst_const_data));
   2379     memcpy(src_buffer, src_const_data, sizeof(src_const_data));
   2380 
   2381     uint32_t i;
   2382     uint32_t exp_buffer[kCount];
   2383 
   2384     for (i = 0; i < kCount; i++) {
   2385       exp_buffer[i] = blend_src_over(dst_buffer[i], src_buffer[i]);
   2386     }
   2387 
   2388     func(dst_buffer, src_buffer, kCount);
   2389 
   2390     result.assign("buf={");
   2391     expect.assign("buf={");
   2392 
   2393     for (i = 0; i < kCount; i++) {
   2394       if (i != 0) {
   2395         result.append(", ");
   2396         expect.append(", ");
   2397       }
   2398 
   2399       result.append_format("%08X", unsigned(dst_buffer[i]));
   2400       expect.append_format("%08X", unsigned(exp_buffer[i]));
   2401     }
   2402 
   2403     result.append("}");
   2404     expect.append("}");
   2405 
   2406     return result == expect;
   2407   }
   2408 };
   2409 
   2410 // x86::Compiler - X86Test_AVX512_KK
   2411 // =================================
   2412 
   2413 class X86Test_AVX512_KK : public X86TestCase {
   2414 public:
   2415   X86Test_AVX512_KK() : X86TestCase("AVX512_KK") {}
   2416 
   2417   static void add(TestApp& app) {
   2418     const CpuInfo& cpu_info = CpuInfo::host();
   2419 
   2420     if (cpu_info.features().x86().has_avx512_f()) {
   2421       app.add(new X86Test_AVX512_KK());
   2422     }
   2423   }
   2424 
   2425   void compile(x86::Compiler& cc) override {
   2426     FuncNode* func_node = cc.add_func(FuncSignature::build<uint32_t, const void*, const void*, uint32_t>());
   2427 
   2428     x86::Gp a = cc.new_gp_ptr("a");
   2429     x86::Gp b = cc.new_gp_ptr("b");
   2430     x86::Gp pred = cc.new_gp32("pred");
   2431     x86::Gp result = cc.new_gp32("result");
   2432 
   2433     x86::Vec va = cc.new_zmm("va");
   2434     x86::Vec vb = cc.new_zmm("vb");
   2435     x86::KReg k_in = cc.new_kd("k_in");
   2436     x86::KReg k_out = cc.new_kd("k_out");
   2437 
   2438     func_node->set_arg(0, a);
   2439     func_node->set_arg(1, b);
   2440     func_node->set_arg(2, pred);
   2441 
   2442     cc.vmovdqu32(va, x86::ptr(a));
   2443     cc.vmovdqu32(vb, x86::ptr(b));
   2444     cc.kmovd(k_in, pred);
   2445     cc.k(k_in).vpcmpeqd(k_out, va, vb);
   2446     cc.kmovd(result, k_out);
   2447     cc.ret(result);
   2448     cc.end_func();
   2449   }
   2450 
   2451   bool run(void* _func, String& result, String& expect) override {
   2452     using Func = uint32_t (*)(const void*, const void*, uint32_t pred_k);
   2453     Func func = ptr_as_func<Func>(_func);
   2454 
   2455     static const uint32_t src_a[16] = { 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 };
   2456     static const uint32_t src_b[16] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1 };
   2457 
   2458     uint32_t ret = func(src_a, src_b, 0xF0F0);
   2459 
   2460     result.assign_format("0x%08X", ret);
   2461     expect.assign_format("0x%08X", 0xA040u);
   2462 
   2463     return result == expect;
   2464   }
   2465 };
   2466 
   2467 // x86::Compiler - X86Test_AVX512_TernLog
   2468 // ======================================
   2469 
   2470 class X86Test_AVX512_TernLog : public X86TestCase {
   2471 public:
   2472   X86Test_AVX512_TernLog() : X86TestCase("AVX512_TernLog") {}
   2473 
   2474   static void add(TestApp& app) {
   2475     const CpuInfo& cpu_info = CpuInfo::host();
   2476 
   2477     if (cpu_info.features().x86().has_avx512_f()) {
   2478       app.add(new X86Test_AVX512_TernLog());
   2479     }
   2480   }
   2481 
   2482   void compile(x86::Compiler& cc) override {
   2483     FuncNode* func_node = cc.add_func(FuncSignature::build<void, void*>());
   2484 
   2485     x86::Gp out_ptr = cc.new_gp_ptr("out_ptr");
   2486     x86::Vec vec = cc.new_zmm("vec");
   2487 
   2488     func_node->set_arg(0, out_ptr);
   2489 
   2490     cc.vpternlogd(vec, vec, vec, 0xFFu);
   2491     cc.vmovdqu8(x86::ptr(out_ptr), vec);
   2492     cc.end_func();
   2493   }
   2494 
   2495   bool run(void* _func, String& result, String& expect) override {
   2496     using Func = void (*)(void*);
   2497     Func func = ptr_as_func<Func>(_func);
   2498 
   2499     uint32_t out[16] {};
   2500     func(out);
   2501 
   2502     result.assign("{");
   2503     expect.assign("{");
   2504 
   2505     for (uint32_t i = 0; i < 16; i++) {
   2506       if (i) {
   2507         result.append(", ");
   2508         expect.append(", ");
   2509       }
   2510       result.append_format("0x%08X", out[i]);
   2511       expect.append_format("0x%08X", 0xFFFFFFFFu);
   2512     }
   2513 
   2514     result.append("}");
   2515     expect.append("}");
   2516 
   2517     return result == expect;
   2518   }
   2519 };
   2520 
   2521 // x86::Compiler - X86Test_FuncArgInt8
   2522 // ===================================
   2523 
   2524 class X86Test_FuncArgInt8 : public X86TestCase {
   2525 public:
   2526   X86Test_FuncArgInt8() : X86TestCase("FuncArgInt8") {}
   2527 
   2528   static void add(TestApp& app) {
   2529     app.add(new X86Test_FuncArgInt8());
   2530   }
   2531 
   2532   void compile(x86::Compiler& cc) override {
   2533     x86::Gp v0 = cc.new_gp32("v0");
   2534     x86::Gp v1 = cc.new_gp32("v1");
   2535 
   2536     FuncNode* func_node = cc.add_func(FuncSignature::build<unsigned, uint8_t, uint8_t, uint32_t>());
   2537     func_node->set_arg(0, v0);
   2538     func_node->set_arg(1, v1);
   2539 
   2540     cc.add(v0, v1);
   2541 
   2542     cc.ret(v0);
   2543     cc.end_func();
   2544   }
   2545 
   2546   bool run(void* _func, String& result, String& expect) override {
   2547     using Func = uint32_t (*)(uint8_t, uint8_t, uint32_t);
   2548     Func func = ptr_as_func<Func>(_func);
   2549 
   2550     uint32_t arg = uint32_t(uintptr_t(_func) & 0xFFFFFFFF);
   2551 
   2552     unsigned result_ret = func(uint8_t(arg & 0xFF), uint8_t(arg & 0xFF), arg);
   2553     unsigned expect_ret = (arg & 0xFF) * 2;
   2554 
   2555     result.assign_format("ret=%u", result_ret);
   2556     expect.assign_format("ret=%u", expect_ret);
   2557 
   2558     return result == expect;
   2559   }
   2560 };
   2561 
   2562 // x86::Compiler - X86Test_FuncCallBase1
   2563 // =====================================
   2564 
   2565 class X86Test_FuncCallBase1 : public X86TestCase {
   2566 public:
   2567   X86Test_FuncCallBase1() : X86TestCase("FuncCallBase1") {}
   2568 
   2569   static void add(TestApp& app) {
   2570     app.add(new X86Test_FuncCallBase1());
   2571   }
   2572 
   2573   void compile(x86::Compiler& cc) override {
   2574     x86::Gp v0 = cc.new_gp32("v0");
   2575     x86::Gp v1 = cc.new_gp32("v1");
   2576     x86::Gp v2 = cc.new_gp32("v2");
   2577 
   2578     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   2579     func_node->set_arg(0, v0);
   2580     func_node->set_arg(1, v1);
   2581     func_node->set_arg(2, v2);
   2582 
   2583     // Just do something.
   2584     cc.shl(v0, 1);
   2585     cc.shl(v1, 1);
   2586     cc.shl(v2, 1);
   2587 
   2588     // Call a function.
   2589     InvokeNode* invoke_node;
   2590     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<int, int, int, int>());
   2591     invoke_node->set_arg(0, v2);
   2592     invoke_node->set_arg(1, v1);
   2593     invoke_node->set_arg(2, v0);
   2594     invoke_node->set_ret(0, v0);
   2595 
   2596     cc.ret(v0);
   2597     cc.end_func();
   2598   }
   2599 
   2600   bool run(void* _func, String& result, String& expect) override {
   2601     using Func = int (*)(int, int, int);
   2602     Func func = ptr_as_func<Func>(_func);
   2603 
   2604     int result_ret = func(3, 2, 1);
   2605     int expect_ret = 36;
   2606 
   2607     result.assign_format("ret=%d", result_ret);
   2608     expect.assign_format("ret=%d", expect_ret);
   2609 
   2610     return result == expect;
   2611   }
   2612 
   2613   static int called_fn(int a, int b, int c) { return (a + b) * c; }
   2614 };
   2615 
   2616 // x86::Compiler - X86Test_FuncCallBase2
   2617 // =====================================
   2618 
   2619 class X86Test_FuncCallBase2 : public X86TestCase {
   2620 public:
   2621   X86Test_FuncCallBase2() : X86TestCase("FuncCallBase2") {}
   2622 
   2623   static inline constexpr uint32_t kSize = 256u;
   2624 
   2625   static void add(TestApp& app) {
   2626     app.add(new X86Test_FuncCallBase2());
   2627   }
   2628 
   2629   void compile(x86::Compiler& cc) override {
   2630     cc.add_func(FuncSignature::build<int>());
   2631 
   2632     const int kTokenSize = 32;
   2633 
   2634     x86::Mem s1 = cc.new_stack(kTokenSize, 32);
   2635     x86::Mem s2 = cc.new_stack(kTokenSize, 32);
   2636 
   2637     x86::Gp p1 = cc.new_gp_ptr("p1");
   2638     x86::Gp p2 = cc.new_gp_ptr("p2");
   2639 
   2640     x86::Gp ret = cc.new_gp32("ret");
   2641     Label L_Exit = cc.new_label();
   2642 
   2643     static const char token[kTokenSize] = "-+:|abcdefghijklmnopqrstuvwxyz|";
   2644     InvokeNode* invoke_node;
   2645 
   2646     cc.lea(p1, s1);
   2647     cc.lea(p2, s2);
   2648 
   2649     // Try to corrupt the stack if wrongly allocated.
   2650     cc.invoke(Out(invoke_node), imm((void*)memcpy), FuncSignature::build<void*, void*, void*, size_t>());
   2651     invoke_node->set_arg(0, p1);
   2652     invoke_node->set_arg(1, imm(token));
   2653     invoke_node->set_arg(2, imm(kTokenSize));
   2654     invoke_node->set_ret(0, p1);
   2655 
   2656     cc.invoke(Out(invoke_node), imm((void*)memcpy), FuncSignature::build<void*, void*, void*, size_t>());
   2657     invoke_node->set_arg(0, p2);
   2658     invoke_node->set_arg(1, imm(token));
   2659     invoke_node->set_arg(2, imm(kTokenSize));
   2660     invoke_node->set_ret(0, p2);
   2661 
   2662     cc.invoke(Out(invoke_node), imm((void*)memcmp), FuncSignature::build<int, void*, void*, size_t>());
   2663     invoke_node->set_arg(0, p1);
   2664     invoke_node->set_arg(1, p2);
   2665     invoke_node->set_arg(2, imm(kTokenSize));
   2666     invoke_node->set_ret(0, ret);
   2667 
   2668     // This should be 0 on success, however, if both `p1` and `p2` were
   2669     // allocated in the same address this check will still pass.
   2670     cc.cmp(ret, 0);
   2671     cc.jnz(L_Exit);
   2672 
   2673     // Checks whether `p1` and `p2` are different (must be).
   2674     cc.xor_(ret, ret);
   2675     cc.cmp(p1, p2);
   2676     cc.setz(ret.r8());
   2677 
   2678     cc.bind(L_Exit);
   2679     cc.ret(ret);
   2680     cc.end_func();
   2681   }
   2682 
   2683   bool run(void* _func, String& result, String& expect) override {
   2684     using Func = int (*)(void);
   2685     Func func = ptr_as_func<Func>(_func);
   2686 
   2687     int result_ret = func();
   2688     int expect_ret = 0; // Must be zero, stack addresses must be different.
   2689 
   2690     result.assign_int(result_ret);
   2691     expect.assign_int(expect_ret);
   2692 
   2693     return result == expect;
   2694   }
   2695 };
   2696 
   2697 // x86::Compiler - X86Test_FuncCallStd
   2698 // ===================================
   2699 
   2700 class X86Test_FuncCallStd : public X86TestCase {
   2701 public:
   2702   X86Test_FuncCallStd() : X86TestCase("FuncCallStd") {}
   2703 
   2704   static void add(TestApp& app) {
   2705     app.add(new X86Test_FuncCallStd());
   2706   }
   2707 
   2708   void compile(x86::Compiler& cc) override {
   2709     x86::Gp x = cc.new_gp32("x");
   2710     x86::Gp y = cc.new_gp32("y");
   2711     x86::Gp z = cc.new_gp32("z");
   2712 
   2713     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   2714     func_node->set_arg(0, x);
   2715     func_node->set_arg(1, y);
   2716     func_node->set_arg(2, z);
   2717 
   2718     InvokeNode* invoke_node;
   2719     cc.invoke(Out(invoke_node),
   2720       imm((void*)called_fn),
   2721       FuncSignature::build<int, int, int, int>(CallConvId::kStdCall));
   2722     invoke_node->set_arg(0, x);
   2723     invoke_node->set_arg(1, y);
   2724     invoke_node->set_arg(2, z);
   2725     invoke_node->set_ret(0, x);
   2726 
   2727     cc.ret(x);
   2728     cc.end_func();
   2729   }
   2730 
   2731   bool run(void* _func, String& result, String& expect) override {
   2732     using Func = int (*)(int, int, int);
   2733     Func func = ptr_as_func<Func>(_func);
   2734 
   2735     int result_ret = func(1, 42, 3);
   2736     int expect_ret = called_fn(1, 42, 3);
   2737 
   2738     result.assign_format("ret=%d", result_ret);
   2739     expect.assign_format("ret=%d", expect_ret);
   2740 
   2741     return result == expect;
   2742   }
   2743 
   2744   // STDCALL function that is called inside the generated one.
   2745   static int ASMJIT_STDCALL called_fn(int a, int b, int c) noexcept {
   2746     return (a + b) * c;
   2747   }
   2748 };
   2749 
   2750 // x86::Compiler - X86Test_FuncCallFast
   2751 // ====================================
   2752 
   2753 class X86Test_FuncCallFast : public X86TestCase {
   2754 public:
   2755   X86Test_FuncCallFast() : X86TestCase("FuncCallFast") {}
   2756 
   2757   static void add(TestApp& app) {
   2758     app.add(new X86Test_FuncCallFast());
   2759   }
   2760 
   2761   void compile(x86::Compiler& cc) override {
   2762     x86::Gp var = cc.new_gp32("var");
   2763 
   2764     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int>());
   2765     func_node->set_arg(0, var);
   2766 
   2767     InvokeNode* invoke_node;
   2768 
   2769     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<int, int>(CallConvId::kFastCall));
   2770     invoke_node->set_arg(0, var);
   2771     invoke_node->set_ret(0, var);
   2772 
   2773     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<int, int>(CallConvId::kFastCall));
   2774     invoke_node->set_arg(0, var);
   2775     invoke_node->set_ret(0, var);
   2776 
   2777     cc.ret(var);
   2778     cc.end_func();
   2779   }
   2780 
   2781   bool run(void* _func, String& result, String& expect) override {
   2782     using Func = int (*)(int);
   2783     Func func = ptr_as_func<Func>(_func);
   2784 
   2785     int result_ret = func(9);
   2786     int expect_ret = (9 * 9) * (9 * 9);
   2787 
   2788     result.assign_format("ret=%d", result_ret);
   2789     expect.assign_format("ret=%d", expect_ret);
   2790 
   2791     return result == expect;
   2792   }
   2793 
   2794   // FASTCALL function that is called inside the generated one.
   2795   static int ASMJIT_FASTCALL called_fn(int a) noexcept {
   2796     return a * a;
   2797   }
   2798 };
   2799 
   2800 // x86::Compiler - X86Test_FuncCallSIMD
   2801 // ====================================
   2802 
   2803 #if ASMJIT_ARCH_X86
   2804 class X86Test_FuncCallSIMD : public X86TestCase {
   2805 public:
   2806   bool _use_vector_call;
   2807 
   2808   X86Test_FuncCallSIMD(bool use_vector_call)
   2809     : X86TestCase(),
   2810       _use_vector_call(use_vector_call) {
   2811     _name.assign_format("FuncCallSIMD {%s}", _use_vector_call ? "__vectorcall" : "__cdecl");
   2812   }
   2813 
   2814   static void add(TestApp& app) {
   2815     app.add(new X86Test_FuncCallSIMD(false));
   2816 #ifdef _MSC_VER
   2817     app.add(new X86Test_FuncCallSIMD(true));
   2818 #endif
   2819   }
   2820 
   2821   void compile(x86::Compiler& cc) override {
   2822     FuncNode* func_node = cc.add_func(FuncSignature::build<void, void*, const void*, const void*>());
   2823 
   2824     x86::Gp result_ptr = cc.new_gp_ptr("result_ptr");
   2825     x86::Gp a_ptr = cc.new_gp_ptr("a_ptr");
   2826     x86::Gp b_ptr = cc.new_gp_ptr("b_ptr");
   2827     x86::Gp p_fn = cc.new_gp_ptr("p_fn");
   2828 
   2829     x86::Vec xmm_a = cc.new_xmm("xmm_a");
   2830     x86::Vec xmm_b = cc.new_xmm("xmm_b");
   2831 
   2832     func_node->set_arg(0, result_ptr);
   2833     func_node->set_arg(1, a_ptr);
   2834     func_node->set_arg(2, b_ptr);
   2835 
   2836     CallConvId call_conv_id = CallConvId::kCDecl;
   2837     Imm p_fn_imm = imm((void*)called_fn_cdecl);
   2838 
   2839 #ifdef _MSC_VER
   2840     if (_use_vector_call) {
   2841       call_conv_id = CallConvId::kVectorCall;
   2842       p_fn_imm = imm((void*)called_fn_vectorcall);
   2843     }
   2844 #endif
   2845 
   2846     cc.mov(p_fn, p_fn_imm);
   2847     cc.movdqu(xmm_a, x86::ptr(a_ptr));
   2848     cc.movdqu(xmm_b, x86::ptr(b_ptr));
   2849 
   2850     InvokeNode* invoke_node;
   2851     cc.invoke(Out(invoke_node), p_fn, FuncSignature::build<Type::Vec128, Type::Vec128, Type::Vec128>(call_conv_id));
   2852 
   2853     invoke_node->set_arg(0, xmm_a);
   2854     invoke_node->set_arg(1, xmm_b);
   2855     invoke_node->set_ret(0, xmm_a);
   2856 
   2857     cc.movdqu(x86::ptr(result_ptr), xmm_a);
   2858 
   2859     cc.end_func();
   2860   }
   2861 
   2862   bool run(void* _func, String& result, String& expect) override {
   2863     using Func = void (*)(void*, const void*, const void*);
   2864     Func func = ptr_as_func<Func>(_func);
   2865 
   2866     uint8_t a_data[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
   2867     uint8_t b_data[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
   2868 
   2869     uint8_t r_data[16] {};
   2870     uint8_t e_data[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
   2871 
   2872     func(r_data, a_data, b_data);
   2873 
   2874     result.append_hex(r_data, 16);
   2875     expect.append_hex(e_data, 16);
   2876 
   2877     return result == expect;
   2878   }
   2879 
   2880   static __m128i called_fn_cdecl(__m128i a, __m128i b) {
   2881     return _mm_add_epi8(a, b);
   2882   }
   2883 
   2884 #ifdef _MSC_VER
   2885   static __m128i __vectorcall called_fn_vectorcall(__m128i a, __m128i b) {
   2886     return _mm_add_epi8(a, b);
   2887   }
   2888 #endif
   2889 };
   2890 #endif // ASMJIT_ARCH_X86
   2891 
   2892 // x86::Compiler - X86Test_FuncCallLight
   2893 // =====================================
   2894 
   2895 class X86Test_FuncCallLight : public X86TestCase {
   2896 public:
   2897   X86Test_FuncCallLight() : X86TestCase("FuncCallLight") {}
   2898 
   2899   static void add(TestApp& app) {
   2900     app.add(new X86Test_FuncCallLight());
   2901   }
   2902 
   2903   void compile(x86::Compiler& cc) override {
   2904     FuncSignature f1_signature = FuncSignature::build<void, const void*, const void*, const void*, const void*, void*>();
   2905     FuncSignature f2_signature = FuncSignature::build<Type::Vec128, Type::Vec128, Type::Vec128>(CallConvId::kLightCall2);
   2906 
   2907     FuncNode* f1_node = cc.new_func(f1_signature);
   2908     FuncNode* f2_node = cc.new_func(f2_signature);
   2909 
   2910     {
   2911       x86::Gp a_ptr = cc.new_gp_ptr("a_ptr");
   2912       x86::Gp b_ptr = cc.new_gp_ptr("b_ptr");
   2913       x86::Gp c_ptr = cc.new_gp_ptr("c_ptr");
   2914       x86::Gp d_ptr = cc.new_gp_ptr("d_ptr");
   2915       x86::Gp p_out = cc.new_gp_ptr("p_out");
   2916 
   2917       x86::Vec xmm_a = cc.new_xmm("xmm_a");
   2918       x86::Vec xmm_b = cc.new_xmm("xmm_b");
   2919       x86::Vec xmm_c = cc.new_xmm("xmm_c");
   2920       x86::Vec xmm_d = cc.new_xmm("xmm_d");
   2921 
   2922       cc.add_func(f1_node);
   2923       f1_node->set_arg(0, a_ptr);
   2924       f1_node->set_arg(1, b_ptr);
   2925       f1_node->set_arg(2, c_ptr);
   2926       f1_node->set_arg(3, d_ptr);
   2927       f1_node->set_arg(4, p_out);
   2928 
   2929       cc.movups(xmm_a, x86::ptr(a_ptr));
   2930       cc.movups(xmm_b, x86::ptr(b_ptr));
   2931       cc.movups(xmm_c, x86::ptr(c_ptr));
   2932       cc.movups(xmm_d, x86::ptr(d_ptr));
   2933 
   2934       x86::Vec xmm_x = cc.new_xmm("xmm_x");
   2935       x86::Vec xmm_y = cc.new_xmm("xmm_y");
   2936 
   2937       InvokeNode* invoke_node;
   2938 
   2939       cc.invoke(Out(invoke_node), f2_node->label(), f2_signature);
   2940       invoke_node->set_arg(0, xmm_a);
   2941       invoke_node->set_arg(1, xmm_b);
   2942       invoke_node->set_ret(0, xmm_x);
   2943 
   2944       cc.invoke(Out(invoke_node), f2_node->label(), f2_signature);
   2945       invoke_node->set_arg(0, xmm_c);
   2946       invoke_node->set_arg(1, xmm_d);
   2947       invoke_node->set_ret(0, xmm_y);
   2948 
   2949       cc.pmullw(xmm_x, xmm_y);
   2950       cc.movups(x86::ptr(p_out), xmm_x);
   2951 
   2952       cc.end_func();
   2953     }
   2954 
   2955     {
   2956       x86::Vec xmm_a = cc.new_xmm("xmm_a");
   2957       x86::Vec xmm_b = cc.new_xmm("xmm_b");
   2958 
   2959       cc.add_func(f2_node);
   2960       f2_node->set_arg(0, xmm_a);
   2961       f2_node->set_arg(1, xmm_b);
   2962       cc.paddw(xmm_a, xmm_b);
   2963       cc.ret(xmm_a);
   2964       cc.end_func();
   2965     }
   2966   }
   2967 
   2968   bool run(void* _func, String& result, String& expect) override {
   2969     using Func = void (*)(const void*, const void*, const void*, const void*, void*);
   2970 
   2971     Func func = ptr_as_func<Func>(_func);
   2972 
   2973     int16_t a[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
   2974     int16_t b[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
   2975     int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 };
   2976     int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 };
   2977 
   2978     int16_t o[8] {};
   2979     int oexp = 7 * 3;
   2980 
   2981     func(a, b, c, d, o);
   2982 
   2983     result.assign_format("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]);
   2984     expect.assign_format("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", oexp, oexp, oexp, oexp, oexp, oexp, oexp, oexp);
   2985 
   2986     return result == expect;
   2987   }
   2988 };
   2989 
   2990 // x86::Compiler - X86Test_FuncCallManyArgs
   2991 // ========================================
   2992 
   2993 class X86Test_FuncCallManyArgs : public X86TestCase {
   2994 public:
   2995   X86Test_FuncCallManyArgs() : X86TestCase("FuncCallManyArgs") {}
   2996 
   2997   static void add(TestApp& app) {
   2998     app.add(new X86Test_FuncCallManyArgs());
   2999   }
   3000 
   3001   static int called_fn(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
   3002     return (a * b * c * d * e) + (f * g * h * i * j);
   3003   }
   3004 
   3005   void compile(x86::Compiler& cc) override {
   3006     cc.add_func(FuncSignature::build<int>());
   3007 
   3008     // Prepare.
   3009     x86::Gp va = cc.new_gp32("va");
   3010     x86::Gp vb = cc.new_gp32("vb");
   3011     x86::Gp vc = cc.new_gp32("vc");
   3012     x86::Gp vd = cc.new_gp32("vd");
   3013     x86::Gp ve = cc.new_gp32("ve");
   3014     x86::Gp vf = cc.new_gp32("vf");
   3015     x86::Gp vg = cc.new_gp32("vg");
   3016     x86::Gp vh = cc.new_gp32("vh");
   3017     x86::Gp vi = cc.new_gp32("vi");
   3018     x86::Gp vj = cc.new_gp32("vj");
   3019 
   3020     cc.mov(va, 0x03);
   3021     cc.mov(vb, 0x12);
   3022     cc.mov(vc, 0xA0);
   3023     cc.mov(vd, 0x0B);
   3024     cc.mov(ve, 0x2F);
   3025     cc.mov(vf, 0x02);
   3026     cc.mov(vg, 0x0C);
   3027     cc.mov(vh, 0x12);
   3028     cc.mov(vi, 0x18);
   3029     cc.mov(vj, 0x1E);
   3030 
   3031     // Function call.
   3032     InvokeNode* invoke_node;
   3033     cc.invoke(Out(invoke_node),
   3034       imm((void*)called_fn),
   3035       FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
   3036     invoke_node->set_arg(0, va);
   3037     invoke_node->set_arg(1, vb);
   3038     invoke_node->set_arg(2, vc);
   3039     invoke_node->set_arg(3, vd);
   3040     invoke_node->set_arg(4, ve);
   3041     invoke_node->set_arg(5, vf);
   3042     invoke_node->set_arg(6, vg);
   3043     invoke_node->set_arg(7, vh);
   3044     invoke_node->set_arg(8, vi);
   3045     invoke_node->set_arg(9, vj);
   3046     invoke_node->set_ret(0, va);
   3047 
   3048     cc.ret(va);
   3049     cc.end_func();
   3050   }
   3051 
   3052   bool run(void* _func, String& result, String& expect) override {
   3053     using Func = int (*)(void);
   3054     Func func = ptr_as_func<Func>(_func);
   3055 
   3056     int result_ret = func();
   3057     int expect_ret = called_fn(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
   3058 
   3059     result.assign_format("ret=%d", result_ret);
   3060     expect.assign_format("ret=%d", expect_ret);
   3061 
   3062     return result == expect;
   3063   }
   3064 };
   3065 
   3066 // x86::Compiler - X86Test_FuncCallDuplicateArgs
   3067 // =============================================
   3068 
   3069 class X86Test_FuncCallDuplicateArgs : public X86TestCase {
   3070 public:
   3071   X86Test_FuncCallDuplicateArgs() : X86TestCase("FuncCallDuplicateArgs") {}
   3072 
   3073   static void add(TestApp& app) {
   3074     app.add(new X86Test_FuncCallDuplicateArgs());
   3075   }
   3076 
   3077   static int called_fn(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
   3078     return (a * b * c * d * e) + (f * g * h * i * j);
   3079   }
   3080 
   3081   void compile(x86::Compiler& cc) override {
   3082     cc.add_func(FuncSignature::build<int>());
   3083 
   3084     // Prepare.
   3085     x86::Gp a = cc.new_gp32("a");
   3086     cc.mov(a, 3);
   3087 
   3088     // Call function.
   3089     InvokeNode* invoke_node;
   3090     cc.invoke(Out(invoke_node),
   3091       imm((void*)called_fn),
   3092       FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
   3093     invoke_node->set_arg(0, a);
   3094     invoke_node->set_arg(1, a);
   3095     invoke_node->set_arg(2, a);
   3096     invoke_node->set_arg(3, a);
   3097     invoke_node->set_arg(4, a);
   3098     invoke_node->set_arg(5, a);
   3099     invoke_node->set_arg(6, a);
   3100     invoke_node->set_arg(7, a);
   3101     invoke_node->set_arg(8, a);
   3102     invoke_node->set_arg(9, a);
   3103     invoke_node->set_ret(0, a);
   3104 
   3105     cc.ret(a);
   3106     cc.end_func();
   3107   }
   3108 
   3109   bool run(void* _func, String& result, String& expect) override {
   3110     using Func = int (*)(void);
   3111     Func func = ptr_as_func<Func>(_func);
   3112 
   3113     int result_ret = func();
   3114     int expect_ret = called_fn(3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
   3115 
   3116     result.assign_format("ret=%d", result_ret);
   3117     expect.assign_format("ret=%d", expect_ret);
   3118 
   3119     return result == expect;
   3120   }
   3121 };
   3122 
   3123 // x86::Compiler - X86Test_FuncCallImmArgs
   3124 // =======================================
   3125 
   3126 class X86Test_FuncCallImmArgs : public X86TestCase {
   3127 public:
   3128   X86Test_FuncCallImmArgs() : X86TestCase("FuncCallImmArgs") {}
   3129 
   3130   static void add(TestApp& app) {
   3131     app.add(new X86Test_FuncCallImmArgs());
   3132   }
   3133 
   3134   void compile(x86::Compiler& cc) override {
   3135     cc.add_func(FuncSignature::build<int>());
   3136 
   3137     // Prepare.
   3138     x86::Gp rv = cc.new_gp32("rv");
   3139 
   3140     // Call function.
   3141     InvokeNode* invoke_node;
   3142     cc.invoke(Out(invoke_node),
   3143       imm((void*)X86Test_FuncCallManyArgs::called_fn),
   3144       FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
   3145 
   3146     invoke_node->set_arg(0, imm(0x03));
   3147     invoke_node->set_arg(1, imm(0x12));
   3148     invoke_node->set_arg(2, imm(0xA0));
   3149     invoke_node->set_arg(3, imm(0x0B));
   3150     invoke_node->set_arg(4, imm(0x2F));
   3151     invoke_node->set_arg(5, imm(0x02));
   3152     invoke_node->set_arg(6, imm(0x0C));
   3153     invoke_node->set_arg(7, imm(0x12));
   3154     invoke_node->set_arg(8, imm(0x18));
   3155     invoke_node->set_arg(9, imm(0x1E));
   3156     invoke_node->set_ret(0, rv);
   3157 
   3158     cc.ret(rv);
   3159     cc.end_func();
   3160   }
   3161 
   3162   bool run(void* _func, String& result, String& expect) override {
   3163     using Func = int (*)(void);
   3164     Func func = ptr_as_func<Func>(_func);
   3165 
   3166     int result_ret = func();
   3167     int expect_ret = X86Test_FuncCallManyArgs::called_fn(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
   3168 
   3169     result.assign_format("ret=%d", result_ret);
   3170     expect.assign_format("ret=%d", expect_ret);
   3171 
   3172     return result == expect;
   3173   }
   3174 };
   3175 
   3176 // x86::Compiler - X86Test_FuncCallPtrArgs
   3177 // =======================================
   3178 
   3179 class X86Test_FuncCallPtrArgs : public X86TestCase {
   3180 public:
   3181   X86Test_FuncCallPtrArgs() : X86TestCase("FuncCallPtrArgs") {}
   3182 
   3183   static void add(TestApp& app) {
   3184     app.add(new X86Test_FuncCallPtrArgs());
   3185   }
   3186 
   3187   static int called_fn(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j) {
   3188     return int((intptr_t)a) +
   3189            int((intptr_t)b) +
   3190            int((intptr_t)c) +
   3191            int((intptr_t)d) +
   3192            int((intptr_t)e) +
   3193            int((intptr_t)f) +
   3194            int((intptr_t)g) +
   3195            int((intptr_t)h) +
   3196            int((intptr_t)i) +
   3197            int((intptr_t)j) ;
   3198   }
   3199 
   3200   void compile(x86::Compiler& cc) override {
   3201     cc.add_func(FuncSignature::build<int>());
   3202 
   3203     // Prepare.
   3204     x86::Gp rv = cc.new_gp32("rv");
   3205 
   3206     // Call function.
   3207     InvokeNode* invoke_node;
   3208     cc.invoke(Out(invoke_node),
   3209       imm((void*)called_fn),
   3210       FuncSignature::build<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>());
   3211 
   3212     invoke_node->set_arg(0, imm(0x01));
   3213     invoke_node->set_arg(1, imm(0x02));
   3214     invoke_node->set_arg(2, imm(0x03));
   3215     invoke_node->set_arg(3, imm(0x04));
   3216     invoke_node->set_arg(4, imm(0x05));
   3217     invoke_node->set_arg(5, imm(0x06));
   3218     invoke_node->set_arg(6, imm(0x07));
   3219     invoke_node->set_arg(7, imm(0x08));
   3220     invoke_node->set_arg(8, imm(0x09));
   3221     invoke_node->set_arg(9, imm(0x0A));
   3222     invoke_node->set_ret(0, rv);
   3223 
   3224     cc.ret(rv);
   3225     cc.end_func();
   3226   }
   3227 
   3228   bool run(void* _func, String& result, String& expect) override {
   3229     using Func = int (*)(void);
   3230     Func func = ptr_as_func<Func>(_func);
   3231 
   3232     int result_ret = func();
   3233     int expect_ret = 55;
   3234 
   3235     result.assign_format("ret=%d", result_ret);
   3236     expect.assign_format("ret=%d", expect_ret);
   3237 
   3238     return result == expect;
   3239   }
   3240 };
   3241 
   3242 // x86::Compiler - X86Test_FuncCallRefArgs
   3243 // =======================================
   3244 
   3245 class X86Test_FuncCallRefArgs : public X86TestCase {
   3246 public:
   3247   X86Test_FuncCallRefArgs() : X86TestCase("FuncCallRefArgs") {}
   3248 
   3249   static void add(TestApp& app) {
   3250     app.add(new X86Test_FuncCallRefArgs());
   3251   }
   3252 
   3253   static int called_fn(int& a, int& b, int& c, int& d) {
   3254     a += a;
   3255     b += b;
   3256     c += c;
   3257     d += d;
   3258     return a + b + c + d;
   3259   }
   3260 
   3261   void compile(x86::Compiler& cc) override {
   3262     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int&, int&, int&, int&>());
   3263 
   3264     // Prepare.
   3265     x86::Gp arg1 = cc.new_gp32();
   3266     x86::Gp arg2 = cc.new_gp32();
   3267     x86::Gp arg3 = cc.new_gp32();
   3268     x86::Gp arg4 = cc.new_gp32();
   3269     x86::Gp rv = cc.new_gp32("rv");
   3270 
   3271     func_node->set_arg(0, arg1);
   3272     func_node->set_arg(1, arg2);
   3273     func_node->set_arg(2, arg3);
   3274     func_node->set_arg(3, arg4);
   3275 
   3276     // Call function.
   3277     InvokeNode* invoke_node;
   3278     cc.invoke(Out(invoke_node),
   3279       imm((void*)called_fn),
   3280       FuncSignature::build<int, int&, int&, int&, int&>());
   3281 
   3282     invoke_node->set_arg(0, arg1);
   3283     invoke_node->set_arg(1, arg2);
   3284     invoke_node->set_arg(2, arg3);
   3285     invoke_node->set_arg(3, arg4);
   3286     invoke_node->set_ret(0, rv);
   3287 
   3288     cc.ret(rv);
   3289     cc.end_func();
   3290   }
   3291 
   3292   bool run(void* _func, String& result, String& expect) override {
   3293     using Func = int (*)(int&, int&, int&, int&);
   3294     Func func = ptr_as_func<Func>(_func);
   3295 
   3296     int inputs[4] = { 1, 2, 3, 4 };
   3297     int outputs[4] = { 2, 4, 6, 8 };
   3298     int result_ret = func(inputs[0], inputs[1], inputs[2], inputs[3]);
   3299     int expect_ret = 20;
   3300 
   3301     result.assign_format("ret={%08X %08X %08X %08X %08X}", result_ret, inputs[0], inputs[1], inputs[2], inputs[3]);
   3302     expect.assign_format("ret={%08X %08X %08X %08X %08X}", expect_ret, outputs[0], outputs[1], outputs[2], outputs[3]);
   3303 
   3304     return result == expect;
   3305   }
   3306 };
   3307 
   3308 // x86::Compiler - X86Test_FuncCallFloatAsXmmRet
   3309 // =============================================
   3310 
   3311 class X86Test_FuncCallFloatAsXmmRet : public X86TestCase {
   3312 public:
   3313   X86Test_FuncCallFloatAsXmmRet() : X86TestCase("FuncCallFloatAsXmmRet") {}
   3314 
   3315   static void add(TestApp& app) {
   3316     app.add(new X86Test_FuncCallFloatAsXmmRet());
   3317   }
   3318 
   3319   static float called_fn(float a, float b) {
   3320     return a * b;
   3321   }
   3322 
   3323   void compile(x86::Compiler& cc) override {
   3324     FuncNode* func_node = cc.add_func(FuncSignature::build<float, float, float>());
   3325 
   3326     x86::Vec a = cc.new_xmm_ss("a");
   3327     x86::Vec b = cc.new_xmm_ss("b");
   3328     x86::Vec ret = cc.new_xmm_ss("ret");
   3329 
   3330     func_node->set_arg(0, a);
   3331     func_node->set_arg(1, b);
   3332 
   3333     // Call function.
   3334     InvokeNode* invoke_node;
   3335     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<float, float, float>());
   3336     invoke_node->set_arg(0, a);
   3337     invoke_node->set_arg(1, b);
   3338     invoke_node->set_ret(0, ret);
   3339 
   3340     cc.ret(ret);
   3341     cc.end_func();
   3342   }
   3343 
   3344   bool run(void* _func, String& result, String& expect) override {
   3345     using Func = float (*)(float, float);
   3346     Func func = ptr_as_func<Func>(_func);
   3347 
   3348     float result_ret = func(15.5f, 2.0f);
   3349     float expect_ret = called_fn(15.5f, 2.0f);
   3350 
   3351     result.assign_format("ret=%g", double(result_ret));
   3352     expect.assign_format("ret=%g", double(expect_ret));
   3353 
   3354     return result == expect;
   3355   }
   3356 };
   3357 
   3358 // x86::Compiler - X86Test_FuncCallDoubleAsXmmRet
   3359 // ==============================================
   3360 
   3361 class X86Test_FuncCallDoubleAsXmmRet : public X86TestCase {
   3362 public:
   3363   X86Test_FuncCallDoubleAsXmmRet() : X86TestCase("FuncCallDoubleAsXmmRet") {}
   3364 
   3365   static void add(TestApp& app) {
   3366     app.add(new X86Test_FuncCallDoubleAsXmmRet());
   3367   }
   3368 
   3369   static double called_fn(double a, double b) {
   3370     return a * b;
   3371   }
   3372 
   3373   void compile(x86::Compiler& cc) override {
   3374     FuncNode* func_node = cc.add_func(FuncSignature::build<double, double, double>());
   3375 
   3376     x86::Vec a = cc.new_xmm_sd("a");
   3377     x86::Vec b = cc.new_xmm_sd("b");
   3378     x86::Vec ret = cc.new_xmm_sd("ret");
   3379 
   3380     func_node->set_arg(0, a);
   3381     func_node->set_arg(1, b);
   3382 
   3383     InvokeNode* invoke_node;
   3384     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<double, double, double>());
   3385     invoke_node->set_arg(0, a);
   3386     invoke_node->set_arg(1, b);
   3387     invoke_node->set_ret(0, ret);
   3388 
   3389     cc.ret(ret);
   3390     cc.end_func();
   3391   }
   3392 
   3393   bool run(void* _func, String& result, String& expect) override {
   3394     using Func = double (*)(double, double);
   3395     Func func = ptr_as_func<Func>(_func);
   3396 
   3397     double result_ret = func(15.5, 2.0);
   3398     double expect_ret = called_fn(15.5, 2.0);
   3399 
   3400     result.assign_format("ret=%g", result_ret);
   3401     expect.assign_format("ret=%g", expect_ret);
   3402 
   3403     return result == expect;
   3404   }
   3405 };
   3406 
   3407 // x86::Compiler - X86Test_FuncCallConditional
   3408 // ===========================================
   3409 
   3410 class X86Test_FuncCallConditional : public X86TestCase {
   3411 public:
   3412   X86Test_FuncCallConditional() : X86TestCase("FuncCallConditional") {}
   3413 
   3414   static void add(TestApp& app) {
   3415     app.add(new X86Test_FuncCallConditional());
   3416   }
   3417 
   3418   void compile(x86::Compiler& cc) override {
   3419     x86::Gp x = cc.new_gp32("x");
   3420     x86::Gp y = cc.new_gp32("y");
   3421     x86::Gp op = cc.new_gp32("op");
   3422 
   3423     InvokeNode* invoke_node;
   3424     x86::Gp result;
   3425 
   3426     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   3427     func_node->set_arg(0, x);
   3428     func_node->set_arg(1, y);
   3429     func_node->set_arg(2, op);
   3430 
   3431     Label op_add = cc.new_label();
   3432     Label op_mul = cc.new_label();
   3433 
   3434     cc.cmp(op, 0);
   3435     cc.jz(op_add);
   3436     cc.cmp(op, 1);
   3437     cc.jz(op_mul);
   3438 
   3439     result = cc.new_gp32("result_0");
   3440     cc.mov(result, 0);
   3441     cc.ret(result);
   3442 
   3443     cc.bind(op_add);
   3444     result = cc.new_gp32("result_1");
   3445 
   3446     cc.invoke(Out(invoke_node), (uint64_t)called_fn_add, FuncSignature::build<int, int, int>());
   3447     invoke_node->set_arg(0, x);
   3448     invoke_node->set_arg(1, y);
   3449     invoke_node->set_ret(0, result);
   3450     cc.ret(result);
   3451 
   3452     cc.bind(op_mul);
   3453     result = cc.new_gp32("result_2");
   3454 
   3455     cc.invoke(Out(invoke_node), (uint64_t)called_fn_mul, FuncSignature::build<int, int, int>());
   3456     invoke_node->set_arg(0, x);
   3457     invoke_node->set_arg(1, y);
   3458     invoke_node->set_ret(0, result);
   3459 
   3460     cc.ret(result);
   3461     cc.end_func();
   3462   }
   3463 
   3464   bool run(void* _func, String& result, String& expect) override {
   3465     using Func = int (*)(int, int, int);
   3466     Func func = ptr_as_func<Func>(_func);
   3467 
   3468     int arg1 = 4;
   3469     int arg2 = 8;
   3470 
   3471     int result_add = func(arg1, arg2, 0);
   3472     int expect_add = called_fn_add(arg1, arg2);
   3473 
   3474     int result_mul = func(arg1, arg2, 1);
   3475     int expect_mul = called_fn_mul(arg1, arg2);
   3476 
   3477     result.assign_format("ret={add=%d, mul=%d}", result_add, result_mul);
   3478     expect.assign_format("ret={add=%d, mul=%d}", expect_add, expect_mul);
   3479 
   3480     return (result_add == expect_add) && (result_mul == expect_mul);
   3481   }
   3482 
   3483   static int called_fn_add(int x, int y) { return x + y; }
   3484   static int called_fn_mul(int x, int y) { return x * y; }
   3485 };
   3486 
   3487 // x86::Compiler - X86Test_FuncCallMultiple
   3488 // ========================================
   3489 
   3490 class X86Test_FuncCallMultiple : public X86TestCase {
   3491 public:
   3492   X86Test_FuncCallMultiple() : X86TestCase("FuncCallMultiple") {}
   3493 
   3494   static void add(TestApp& app) {
   3495     app.add(new X86Test_FuncCallMultiple());
   3496   }
   3497 
   3498   static int ASMJIT_FASTCALL called_fn(int* p_int, int index) {
   3499     return p_int[index];
   3500   }
   3501 
   3502   void compile(x86::Compiler& cc) override {
   3503     unsigned int i;
   3504 
   3505     x86::Gp buf = cc.new_gp_ptr("buf");
   3506     x86::Gp acc0 = cc.new_gp32("acc0");
   3507     x86::Gp acc1 = cc.new_gp32("acc1");
   3508 
   3509     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int*>());
   3510     func_node->set_arg(0, buf);
   3511 
   3512     cc.mov(acc0, 0);
   3513     cc.mov(acc1, 0);
   3514 
   3515     for (i = 0; i < 4; i++) {
   3516       x86::Gp ret = cc.new_gp32("ret");
   3517       x86::Gp ptr = cc.new_gp_ptr("ptr");
   3518       x86::Gp idx = cc.new_gp32("idx");
   3519       InvokeNode* invoke_node;
   3520 
   3521       cc.mov(ptr, buf);
   3522       cc.mov(idx, int(i));
   3523 
   3524       cc.invoke(Out(invoke_node), (uint64_t)called_fn, FuncSignature::build<int, int*, int>(CallConvId::kFastCall));
   3525       invoke_node->set_arg(0, ptr);
   3526       invoke_node->set_arg(1, idx);
   3527       invoke_node->set_ret(0, ret);
   3528 
   3529       cc.add(acc0, ret);
   3530 
   3531       cc.mov(ptr, buf);
   3532       cc.mov(idx, int(i));
   3533 
   3534       cc.invoke(Out(invoke_node), (uint64_t)called_fn, FuncSignature::build<int, int*, int>(CallConvId::kFastCall));
   3535       invoke_node->set_arg(0, ptr);
   3536       invoke_node->set_arg(1, idx);
   3537       invoke_node->set_ret(0, ret);
   3538 
   3539       cc.sub(acc1, ret);
   3540     }
   3541 
   3542     cc.add(acc0, acc1);
   3543     cc.ret(acc0);
   3544     cc.end_func();
   3545   }
   3546 
   3547   bool run(void* _func, String& result, String& expect) override {
   3548     using Func = int (*)(int*);
   3549     Func func = ptr_as_func<Func>(_func);
   3550 
   3551     int buffer[4] = { 127, 87, 23, 17 };
   3552 
   3553     int result_ret = func(buffer);
   3554     int expect_ret = 0;
   3555 
   3556     result.assign_format("ret=%d", result_ret);
   3557     expect.assign_format("ret=%d", expect_ret);
   3558 
   3559     return result == expect;
   3560   }
   3561 };
   3562 
   3563 // x86::Compiler - X86Test_FuncCallRecursive
   3564 // =========================================
   3565 
   3566 class X86Test_FuncCallRecursive : public X86TestCase {
   3567 public:
   3568   X86Test_FuncCallRecursive() : X86TestCase("FuncCallRecursive") {}
   3569 
   3570   static void add(TestApp& app) {
   3571     app.add(new X86Test_FuncCallRecursive());
   3572   }
   3573 
   3574   void compile(x86::Compiler& cc) override {
   3575     x86::Gp val = cc.new_gp32("val");
   3576     Label skip = cc.new_label();
   3577 
   3578     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int>());
   3579     func_node->set_arg(0, val);
   3580 
   3581     cc.cmp(val, 1);
   3582     cc.jle(skip);
   3583 
   3584     x86::Gp tmp = cc.new_gp32("tmp");
   3585     cc.mov(tmp, val);
   3586     cc.dec(tmp);
   3587 
   3588     InvokeNode* invoke_node;
   3589 
   3590     cc.invoke(Out(invoke_node), func_node->label(), FuncSignature::build<int, int>());
   3591     invoke_node->set_arg(0, tmp);
   3592     invoke_node->set_ret(0, tmp);
   3593     cc.mul(cc.new_gp32(), val, tmp);
   3594 
   3595     cc.bind(skip);
   3596     cc.ret(val);
   3597     cc.end_func();
   3598   }
   3599 
   3600   bool run(void* _func, String& result, String& expect) override {
   3601     using Func = int (*)(int);
   3602     Func func = ptr_as_func<Func>(_func);
   3603 
   3604     int result_ret = func(5);
   3605     int expect_ret = 1 * 2 * 3 * 4 * 5;
   3606 
   3607     result.assign_format("ret=%d", result_ret);
   3608     expect.assign_format("ret=%d", expect_ret);
   3609 
   3610     return result == expect;
   3611   }
   3612 };
   3613 
   3614 // x86::Compiler - X86Test_FuncCallVarArg1
   3615 // =======================================
   3616 
   3617 class X86Test_FuncCallVarArg1 : public X86TestCase {
   3618 public:
   3619   X86Test_FuncCallVarArg1() : X86TestCase("FuncCallVarArg1") {}
   3620 
   3621   static void add(TestApp& app) {
   3622     app.add(new X86Test_FuncCallVarArg1());
   3623   }
   3624 
   3625   void compile(x86::Compiler& cc) override {
   3626     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int, int>());
   3627 
   3628     x86::Gp a0 = cc.new_gp32("a0");
   3629     x86::Gp a1 = cc.new_gp32("a1");
   3630     x86::Gp a2 = cc.new_gp32("a2");
   3631     x86::Gp a3 = cc.new_gp32("a3");
   3632 
   3633     func_node->set_arg(0, a0);
   3634     func_node->set_arg(1, a1);
   3635     func_node->set_arg(2, a2);
   3636     func_node->set_arg(3, a3);
   3637 
   3638     // We call `int func(size_t, ...)`
   3639     //   - The `va_index` must be 1 (first argument after size_t).
   3640     //   - The full signature of varargs (int, int, int, int) must follow.
   3641     InvokeNode* invoke_node;
   3642     cc.invoke(Out(invoke_node),
   3643       imm((void*)called_fn),
   3644       FuncSignature::build<int, size_t, int, int, int, int>(CallConvId::kCDecl, 1));
   3645     invoke_node->set_arg(0, imm(4));
   3646     invoke_node->set_arg(1, a0);
   3647     invoke_node->set_arg(2, a1);
   3648     invoke_node->set_arg(3, a2);
   3649     invoke_node->set_arg(4, a3);
   3650     invoke_node->set_ret(0, a0);
   3651 
   3652     cc.ret(a0);
   3653     cc.end_func();
   3654   }
   3655 
   3656   bool run(void* _func, String& result, String& expect) override {
   3657     using Func = int (*)(int, int, int, int);
   3658     Func func = ptr_as_func<Func>(_func);
   3659 
   3660     int result_ret = func(1, 2, 3, 4);
   3661     int expect_ret = 1 + 2 + 3 + 4;
   3662 
   3663     result.assign_format("ret=%d", result_ret);
   3664     expect.assign_format("ret=%d", expect_ret);
   3665 
   3666     return result == expect;
   3667   }
   3668 
   3669   static int called_fn(size_t n, ...) {
   3670     int sum = 0;
   3671     va_list ap;
   3672     va_start(ap, n);
   3673     for (size_t i = 0; i < n; i++) {
   3674       int arg = va_arg(ap, int);
   3675       sum += arg;
   3676     }
   3677     va_end(ap);
   3678     return sum;
   3679   }
   3680 };
   3681 
   3682 // x86::Compiler - X86Test_FuncCallVarArg2
   3683 // =======================================
   3684 
   3685 class X86Test_FuncCallVarArg2 : public X86TestCase {
   3686 public:
   3687   X86Test_FuncCallVarArg2() : X86TestCase("FuncCallVarArg2") {}
   3688 
   3689   static void add(TestApp& app) {
   3690     app.add(new X86Test_FuncCallVarArg2());
   3691   }
   3692 
   3693   void compile(x86::Compiler& cc) override {
   3694     FuncNode* func_node = cc.add_func(FuncSignature::build<double, double, double, double, double>());
   3695 
   3696     x86::Vec a0 = cc.new_xmm_sd("a0");
   3697     x86::Vec a1 = cc.new_xmm_sd("a1");
   3698     x86::Vec a2 = cc.new_xmm_sd("a2");
   3699     x86::Vec a3 = cc.new_xmm_sd("a3");
   3700 
   3701     func_node->set_arg(0, a0);
   3702     func_node->set_arg(1, a1);
   3703     func_node->set_arg(2, a2);
   3704     func_node->set_arg(3, a3);
   3705 
   3706     // We call `double func(size_t, ...)`
   3707     //   - The `va_index` must be 1 (first argument after size_t).
   3708     //   - The full signature of varargs (double, double, double, double) must follow.
   3709     InvokeNode* invoke_node;
   3710     cc.invoke(Out(invoke_node),
   3711       imm((void*)called_fn),
   3712       FuncSignature::build<double, size_t, double, double, double, double>(CallConvId::kCDecl, 1));
   3713     invoke_node->set_arg(0, imm(4));
   3714     invoke_node->set_arg(1, a0);
   3715     invoke_node->set_arg(2, a1);
   3716     invoke_node->set_arg(3, a2);
   3717     invoke_node->set_arg(4, a3);
   3718     invoke_node->set_ret(0, a0);
   3719 
   3720     cc.ret(a0);
   3721     cc.end_func();
   3722   }
   3723 
   3724   bool run(void* _func, String& result, String& expect) override {
   3725     using Func = double (*)(double, double, double, double);
   3726     Func func = ptr_as_func<Func>(_func);
   3727 
   3728     double result_ret = func(1.0, 2.0, 3.0, 4.0);
   3729     double expect_ret = 1.0 + 2.0 + 3.0 + 4.0;
   3730 
   3731     result.assign_format("ret=%f", result_ret);
   3732     expect.assign_format("ret=%f", expect_ret);
   3733 
   3734     return result == expect;
   3735   }
   3736 
   3737   static double called_fn(size_t n, ...) {
   3738     double sum = 0;
   3739     va_list ap;
   3740     va_start(ap, n);
   3741     for (size_t i = 0; i < n; i++) {
   3742       double arg = va_arg(ap, double);
   3743       sum += arg;
   3744     }
   3745     va_end(ap);
   3746     return sum;
   3747   }
   3748 };
   3749 
   3750 // x86::Compiler - X86Test_FuncCallInt64Arg
   3751 // ========================================
   3752 
   3753 class X86Test_FuncCallInt64Arg : public X86TestCase {
   3754 public:
   3755   X86Test_FuncCallInt64Arg() : X86TestCase("FuncCallInt64Arg") {}
   3756 
   3757   static void add(TestApp& app) {
   3758     app.add(new X86Test_FuncCallInt64Arg());
   3759   }
   3760 
   3761   void compile(x86::Compiler& cc) override {
   3762     FuncNode* func_node = cc.add_func(FuncSignature::build<uint64_t, uint64_t>());
   3763 
   3764     if (cc.is_64bit()) {
   3765       x86::Gp reg = cc.new_gp64();
   3766       func_node->set_arg(0, reg);
   3767       cc.add(reg, 1);
   3768       cc.ret(reg);
   3769     }
   3770     else {
   3771       x86::Gp hi = cc.new_gp32("hi");
   3772       x86::Gp lo = cc.new_gp32("lo");
   3773 
   3774       func_node->set_arg(0, 0, lo);
   3775       func_node->set_arg(0, 1, hi);
   3776 
   3777       cc.add(lo, 1);
   3778       cc.adc(hi, 0);
   3779       cc.ret(lo, hi);
   3780     }
   3781 
   3782     cc.end_func();
   3783   }
   3784 
   3785   bool run(void* _func, String& result, String& expect) override {
   3786     using Func = uint64_t (*)(uint64_t);
   3787     Func func = ptr_as_func<Func>(_func);
   3788 
   3789     uint64_t result_ret = func(uint64_t(0xFFFFFFFF));
   3790     uint64_t expect_ret = 0x100000000;
   3791 
   3792     result.assign_format("ret=%llu", (unsigned long long)result_ret);
   3793     expect.assign_format("ret=%llu", (unsigned long long)expect_ret);
   3794 
   3795     return result == expect;
   3796   }
   3797 
   3798   static double called_fn(size_t n, ...) {
   3799     double sum = 0;
   3800     va_list ap;
   3801     va_start(ap, n);
   3802     for (size_t i = 0; i < n; i++) {
   3803       double arg = va_arg(ap, double);
   3804       sum += arg;
   3805     }
   3806     va_end(ap);
   3807     return sum;
   3808   }
   3809 };
   3810 
   3811 // x86::Compiler - X86Test_FuncCallMisc1
   3812 // =====================================
   3813 
   3814 class X86Test_FuncCallMisc1 : public X86TestCase {
   3815 public:
   3816   X86Test_FuncCallMisc1() : X86TestCase("FuncCallMisc1") {}
   3817 
   3818   static void add(TestApp& app) {
   3819     app.add(new X86Test_FuncCallMisc1());
   3820   }
   3821 
   3822   static void dummy(int, int) {}
   3823 
   3824   void compile(x86::Compiler& cc) override {
   3825     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int>());
   3826 
   3827     x86::Gp a = cc.new_gp32("a");
   3828     x86::Gp b = cc.new_gp32("b");
   3829     x86::Gp r = cc.new_gp32("r");
   3830 
   3831     func_node->set_arg(0, a);
   3832     func_node->set_arg(1, b);
   3833 
   3834     InvokeNode* invoke_node;
   3835     cc.invoke(Out(invoke_node),
   3836       imm((void*)dummy),
   3837       FuncSignature::build<void, int, int>());
   3838     invoke_node->set_arg(0, a);
   3839     invoke_node->set_arg(1, b);
   3840 
   3841     cc.lea(r, x86::ptr(a, b));
   3842     cc.ret(r);
   3843 
   3844     cc.end_func();
   3845   }
   3846 
   3847   bool run(void* _func, String& result, String& expect) override {
   3848     using Func = int (*)(int, int);
   3849     Func func = ptr_as_func<Func>(_func);
   3850 
   3851     int result_ret = func(44, 199);
   3852     int expect_ret = 243;
   3853 
   3854     result.assign_format("ret=%d", result_ret);
   3855     expect.assign_format("ret=%d", expect_ret);
   3856 
   3857     return result == expect;
   3858   }
   3859 };
   3860 
   3861 // x86::Compiler - X86Test_FuncCallMisc2
   3862 // =====================================
   3863 
   3864 class X86Test_FuncCallMisc2 : public X86TestCase {
   3865 public:
   3866   X86Test_FuncCallMisc2() : X86TestCase("FuncCallMisc2") {}
   3867 
   3868   static void add(TestApp& app) {
   3869     app.add(new X86Test_FuncCallMisc2());
   3870   }
   3871 
   3872   void compile(x86::Compiler& cc) override {
   3873     FuncNode* func_node = cc.add_func(FuncSignature::build<double, const double*>());
   3874 
   3875     x86::Gp p = cc.new_gp_ptr("p");
   3876     x86::Vec arg = cc.new_xmm_sd("arg");
   3877     x86::Vec ret = cc.new_xmm_sd("ret");
   3878 
   3879     func_node->set_arg(0, p);
   3880     cc.movsd(arg, x86::ptr(p));
   3881 
   3882     InvokeNode* invoke_node;
   3883     cc.invoke(Out(invoke_node),
   3884       imm((void*)op),
   3885       FuncSignature::build<double, double>());
   3886     invoke_node->set_arg(0, arg);
   3887     invoke_node->set_ret(0, ret);
   3888 
   3889     cc.ret(ret);
   3890     cc.end_func();
   3891   }
   3892 
   3893   bool run(void* _func, String& result, String& expect) override {
   3894     using Func = double (*)(const double*);
   3895     Func func = ptr_as_func<Func>(_func);
   3896 
   3897     double arg = 2;
   3898 
   3899     double result_ret = func(&arg);
   3900     double expect_ret = op(arg);
   3901 
   3902     result.assign_format("ret=%g", result_ret);
   3903     expect.assign_format("ret=%g", expect_ret);
   3904 
   3905     return result == expect;
   3906   }
   3907 
   3908   static double op(double a) { return a * a; }
   3909 };
   3910 
   3911 // x86::Compiler - X86Test_FuncCallMisc3
   3912 // =====================================
   3913 
   3914 class X86Test_FuncCallMisc3 : public X86TestCase {
   3915 public:
   3916   X86Test_FuncCallMisc3() : X86TestCase("FuncCallMisc3") {}
   3917 
   3918   static void add(TestApp& app) {
   3919     app.add(new X86Test_FuncCallMisc3());
   3920   }
   3921 
   3922   void compile(x86::Compiler& cc) override {
   3923     FuncNode* func_node = cc.add_func(FuncSignature::build<double, const double*>());
   3924 
   3925     x86::Gp p = cc.new_gp_ptr("p");
   3926     x86::Vec arg = cc.new_xmm_sd("arg");
   3927     x86::Vec ret = cc.new_xmm_sd("ret");
   3928 
   3929     func_node->set_arg(0, p);
   3930     cc.movsd(arg, x86::ptr(p));
   3931 
   3932     InvokeNode* invoke_node;
   3933     cc.invoke(Out(invoke_node),
   3934       imm((void*)op),
   3935       FuncSignature::build<double, double>());
   3936     invoke_node->set_arg(0, arg);
   3937     invoke_node->set_ret(0, ret);
   3938 
   3939     cc.xorps(arg, arg);
   3940     cc.subsd(arg, ret);
   3941 
   3942     cc.ret(arg);
   3943     cc.end_func();
   3944   }
   3945 
   3946   bool run(void* _func, String& result, String& expect) override {
   3947     using Func = double (*)(const double*);
   3948     Func func = ptr_as_func<Func>(_func);
   3949 
   3950     double arg = 2;
   3951 
   3952     double result_ret = func(&arg);
   3953     double expect_ret = -op(arg);
   3954 
   3955     result.assign_format("ret=%g", result_ret);
   3956     expect.assign_format("ret=%g", expect_ret);
   3957 
   3958     return result == expect;
   3959   }
   3960 
   3961   static double op(double a) { return a * a; }
   3962 };
   3963 
   3964 // x86::Compiler - X86Test_FuncCallMisc4
   3965 // =====================================
   3966 
   3967 class X86Test_FuncCallMisc4 : public X86TestCase {
   3968 public:
   3969   X86Test_FuncCallMisc4() : X86TestCase("FuncCallMisc4") {}
   3970 
   3971   static void add(TestApp& app) {
   3972     app.add(new X86Test_FuncCallMisc4());
   3973   }
   3974 
   3975   void compile(x86::Compiler& cc) override {
   3976     InvokeNode* invoke_node;
   3977 
   3978     FuncSignature func_signature;
   3979     func_signature.set_call_conv_id(CallConvId::kCDecl);
   3980     func_signature.set_ret(TypeId::kFloat64);
   3981     cc.add_func(func_signature);
   3982 
   3983     FuncSignature invoke_signature;
   3984     invoke_signature.set_call_conv_id(CallConvId::kCDecl);
   3985     invoke_signature.set_ret(TypeId::kFloat64);
   3986 
   3987     cc.invoke(Out(invoke_node), imm((void*)called_fn), invoke_signature);
   3988     x86::Vec ret = cc.new_xmm_sd("ret");
   3989     invoke_node->set_ret(0, ret);
   3990     cc.ret(ret);
   3991 
   3992     cc.end_func();
   3993   }
   3994 
   3995   bool run(void* _func, String& result, String& expect) override {
   3996     using Func = double (*)(void);
   3997     Func func = ptr_as_func<Func>(_func);
   3998 
   3999     double result_ret = func();
   4000     double expect_ret = 3.14;
   4001 
   4002     result.assign_format("ret=%g", result_ret);
   4003     expect.assign_format("ret=%g", expect_ret);
   4004 
   4005     return result == expect;
   4006   }
   4007 
   4008   static double called_fn() { return 3.14; }
   4009 };
   4010 
   4011 // x86::Compiler - X86Test_FuncCallMisc5
   4012 // =====================================
   4013 
   4014 // The register allocator should clobber the register used by the `call` itself.
   4015 class X86Test_FuncCallMisc5 : public X86TestCase {
   4016 public:
   4017   X86Test_FuncCallMisc5() : X86TestCase("FuncCallMisc5") {}
   4018 
   4019   static void add(TestApp& app) {
   4020     app.add(new X86Test_FuncCallMisc5());
   4021   }
   4022 
   4023   void compile(x86::Compiler& cc) override {
   4024     cc.add_func(FuncSignature::build<int>());
   4025 
   4026     x86::Gp p_fn = cc.new_gp_ptr("p_fn");
   4027     x86::Gp vars[16];
   4028 
   4029     uint32_t i, reg_count = cc.arch() == Arch::kX86 ? 8 : 16;
   4030     ASMJIT_ASSERT(reg_count <= ASMJIT_ARRAY_SIZE(vars));
   4031 
   4032     cc.mov(p_fn, imm((void*)called_fn));
   4033 
   4034     for (i = 0; i < reg_count; i++) {
   4035       if (i == x86::Gp::kIdBp || i == x86::Gp::kIdSp)
   4036         continue;
   4037 
   4038       vars[i] = cc.new_gp32("%%%u", unsigned(i));
   4039       cc.mov(vars[i], 1);
   4040     }
   4041 
   4042     InvokeNode* invoke_node;
   4043     cc.invoke(Out(invoke_node), p_fn, FuncSignature::build<void>());
   4044 
   4045     for (i = 1; i < reg_count; i++)
   4046       if (vars[i].is_valid())
   4047         cc.add(vars[0], vars[i]);
   4048     cc.ret(vars[0]);
   4049 
   4050     cc.end_func();
   4051   }
   4052 
   4053   bool run(void* _func, String& result, String& expect) override {
   4054     using Func = int (*)(void);
   4055     Func func = ptr_as_func<Func>(_func);
   4056 
   4057     int result_ret = func();
   4058     int expect_ret = sizeof(void*) == 4 ? 6 : 14;
   4059 
   4060     result.assign_format("ret=%d", result_ret);
   4061     expect.assign_format("ret=%d", expect_ret);
   4062 
   4063     return result == expect;
   4064   }
   4065 
   4066   static void called_fn() {}
   4067 };
   4068 
   4069 // x86::Compiler - X86Test_FuncCallMisc6
   4070 // =====================================
   4071 
   4072 class X86Test_FuncCallMisc6 : public X86TestCase {
   4073 public:
   4074   X86Test_FuncCallMisc6() : X86TestCase("FuncCallMisc6") {}
   4075 
   4076   static void add(TestApp& app) {
   4077     app.add(new X86Test_FuncCallMisc6());
   4078   }
   4079 
   4080   void compile(x86::Compiler& cc) override {
   4081     FuncNode* func_node = cc.add_func(FuncSignature::build<uint32_t, uint32_t>());
   4082 
   4083     constexpr uint32_t kCount = 16;
   4084 
   4085     x86::Gp v[kCount];
   4086     x86::Gp arg_val = cc.new_gp32("arg_val");
   4087     x86::Gp ret_val = cc.new_gp32("ret_val");
   4088 
   4089     func_node->set_arg(0, arg_val);
   4090     cc.add(arg_val, 1);
   4091 
   4092     for (uint32_t i = 0; i < kCount; i++) {
   4093       v[i] = cc.new_gp32("v%u", i);
   4094     }
   4095 
   4096     InvokeNode* invoke_node;
   4097     cc.invoke(Out(invoke_node), imm((void*)called_fn), FuncSignature::build<uint32_t, uint32_t>());
   4098     invoke_node->set_arg(0, arg_val);
   4099     invoke_node->set_ret(0, ret_val);
   4100 
   4101     for (uint32_t i = 0; i < kCount; i++) {
   4102       cc.mov(v[i], i + 1);
   4103     }
   4104 
   4105     for (uint32_t i = 0; i < kCount; i++) {
   4106       cc.add(arg_val, v[i]);
   4107     }
   4108 
   4109     cc.add(ret_val, arg_val);
   4110     cc.ret(ret_val);
   4111 
   4112     cc.end_func();
   4113   }
   4114 
   4115   bool run(void* _func, String& result, String& expect) override {
   4116     using Func = uint32_t (*)(uint32_t x);
   4117     Func func = ptr_as_func<Func>(_func);
   4118 
   4119     uint32_t result_ret = func(111);
   4120     uint32_t expect_ret = 111 + 112 + 2 + (1 + 16) * 8;
   4121 
   4122     result.assign_format("ret=%u", result_ret);
   4123     expect.assign_format("ret=%u", expect_ret);
   4124 
   4125     return result == expect;
   4126   }
   4127 
   4128   static uint32_t called_fn(uint32_t x) { return x + 1; }
   4129 };
   4130 
   4131 // x86::Compiler - X86Test_FuncCallAVXClobber
   4132 // ==========================================
   4133 
   4134 class X86Test_FuncCallAVXClobber : public X86TestCase {
   4135 public:
   4136   X86Test_FuncCallAVXClobber() : X86TestCase("FuncCallAVXClobber") {}
   4137 
   4138   static void add(TestApp& app) {
   4139     const CpuInfo& cpu_info = CpuInfo::host();
   4140 
   4141     if (cpu_info.features().x86().has_avx2() && sizeof(void*) == 8) {
   4142       app.add(new X86Test_FuncCallAVXClobber());
   4143     }
   4144   }
   4145 
   4146   void compile(x86::Compiler& cc) override {
   4147     FuncNode* main_func = cc.add_func(FuncSignature::build<void, void*, const void*, const void*>());
   4148     main_func->frame().set_avx_enabled();
   4149     main_func->frame().set_avx_cleanup();
   4150 
   4151     // We need a Windows calling convention to test this properly also on a non-Windows machine.
   4152     FuncNode* helper_func = cc.new_func(FuncSignature::build<void, void*, const void*>(CallConvId::kX64Windows));
   4153     helper_func->frame().set_avx_enabled();
   4154     helper_func->frame().set_avx_cleanup();
   4155 
   4156     {
   4157       size_t i;
   4158 
   4159       x86::Gp d_ptr = cc.new_gp_ptr("d_ptr");
   4160       x86::Gp a_ptr = cc.new_gp_ptr("a_ptr");
   4161       x86::Gp b_ptr = cc.new_gp_ptr("b_ptr");
   4162       x86::Gp t_ptr = cc.new_gp_ptr("t_ptr");
   4163       x86::Vec acc[8];
   4164       x86::Mem stack = cc.new_stack(32, 1, "stack");
   4165 
   4166       main_func->set_arg(0, d_ptr);
   4167       main_func->set_arg(1, a_ptr);
   4168       main_func->set_arg(2, b_ptr);
   4169 
   4170       cc.lea(t_ptr, stack);
   4171       for (i = 0; i < 8; i++) {
   4172         acc[i] = cc.new_ymm("acc%zu", i);
   4173         cc.vmovdqu(acc[i], x86::ptr(a_ptr));
   4174       }
   4175 
   4176       InvokeNode* invoke_node;
   4177       cc.invoke(Out(invoke_node),
   4178         helper_func->label(),
   4179         FuncSignature::build<void, void*, const void*>(CallConvId::kX64Windows));
   4180       invoke_node->set_arg(0, t_ptr);
   4181       invoke_node->set_arg(1, b_ptr);
   4182 
   4183       for (i = 1; i < 8; i++) {
   4184         cc.vpaddd(acc[0], acc[0], acc[i]);
   4185       }
   4186 
   4187       cc.vpaddd(acc[0], acc[0], x86::ptr(t_ptr));
   4188       cc.vmovdqu(x86::ptr(d_ptr), acc[0]);
   4189 
   4190       cc.end_func();
   4191     }
   4192 
   4193     {
   4194       cc.add_func(helper_func);
   4195 
   4196       x86::Gp d_ptr = cc.new_gp_ptr("d_ptr");
   4197       x86::Gp a_ptr = cc.new_gp_ptr("a_ptr");
   4198 
   4199       helper_func->set_arg(0, d_ptr);
   4200       helper_func->set_arg(1, a_ptr);
   4201 
   4202       x86::Gp tmp = cc.new_gp_ptr("tmp");
   4203       x86::Vec acc = cc.new_ymm("acc");
   4204 
   4205       cc.mov(tmp, 1);
   4206       cc.vmovd(acc.xmm(), tmp);
   4207       cc.vpbroadcastd(acc, acc.xmm());
   4208       cc.vpaddd(acc, acc, x86::ptr(a_ptr));
   4209       cc.vmovdqu(x86::ptr(d_ptr), acc);
   4210 
   4211       cc.end_func();
   4212     }
   4213   }
   4214 
   4215   bool run(void* _func, String& result, String& expect) override {
   4216     using Func = void (*)(void*, const void*, const void*);
   4217     Func func = ptr_as_func<Func>(_func);
   4218 
   4219     size_t i;
   4220 
   4221     static const uint32_t a_data[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
   4222     static const uint32_t b_data[8] = { 6, 3, 5, 9, 1, 8, 7, 2 };
   4223 
   4224     uint32_t result_data[8] {};
   4225     uint32_t expect_data[8] {};
   4226 
   4227     for (i = 0; i < 8; i++)
   4228       expect_data[i] = a_data[i] * 8 + b_data[i] + 1;
   4229 
   4230     func(result_data, a_data, b_data);
   4231 
   4232     result.assign("{");
   4233     expect.assign("{");
   4234 
   4235     for (i = 0; i < 8; i++) {
   4236       result.append_format("%u", result_data[i]);
   4237       expect.append_format("%u", expect_data[i]);
   4238 
   4239       if (i != 7) result.append(", ");
   4240       if (i != 7) expect.append(", ");
   4241     }
   4242 
   4243     result.append("}");
   4244     expect.append("}");
   4245 
   4246     return result == expect;
   4247   }
   4248 };
   4249 
   4250 // x86::Compiler - X86Test_VecToScalar
   4251 // ===================================
   4252 
   4253 class X86Test_VecToScalar : public X86TestCase {
   4254 public:
   4255   static inline constexpr uint32_t kVecCount = 64;
   4256 
   4257   X86Test_VecToScalar() : X86TestCase("VecToScalar") {}
   4258 
   4259   static void add(TestApp& app) {
   4260     app.add(new X86Test_VecToScalar());
   4261   }
   4262 
   4263   void compile(x86::Compiler& cc) override {
   4264     FuncNode* func = cc.add_func(FuncSignature::build<uint32_t, uint32_t>());
   4265 
   4266     x86::Gp x = cc.new_gp32("x");
   4267     x86::Gp t = cc.new_gp32("t");
   4268     x86::Vec v[kVecCount];
   4269 
   4270     func->set_arg(0, x);
   4271 
   4272     for (size_t i = 0; i < kVecCount; i++) {
   4273       v[i] = cc.new_xmm("v%d", i);
   4274       if (i != 0)
   4275         cc.add(x, 1);
   4276       cc.movd(v[i], x);
   4277     }
   4278 
   4279     cc.xor_(x, x);
   4280 
   4281     for (size_t i = 0; i < kVecCount; i++) {
   4282       cc.movd(t, v[i]);
   4283       cc.add(x, t);
   4284     }
   4285 
   4286     cc.ret(x);
   4287     cc.end_func();
   4288   }
   4289 
   4290   bool run(void* _func, String& result, String& expect) override {
   4291     using Func = uint32_t (*)(uint32_t);
   4292     Func func = ptr_as_func<Func>(_func);
   4293 
   4294     uint32_t result_ret = func(1);
   4295     uint32_t expect_ret = 2080; // 1 + 2 + 3 + ... + 64
   4296 
   4297     result.assign_format("ret=%d", result_ret);
   4298     expect.assign_format("ret=%d", expect_ret);
   4299 
   4300     return result == expect;
   4301   }
   4302 };
   4303 
   4304 // x86::Compiler - X86Test_MiscLocalConstPool
   4305 // ==========================================
   4306 
   4307 class X86Test_MiscLocalConstPool : public X86TestCase {
   4308 public:
   4309   X86Test_MiscLocalConstPool() : X86TestCase("MiscLocalConstPool") {}
   4310 
   4311   static void add(TestApp& app) {
   4312     app.add(new X86Test_MiscLocalConstPool());
   4313   }
   4314 
   4315   void compile(x86::Compiler& cc) override {
   4316     cc.add_func(FuncSignature::build<int>());
   4317 
   4318     x86::Gp v0 = cc.new_gp32("v0");
   4319     x86::Gp v1 = cc.new_gp32("v1");
   4320 
   4321     x86::Mem c0 = cc.new_int32_const(ConstPoolScope::kLocal, 200);
   4322     x86::Mem c1 = cc.new_int32_const(ConstPoolScope::kLocal, 33);
   4323 
   4324     cc.mov(v0, c0);
   4325     cc.mov(v1, c1);
   4326     cc.add(v0, v1);
   4327 
   4328     cc.ret(v0);
   4329     cc.end_func();
   4330   }
   4331 
   4332   bool run(void* _func, String& result, String& expect) override {
   4333     using Func = int (*)(void);
   4334     Func func = ptr_as_func<Func>(_func);
   4335 
   4336     int result_ret = func();
   4337     int expect_ret = 233;
   4338 
   4339     result.assign_format("ret=%d", result_ret);
   4340     expect.assign_format("ret=%d", expect_ret);
   4341 
   4342     return result == expect;
   4343   }
   4344 };
   4345 
   4346 // x86::Compiler - X86Test_MiscGlobalConstPool
   4347 // ===========================================
   4348 
   4349 class X86Test_MiscGlobalConstPool : public X86TestCase {
   4350 public:
   4351   X86Test_MiscGlobalConstPool() : X86TestCase("MiscGlobalConstPool") {}
   4352 
   4353   static void add(TestApp& app) {
   4354     app.add(new X86Test_MiscGlobalConstPool());
   4355   }
   4356 
   4357   void compile(x86::Compiler& cc) override {
   4358     cc.add_func(FuncSignature::build<int>());
   4359 
   4360     x86::Gp v0 = cc.new_gp32("v0");
   4361     x86::Gp v1 = cc.new_gp32("v1");
   4362 
   4363     x86::Mem c0 = cc.new_int32_const(ConstPoolScope::kGlobal, 200);
   4364     x86::Mem c1 = cc.new_int32_const(ConstPoolScope::kGlobal, 33);
   4365 
   4366     cc.mov(v0, c0);
   4367     cc.mov(v1, c1);
   4368     cc.add(v0, v1);
   4369 
   4370     cc.ret(v0);
   4371     cc.end_func();
   4372   }
   4373 
   4374   bool run(void* _func, String& result, String& expect) override {
   4375     using Func = int (*)(void);
   4376     Func func = ptr_as_func<Func>(_func);
   4377 
   4378     int result_ret = func();
   4379     int expect_ret = 233;
   4380 
   4381     result.assign_format("ret=%d", result_ret);
   4382     expect.assign_format("ret=%d", expect_ret);
   4383 
   4384     return result == expect;
   4385   }
   4386 };
   4387 
   4388 // x86::Compiler - X86Test_MiscMultiRet
   4389 // ====================================
   4390 
   4391 struct X86Test_MiscMultiRet : public X86TestCase {
   4392   X86Test_MiscMultiRet() : X86TestCase("MiscMultiRet") {}
   4393 
   4394   static void add(TestApp& app) {
   4395     app.add(new X86Test_MiscMultiRet());
   4396   }
   4397 
   4398   void compile(x86::Compiler& cc) override {
   4399     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, int, int>());
   4400 
   4401     x86::Gp op = cc.new_gp32("op");
   4402     x86::Gp a = cc.new_gp32("a");
   4403     x86::Gp b = cc.new_gp32("b");
   4404 
   4405     Label L_Zero = cc.new_label();
   4406     Label L_Add = cc.new_label();
   4407     Label L_Sub = cc.new_label();
   4408     Label L_Mul = cc.new_label();
   4409     Label L_Div = cc.new_label();
   4410 
   4411     func_node->set_arg(0, op);
   4412     func_node->set_arg(1, a);
   4413     func_node->set_arg(2, b);
   4414 
   4415     cc.cmp(op, 0);
   4416     cc.jz(L_Add);
   4417 
   4418     cc.cmp(op, 1);
   4419     cc.jz(L_Sub);
   4420 
   4421     cc.cmp(op, 2);
   4422     cc.jz(L_Mul);
   4423 
   4424     cc.cmp(op, 3);
   4425     cc.jz(L_Div);
   4426 
   4427     cc.bind(L_Zero);
   4428     cc.xor_(a, a);
   4429     cc.ret(a);
   4430 
   4431     cc.bind(L_Add);
   4432     cc.add(a, b);
   4433     cc.ret(a);
   4434 
   4435     cc.bind(L_Sub);
   4436     cc.sub(a, b);
   4437     cc.ret(a);
   4438 
   4439     cc.bind(L_Mul);
   4440     cc.imul(a, b);
   4441     cc.ret(a);
   4442 
   4443     cc.bind(L_Div);
   4444     cc.cmp(b, 0);
   4445     cc.jz(L_Zero);
   4446 
   4447     x86::Gp zero = cc.new_gp32("zero");
   4448     cc.xor_(zero, zero);
   4449     cc.idiv(zero, a, b);
   4450     cc.ret(a);
   4451 
   4452     cc.end_func();
   4453   }
   4454 
   4455   bool run(void* _func, String& result, String& expect) override {
   4456     using Func = int (*)(int, int, int);
   4457 
   4458     Func func = ptr_as_func<Func>(_func);
   4459 
   4460     int a = 44;
   4461     int b = 3;
   4462 
   4463     int r0 = func(0, a, b);
   4464     int r1 = func(1, a, b);
   4465     int r2 = func(2, a, b);
   4466     int r3 = func(3, a, b);
   4467     int e0 = a + b;
   4468     int e1 = a - b;
   4469     int e2 = a * b;
   4470     int e3 = a / b;
   4471 
   4472     result.assign_format("ret={%d %d %d %d}", r0, r1, r2, r3);
   4473     expect.assign_format("ret={%d %d %d %d}", e0, e1, e2, e3);
   4474 
   4475     return result == expect;
   4476   }
   4477 };
   4478 
   4479 // x86::Compiler - X86Test_MiscMultiFunc
   4480 // =====================================
   4481 
   4482 class X86Test_MiscMultiFunc : public X86TestCase {
   4483 public:
   4484   X86Test_MiscMultiFunc() : X86TestCase("MiscMultiFunc") {}
   4485 
   4486   static void add(TestApp& app) {
   4487     app.add(new X86Test_MiscMultiFunc());
   4488   }
   4489 
   4490   void compile(x86::Compiler& cc) override {
   4491     FuncNode* f1_node = cc.new_func(FuncSignature::build<int, int, int>());
   4492     FuncNode* f2_node = cc.new_func(FuncSignature::build<int, int, int>());
   4493 
   4494     {
   4495       x86::Gp a = cc.new_gp32("a");
   4496       x86::Gp b = cc.new_gp32("b");
   4497 
   4498       cc.add_func(f1_node);
   4499       f1_node->set_arg(0, a);
   4500       f1_node->set_arg(1, b);
   4501 
   4502       InvokeNode* invoke_node;
   4503       cc.invoke(Out(invoke_node), f2_node->label(), FuncSignature::build<int, int, int>());
   4504       invoke_node->set_arg(0, a);
   4505       invoke_node->set_arg(1, b);
   4506       invoke_node->set_ret(0, a);
   4507 
   4508       cc.ret(a);
   4509       cc.end_func();
   4510     }
   4511 
   4512     {
   4513       x86::Gp a = cc.new_gp32("a");
   4514       x86::Gp b = cc.new_gp32("b");
   4515 
   4516       cc.add_func(f2_node);
   4517       f2_node->set_arg(0, a);
   4518       f2_node->set_arg(1, b);
   4519 
   4520       cc.add(a, b);
   4521       cc.ret(a);
   4522       cc.end_func();
   4523     }
   4524   }
   4525 
   4526   bool run(void* _func, String& result, String& expect) override {
   4527     using Func = int (*)(int, int);
   4528 
   4529     Func func = ptr_as_func<Func>(_func);
   4530 
   4531     int result_ret = func(56, 22);
   4532     int expect_ret = 56 + 22;
   4533 
   4534     result.assign_format("ret=%d", result_ret);
   4535     expect.assign_format("ret=%d", expect_ret);
   4536 
   4537     return result == expect;
   4538   }
   4539 };
   4540 
   4541 // x86::Compiler - X86Test_MiscUnfollow
   4542 // ====================================
   4543 
   4544 // Global (I didn't find a better way to test this).
   4545 static jmp_buf global_jmp_buf;
   4546 
   4547 class X86Test_MiscUnfollow : public X86TestCase {
   4548 public:
   4549   X86Test_MiscUnfollow() : X86TestCase("MiscUnfollow") {}
   4550 
   4551   static void add(TestApp& app) {
   4552     app.add(new X86Test_MiscUnfollow());
   4553   }
   4554 
   4555   void compile(x86::Compiler& cc) override {
   4556     // NOTE: Fastcall calling convention is the most appropriate here as all arguments are passed via registers and
   4557     // there won't be any stack misalignment in the `handler()`. This was failing on MacOS when targeting 32-bit mode.
   4558     x86::Gp a = cc.new_gp32("a");
   4559     x86::Gp b = cc.new_gp_ptr("b");
   4560     Label tramp = cc.new_label();
   4561 
   4562     FuncNode* func_node = cc.add_func(FuncSignature::build<int, int, void*>(CallConvId::kFastCall));
   4563     func_node->set_arg(0, a);
   4564     func_node->set_arg(1, b);
   4565 
   4566     cc.cmp(a, 0);
   4567     cc.jz(tramp);
   4568     cc.ret(a);
   4569     cc.bind(tramp);
   4570     cc.unfollow().jmp(b);
   4571     cc.end_func();
   4572   }
   4573 
   4574   bool run(void* _func, String& result, String& expect) override {
   4575     using Func = int (ASMJIT_FASTCALL*)(int, void*);
   4576     Func func = ptr_as_func<Func>(_func);
   4577 
   4578     int result_ret = 0;
   4579     int expect_ret = 1;
   4580 
   4581     if (!setjmp(global_jmp_buf))
   4582       result_ret = func(0, (void*)handler);
   4583     else
   4584       result_ret = 1;
   4585 
   4586     result.assign_format("ret={%d}", result_ret);
   4587     expect.assign_format("ret={%d}", expect_ret);
   4588 
   4589     return result == expect;
   4590   }
   4591 
   4592   static void ASMJIT_FASTCALL handler() { longjmp(global_jmp_buf, 1); }
   4593 };
   4594 
   4595 // x86::Compiler - Tests
   4596 // =====================
   4597 
   4598 void compiler_add_x86_tests(TestApp& app) {
   4599   // Base tests.
   4600   app.add_t<X86Test_NoCode>();
   4601   app.add_t<X86Test_NoAlign>();
   4602   app.add_t<X86Test_IndirectBranchProtection>();
   4603   app.add_t<X86Test_AlignBase>();
   4604 
   4605   // Jump tests.
   4606   app.add_t<X86Test_JumpMerge>();
   4607   app.add_t<X86Test_JumpCross>();
   4608   app.add_t<X86Test_JumpMany>();
   4609   app.add_t<X86Test_JumpUnreachable1>();
   4610   app.add_t<X86Test_JumpUnreachable2>();
   4611   app.add_t<X86Test_JumpTable1>();
   4612   app.add_t<X86Test_JumpTable2>();
   4613   app.add_t<X86Test_JumpTable3>();
   4614   app.add_t<X86Test_JumpTable4>();
   4615 
   4616   // Alloc and instruction tests.
   4617   app.add_t<X86Test_AllocBase>();
   4618   app.add_t<X86Test_AllocMany1>();
   4619   app.add_t<X86Test_AllocMany2>();
   4620   app.add_t<X86Test_AllocInt8>();
   4621   app.add_t<X86Test_AllocUnhandledArg>();
   4622   app.add_t<X86Test_AllocArgsIntPtr>();
   4623   app.add_t<X86Test_AllocArgsFloat>();
   4624   app.add_t<X86Test_AllocArgsDouble>();
   4625 #if ASMJIT_ARCH_X86
   4626   app.add_t<X86Test_AllocArgsVec>();
   4627 #endif
   4628   app.add_t<X86Test_AllocRetFloat1>();
   4629   app.add_t<X86Test_AllocRetFloat2>();
   4630   app.add_t<X86Test_AllocRetDouble1>();
   4631   app.add_t<X86Test_AllocRetDouble2>();
   4632   app.add_t<X86Test_AllocStack>();
   4633   app.add_t<X86Test_Imul1>();
   4634   app.add_t<X86Test_Imul2>();
   4635   app.add_t<X86Test_Idiv1>();
   4636   app.add_t<X86Test_Setz>();
   4637   app.add_t<X86Test_ShlRor>();
   4638   app.add_t<X86Test_GpbLo1>();
   4639   app.add_t<X86Test_GpbLo2>();
   4640   app.add_t<X86Test_RepMovsb>();
   4641   app.add_t<X86Test_IfElse1>();
   4642   app.add_t<X86Test_IfElse2>();
   4643   app.add_t<X86Test_IfElse3>();
   4644   app.add_t<X86Test_IfElse4>();
   4645   app.add_t<X86Test_Memcpy>();
   4646   app.add_t<X86Test_ExtraBlock>();
   4647   app.add_t<X86Test_AlphaBlend>();
   4648   app.add_t<X86Test_AVX512_KK>();
   4649   app.add_t<X86Test_AVX512_TernLog>();
   4650 
   4651   // Function arguments handling tests.
   4652   app.add_t<X86Test_FuncArgInt8>();
   4653 
   4654   // Function call tests.
   4655   app.add_t<X86Test_FuncCallBase1>();
   4656   app.add_t<X86Test_FuncCallBase2>();
   4657   app.add_t<X86Test_FuncCallStd>();
   4658   app.add_t<X86Test_FuncCallFast>();
   4659 #if ASMJIT_ARCH_X86
   4660   app.add_t<X86Test_FuncCallSIMD>();
   4661 #endif
   4662   app.add_t<X86Test_FuncCallLight>();
   4663   app.add_t<X86Test_FuncCallManyArgs>();
   4664   app.add_t<X86Test_FuncCallDuplicateArgs>();
   4665   app.add_t<X86Test_FuncCallImmArgs>();
   4666   app.add_t<X86Test_FuncCallPtrArgs>();
   4667   app.add_t<X86Test_FuncCallRefArgs>();
   4668   app.add_t<X86Test_FuncCallFloatAsXmmRet>();
   4669   app.add_t<X86Test_FuncCallDoubleAsXmmRet>();
   4670   app.add_t<X86Test_FuncCallConditional>();
   4671   app.add_t<X86Test_FuncCallMultiple>();
   4672   app.add_t<X86Test_FuncCallRecursive>();
   4673   app.add_t<X86Test_FuncCallVarArg1>();
   4674   app.add_t<X86Test_FuncCallVarArg2>();
   4675   app.add_t<X86Test_FuncCallInt64Arg>();
   4676   app.add_t<X86Test_FuncCallMisc1>();
   4677   app.add_t<X86Test_FuncCallMisc2>();
   4678   app.add_t<X86Test_FuncCallMisc3>();
   4679   app.add_t<X86Test_FuncCallMisc4>();
   4680   app.add_t<X86Test_FuncCallMisc5>();
   4681   app.add_t<X86Test_FuncCallMisc6>();
   4682   app.add_t<X86Test_FuncCallAVXClobber>();
   4683 
   4684   // Miscellaneous tests.
   4685   app.add_t<X86Test_VecToScalar>();
   4686   app.add_t<X86Test_MiscLocalConstPool>();
   4687   app.add_t<X86Test_MiscGlobalConstPool>();
   4688   app.add_t<X86Test_MiscMultiRet>();
   4689   app.add_t<X86Test_MiscMultiFunc>();
   4690   app.add_t<X86Test_MiscUnfollow>();
   4691 }
   4692 
   4693 #endif // !ASMJIT_NO_X86 && !ASMJIT_NO_COMPILER