Home | History | Annotate | Download | only in AssemblerX8664
      1 //===- subzero/unittest/AssemblerX8664/GPRArith.cpp -----------------------===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include "AssemblerX8664/TestUtil.h"
     10 
     11 namespace Ice {
     12 namespace X8664 {
     13 namespace Test {
     14 namespace {
     15 
     16 TEST_F(AssemblerX8664Test, PopAddr) {
     17   const uint32_t T0 = allocateQword();
     18   constexpr uint64_t V0 = 0x3AABBEFABBBAA3ull;
     19 
     20   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xC0FFEE));
     21   __ pushl(GPRRegister::Encoded_Reg_eax);
     22   __ popl(dwordAddress(T0));
     23 
     24   AssembledTest test = assemble();
     25   test.setQwordTo(T0, V0);
     26 
     27   test.run();
     28 
     29   ASSERT_EQ(0xC0FFEEul, test.contentsOfQword(T0));
     30 }
     31 
     32 TEST_F(AssemblerX8664Test, SetCC) {
     33 #define TestSetCC(C, Dest, IsTrue, Src0, Value0, Src1, Value1)                 \
     34   do {                                                                         \
     35     static constexpr char TestString[] =                                       \
     36         "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1      \
     37         ", " #Value1 ")";                                                      \
     38     const uint32_t T0 = allocateDword();                                       \
     39     constexpr uint32_t V0 = 0xF00F00;                                          \
     40     __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0));              \
     41     __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1));              \
     42     __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1());           \
     43     __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0));                   \
     44     __ setcc(Cond::Br_##C, Encoded_Bytereg_##Dest());                          \
     45     __ setcc(Cond::Br_##C, dwordAddress(T0));                                  \
     46                                                                                \
     47     AssembledTest test = assemble();                                           \
     48     test.setDwordTo(T0, V0);                                                   \
     49                                                                                \
     50     test.run();                                                                \
     51                                                                                \
     52     ASSERT_EQ(IsTrue, test.Dest()) << TestString;                              \
     53     ASSERT_EQ((0xF00F00 | IsTrue), test.contentsOfDword(T0)) << TestString;    \
     54     reset();                                                                   \
     55   } while (0)
     56 
     57 #define TestImpl(Dest, Src0, Src1)                                             \
     58   do {                                                                         \
     59     TestSetCC(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \
     60     TestSetCC(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u);                     \
     61     TestSetCC(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u);                    \
     62     TestSetCC(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \
     63     TestSetCC(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u);                      \
     64     TestSetCC(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                     \
     65     TestSetCC(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \
     66     TestSetCC(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \
     67     TestSetCC(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u);                            \
     68     TestSetCC(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u);                        \
     69     TestSetCC(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \
     70     TestSetCC(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u);                           \
     71     TestSetCC(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \
     72     TestSetCC(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \
     73     TestSetCC(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \
     74     TestSetCC(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \
     75     TestSetCC(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                     \
     76     TestSetCC(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                     \
     77     TestSetCC(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \
     78     TestSetCC(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \
     79     TestSetCC(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \
     80     TestSetCC(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \
     81     TestSetCC(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \
     82     TestSetCC(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \
     83     TestSetCC(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \
     84     TestSetCC(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \
     85     TestSetCC(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \
     86     TestSetCC(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \
     87     TestSetCC(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \
     88     TestSetCC(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \
     89   } while (0)
     90 
     91   TestImpl(r1, r2, r3);
     92   TestImpl(r2, r3, r4);
     93   TestImpl(r3, r4, r5);
     94   TestImpl(r4, r5, r6);
     95   TestImpl(r4, r6, r7);
     96   TestImpl(r5, r6, r7);
     97   TestImpl(r6, r7, r8);
     98   TestImpl(r7, r8, r10);
     99   TestImpl(r8, r10, r11);
    100   TestImpl(r10, r11, r12);
    101   TestImpl(r11, r12, r13);
    102   TestImpl(r12, r13, r14);
    103   TestImpl(r13, r14, r15);
    104   TestImpl(r14, r15, r1);
    105   TestImpl(r15, r1, r2);
    106 
    107 #undef TestImpl
    108 #undef TestSetCC
    109 }
    110 
    111 TEST_F(AssemblerX8664Test, Lea) {
    112 #define TestLeaBaseDisp(Base, BaseValue, Disp, Dst)                            \
    113   do {                                                                         \
    114     static constexpr char TestString[] =                                       \
    115         "(" #Base ", " #BaseValue ", " #Dst ")";                               \
    116     if (Encoded_GPR_##Base() != Encoded_GPR_esp() &&                           \
    117         Encoded_GPR_##Base() != Encoded_GPR_r9()) {                            \
    118       __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue));         \
    119     }                                                                          \
    120     __ lea(IceType_i32, Encoded_GPR_##Dst(),                                   \
    121            Address(Encoded_GPR_##Base(), Disp, AssemblerFixup::NoFixup));      \
    122     AssembledTest test = assemble();                                           \
    123     test.run();                                                                \
    124     ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d())                          \
    125         << TestString << " with Disp " << Disp;                                \
    126     reset();                                                                   \
    127   } while (0)
    128 
    129 #define TestLeaIndex32bitDisp(Index, IndexValue, Disp, Dst0, Dst1, Dst2, Dst3) \
    130   do {                                                                         \
    131     static constexpr char TestString[] =                                       \
    132         "(" #Index ", " #IndexValue ", " #Dst0 ", " #Dst1 ", " #Dst2           \
    133         ", " #Dst3 ")";                                                        \
    134     if (Encoded_GPR_##Index() != Encoded_GPR_r9()) {                           \
    135       __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue));       \
    136     }                                                                          \
    137     __ lea(IceType_i32, Encoded_GPR_##Dst0(),                                  \
    138            Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp,               \
    139                    AssemblerFixup::NoFixup));                                  \
    140     __ lea(IceType_i32, Encoded_GPR_##Dst1(),                                  \
    141            Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp,               \
    142                    AssemblerFixup::NoFixup));                                  \
    143     __ lea(IceType_i32, Encoded_GPR_##Dst2(),                                  \
    144            Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp,               \
    145                    AssemblerFixup::NoFixup));                                  \
    146     __ lea(IceType_i32, Encoded_GPR_##Dst3(),                                  \
    147            Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp,               \
    148                    AssemblerFixup::NoFixup));                                  \
    149     AssembledTest test = assemble();                                           \
    150     test.run();                                                                \
    151     ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d())   \
    152         << TestString << " " << Disp;                                          \
    153     ASSERT_EQ((test.Index##d() << Traits::TIMES_2) + (Disp), test.Dst1##d())   \
    154         << TestString << " " << Disp;                                          \
    155     ASSERT_EQ((test.Index##d() << Traits::TIMES_4) + (Disp), test.Dst2##d())   \
    156         << TestString << " " << Disp;                                          \
    157     ASSERT_EQ((test.Index##d() << Traits::TIMES_8) + (Disp), test.Dst3##d())   \
    158         << TestString << " " << Disp;                                          \
    159     reset();                                                                   \
    160   } while (0)
    161 
    162 #define TestLeaBaseIndexDisp(Base, BaseValue, Index, IndexValue, Disp, Dst0,   \
    163                              Dst1, Dst2, Dst3)                                 \
    164   do {                                                                         \
    165     static constexpr char TestString[] =                                       \
    166         "(" #Base ", " #BaseValue ", " #Index ", " #IndexValue ", " #Dst0      \
    167         ", " #Dst1 ", " #Dst2 ", " #Dst3 ")";                                  \
    168     if (Encoded_GPR_##Base() != Encoded_GPR_esp() &&                           \
    169         Encoded_GPR_##Base() != Encoded_GPR_r9()) {                            \
    170       __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue));         \
    171     }                                                                          \
    172                                                                                \
    173     if (Encoded_GPR_##Index() != Encoded_GPR_r9()) {                           \
    174       __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue));       \
    175     }                                                                          \
    176                                                                                \
    177     __ lea(IceType_i32, Encoded_GPR_##Dst0(),                                  \
    178            Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(),                \
    179                    Traits::TIMES_1, Disp, AssemblerFixup::NoFixup));           \
    180     __ lea(IceType_i32, Encoded_GPR_##Dst1(),                                  \
    181            Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(),                \
    182                    Traits::TIMES_2, Disp, AssemblerFixup::NoFixup));           \
    183     __ lea(IceType_i32, Encoded_GPR_##Dst2(),                                  \
    184            Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(),                \
    185                    Traits::TIMES_4, Disp, AssemblerFixup::NoFixup));           \
    186     __ lea(IceType_i32, Encoded_GPR_##Dst3(),                                  \
    187            Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(),                \
    188                    Traits::TIMES_8, Disp, AssemblerFixup::NoFixup));           \
    189     AssembledTest test = assemble();                                           \
    190     test.run();                                                                \
    191     uint32_t ExpectedIndexValue = test.Index();                                \
    192     if (Encoded_GPR_##Index() == Encoded_GPR_esp()) {                          \
    193       ExpectedIndexValue = 0;                                                  \
    194     }                                                                          \
    195     ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_1) +       \
    196                   (Disp),                                                      \
    197               test.Dst0##d())                                                  \
    198         << TestString << " " << Disp;                                          \
    199     ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_2) +       \
    200                   (Disp),                                                      \
    201               test.Dst1##d())                                                  \
    202         << TestString << " " << Disp;                                          \
    203     ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_4) +       \
    204                   (Disp),                                                      \
    205               test.Dst2##d())                                                  \
    206         << TestString << " " << Disp;                                          \
    207     ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_8) +       \
    208                   (Disp),                                                      \
    209               test.Dst3##d())                                                  \
    210         << TestString << " " << Disp;                                          \
    211     reset();                                                                   \
    212   } while (0)
    213 
    214   for (const int32_t Disp :
    215        {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
    216     TestLeaBaseDisp(r0, 0x22080Fu, Disp, r1);
    217     TestLeaBaseDisp(r1, 0x10000Fu, Disp, r2);
    218     TestLeaBaseDisp(r2, 0x20000Fu, Disp, r3);
    219     TestLeaBaseDisp(r3, 0x30000Fu, Disp, r4);
    220     TestLeaBaseDisp(r4, 0x40000Fu, Disp, r5);
    221     TestLeaBaseDisp(r5, 0x50000Fu, Disp, r6);
    222     TestLeaBaseDisp(r6, 0x60000Fu, Disp, r7);
    223     TestLeaBaseDisp(r7, 0x11000Fu, Disp, r8);
    224     TestLeaBaseDisp(r8, 0x11200Fu, Disp, r10);
    225     TestLeaBaseDisp(r9, 0x220400u, Disp, r10);
    226     TestLeaBaseDisp(r10, 0x22000Fu, Disp, r11);
    227     TestLeaBaseDisp(r11, 0x22030Fu, Disp, r12);
    228     TestLeaBaseDisp(r12, 0x22040Fu, Disp, r13);
    229     TestLeaBaseDisp(r13, 0x22050Fu, Disp, r14);
    230     TestLeaBaseDisp(r14, 0x22060Fu, Disp, r15);
    231     TestLeaBaseDisp(r15, 0x22070Fu, Disp, r1);
    232   }
    233 
    234   // esp is not a valid index register.
    235   // ebp is not valid in this addressing mode (rm = 0).
    236   for (const int32_t Disp :
    237        {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
    238     TestLeaIndex32bitDisp(r1, 0x2000u, Disp, r2, r3, r4, r6);
    239     TestLeaIndex32bitDisp(r2, 0x4010u, Disp, r3, r4, r6, r7);
    240     TestLeaIndex32bitDisp(r3, 0x6020u, Disp, r4, r6, r7, r5);
    241     TestLeaIndex32bitDisp(r4, 0x8030u, Disp, r6, r7, r5, r10);
    242     TestLeaIndex32bitDisp(r6, 0xA040u, Disp, r7, r5, r10, r1);
    243     TestLeaIndex32bitDisp(r7, 0xC050u, Disp, r5, r10, r1, r11);
    244     TestLeaIndex32bitDisp(r8, 0xC060u, Disp, r10, r1, r11, r12);
    245     TestLeaIndex32bitDisp(r9, 0xC100u, Disp, r1, r11, r12, r13);
    246     TestLeaIndex32bitDisp(r10, 0xC008u, Disp, r11, r12, r13, r14);
    247     TestLeaIndex32bitDisp(r11, 0xC009u, Disp, r12, r13, r14, r15);
    248     TestLeaIndex32bitDisp(r12, 0xC00Au, Disp, r13, r14, r15, r1);
    249     TestLeaIndex32bitDisp(r13, 0xC00Bu, Disp, r14, r15, r1, r2);
    250     TestLeaIndex32bitDisp(r14, 0xC00Cu, Disp, r15, r1, r2, r3);
    251     TestLeaIndex32bitDisp(r15, 0xC00Du, Disp, r1, r2, r3, r4);
    252   }
    253 
    254   for (const int32_t Disp :
    255        {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
    256     TestLeaBaseIndexDisp(r1, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
    257     TestLeaBaseIndexDisp(r2, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
    258     TestLeaBaseIndexDisp(r3, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r5);
    259     TestLeaBaseIndexDisp(r4, 0x400000u, r6, 0x300u, Disp, r7, r8, r5, r10);
    260     TestLeaBaseIndexDisp(r6, 0x500000u, r7, 0x200u, Disp, r8, r5, r10, r11);
    261     TestLeaBaseIndexDisp(r7, 0x600000u, r8, 0x100u, Disp, r5, r10, r11, r12);
    262     TestLeaBaseIndexDisp(r8, 0x600000u, r9, 0x1A0u, Disp, r10, r11, r12, r13);
    263     TestLeaBaseIndexDisp(r9, 0x600050u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
    264     TestLeaBaseIndexDisp(r10, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
    265     TestLeaBaseIndexDisp(r11, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
    266     TestLeaBaseIndexDisp(r12, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
    267     TestLeaBaseIndexDisp(r13, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
    268     TestLeaBaseIndexDisp(r14, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
    269     TestLeaBaseIndexDisp(r15, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
    270 
    271     TestLeaBaseIndexDisp(r0, 0, r2, 0x600u, Disp, r3, r4, r6, r7);
    272     TestLeaBaseIndexDisp(r0, 0, r3, 0x500u, Disp, r4, r6, r7, r8);
    273     TestLeaBaseIndexDisp(r0, 0, r4, 0x400u, Disp, r6, r7, r8, r5);
    274     TestLeaBaseIndexDisp(r0, 0, r6, 0x300u, Disp, r7, r8, r5, r10);
    275     TestLeaBaseIndexDisp(r0, 0, r7, 0x200u, Disp, r8, r5, r10, r11);
    276     TestLeaBaseIndexDisp(r0, 0, r8, 0x100u, Disp, r5, r10, r11, r12);
    277     TestLeaBaseIndexDisp(r0, 0, r9, 0x1000u, Disp, r10, r11, r12, r13);
    278     TestLeaBaseIndexDisp(r0, 0, r10, 0x1B0u, Disp, r11, r12, r13, r14);
    279     TestLeaBaseIndexDisp(r0, 0, r11, 0x1C0u, Disp, r12, r13, r14, r15);
    280     TestLeaBaseIndexDisp(r0, 0, r12, 0x1D0u, Disp, r13, r14, r15, r1);
    281     TestLeaBaseIndexDisp(r0, 0, r13, 0x1E0u, Disp, r14, r15, r1, r2);
    282     TestLeaBaseIndexDisp(r0, 0, r14, 0x1F0u, Disp, r15, r1, r2, r3);
    283     TestLeaBaseIndexDisp(r0, 0, r15, 0x10Au, Disp, r1, r2, r3, r4);
    284     TestLeaBaseIndexDisp(r0, 0, r1, 0x10Bu, Disp, r2, r3, r4, r6);
    285 
    286     TestLeaBaseIndexDisp(r5, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
    287     TestLeaBaseIndexDisp(r5, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
    288     TestLeaBaseIndexDisp(r5, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r1);
    289     TestLeaBaseIndexDisp(r5, 0x400000u, r6, 0x300u, Disp, r7, r8, r1, r10);
    290     TestLeaBaseIndexDisp(r5, 0x500000u, r7, 0x200u, Disp, r8, r1, r10, r11);
    291     TestLeaBaseIndexDisp(r5, 0x600000u, r8, 0x100u, Disp, r1, r10, r11, r12);
    292     TestLeaBaseIndexDisp(r5, 0x600000u, r9, 0x1A00u, Disp, r10, r11, r12, r13);
    293     TestLeaBaseIndexDisp(r5, 0x601000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
    294     TestLeaBaseIndexDisp(r5, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
    295     TestLeaBaseIndexDisp(r5, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
    296     TestLeaBaseIndexDisp(r5, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
    297     TestLeaBaseIndexDisp(r5, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
    298     TestLeaBaseIndexDisp(r5, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
    299     TestLeaBaseIndexDisp(r5, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
    300 
    301     TestLeaBaseIndexDisp(r2, 0x100000u, r5, 0x600u, Disp, r3, r4, r6, r7);
    302     TestLeaBaseIndexDisp(r3, 0x200000u, r5, 0x500u, Disp, r4, r6, r7, r8);
    303     TestLeaBaseIndexDisp(r4, 0x300000u, r5, 0x400u, Disp, r6, r7, r8, r1);
    304     TestLeaBaseIndexDisp(r6, 0x400000u, r5, 0x300u, Disp, r7, r8, r1, r10);
    305     TestLeaBaseIndexDisp(r7, 0x500000u, r5, 0x200u, Disp, r8, r1, r10, r11);
    306     TestLeaBaseIndexDisp(r8, 0x600000u, r5, 0x100u, Disp, r1, r10, r11, r12);
    307     TestLeaBaseIndexDisp(r9, 0x660000u, r5, 0x1A0u, Disp, r10, r11, r12, r13);
    308     TestLeaBaseIndexDisp(r10, 0x601000u, r5, 0x1B0u, Disp, r11, r12, r13, r14);
    309     TestLeaBaseIndexDisp(r11, 0x602000u, r5, 0x1C0u, Disp, r12, r13, r14, r15);
    310     TestLeaBaseIndexDisp(r12, 0x603000u, r5, 0x1D0u, Disp, r13, r14, r15, r1);
    311     TestLeaBaseIndexDisp(r13, 0x604000u, r5, 0x1E0u, Disp, r14, r15, r1, r2);
    312     TestLeaBaseIndexDisp(r14, 0x605000u, r5, 0x1F0u, Disp, r15, r1, r2, r3);
    313     TestLeaBaseIndexDisp(r15, 0x606000u, r5, 0x10Au, Disp, r1, r2, r3, r4);
    314     TestLeaBaseIndexDisp(r1, 0x607000u, r5, 0x10Bu, Disp, r2, r3, r4, r6);
    315 
    316     TestLeaBaseIndexDisp(r0, 0, r5, 0xC0BEBEEF, Disp, r2, r3, r4, r6);
    317   }
    318 
    319 // Absolute addressing mode is tested in the Low Level tests. The encoding used
    320 // by the assembler has different meanings in x86-32 and x86-64.
    321 #undef TestLeaBaseIndexDisp
    322 #undef TestLeaScaled32bitDisp
    323 #undef TestLeaBaseDisp
    324 }
    325 
    326 TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
    327 #define TestLeaAbsolute(Dst, Value)                                            \
    328   do {                                                                         \
    329     static constexpr char TestString[] = "(" #Dst ", " #Value ")";             \
    330     __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst,                        \
    331            Address::Absolute(Value));                                          \
    332     static constexpr uint32_t ByteCount = 8;                                   \
    333     ASSERT_EQ(ByteCount, codeBytesSize()) << TestString;                       \
    334     static constexpr uint8_t Opcode = 0x8D;                                    \
    335     static constexpr uint8_t ModRM =                                           \
    336         /*mod*/ 0x00 | /*reg*/ (GPRRegister::Encoded_Reg_##Dst << 3) |         \
    337         /*rm*/ GPRRegister::Encoded_Reg_esp;                                   \
    338     static constexpr uint8_t SIB =                                             \
    339         /*Scale*/ 0x00 | /*Index*/ (GPRRegister::Encoded_Reg_esp << 3) |       \
    340         /*base*/ GPRRegister::Encoded_Reg_ebp;                                 \
    341     ASSERT_TRUE(verifyBytes<ByteCount>(                                        \
    342         codeBytes(), 0x67, Opcode, ModRM, SIB, (Value)&0xFF,                   \
    343         (Value >> 8) & 0xFF, (Value >> 16) & 0xFF, (Value >> 24) & 0xFF));     \
    344     reset();                                                                   \
    345   } while (0)
    346 
    347   TestLeaAbsolute(eax, 0x11BEEF22);
    348   TestLeaAbsolute(ebx, 0x33BEEF44);
    349   TestLeaAbsolute(ecx, 0x55BEEF66);
    350   TestLeaAbsolute(edx, 0x77BEEF88);
    351   TestLeaAbsolute(esi, 0x99BEEFAA);
    352   TestLeaAbsolute(edi, 0xBBBEEFBB);
    353 
    354 #undef TesLeaAbsolute
    355 }
    356 
    357 TEST_F(AssemblerX8664Test, Test) {
    358   static constexpr uint32_t Mask8 = 0xFF;
    359   static constexpr uint32_t Mask16 = 0xFFFF;
    360   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
    361 
    362 #define TestImplRegReg(Dst, Value0, Src, Value1, Size)                         \
    363   do {                                                                         \
    364     static constexpr bool NearJump = true;                                     \
    365     static constexpr char TestString[] =                                       \
    366         "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")";           \
    367     static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB;                        \
    368     static constexpr uint32_t ValueIfFalse = 0x11111111;                       \
    369                                                                                \
    370     __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0));           \
    371     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1));           \
    372     __ test(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());        \
    373     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse));         \
    374     Label Done;                                                                \
    375     __ j(Cond::Br_e, &Done, NearJump);                                         \
    376     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue));          \
    377     __ bind(&Done);                                                            \
    378                                                                                \
    379     AssembledTest test = assemble();                                           \
    380     test.run();                                                                \
    381                                                                                \
    382     ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue      \
    383                                                             : ValueIfFalse,    \
    384               test.Dst())                                                      \
    385         << TestString;                                                         \
    386     reset();                                                                   \
    387   } while (0)
    388 
    389 #define TestImplRegImm(Dst, Value0, Imm, Size)                                 \
    390   do {                                                                         \
    391     static constexpr bool NearJump = true;                                     \
    392     static constexpr char TestString[] =                                       \
    393         "(" #Dst ", " #Value0 ", " #Imm ", " #Size ")";                        \
    394     static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB;                        \
    395     static constexpr uint32_t ValueIfFalse = 0x11111111;                       \
    396                                                                                \
    397     __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0));           \
    398     __ test(IceType_i##Size, Encoded_GPR_##Dst(),                              \
    399             Immediate((Imm)&Mask##Size));                                      \
    400     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse));         \
    401     Label Done;                                                                \
    402     __ j(Cond::Br_e, &Done, NearJump);                                         \
    403     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue));          \
    404     __ bind(&Done);                                                            \
    405                                                                                \
    406     AssembledTest test = assemble();                                           \
    407     test.run();                                                                \
    408                                                                                \
    409     ASSERT_EQ(((Value0)&Mask##Size) & ((Imm)&Mask##Size) ? ValueIfTrue         \
    410                                                          : ValueIfFalse,       \
    411               test.Dst())                                                      \
    412         << TestString;                                                         \
    413     reset();                                                                   \
    414   } while (0)
    415 
    416 #define TestImplAddrReg(Value0, Src, Value1, Size)                             \
    417   do {                                                                         \
    418     static constexpr bool NearJump = true;                                     \
    419     static constexpr char TestString[] =                                       \
    420         "(Addr, " #Value0 ", " #Src ", " #Value1 ", " #Size ")";               \
    421     static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB;                        \
    422     static constexpr uint32_t ValueIfFalse = 0x11111111;                       \
    423     const uint32_t T0 = allocateDword();                                       \
    424                                                                                \
    425     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1));           \
    426     __ test(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src());           \
    427     __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse));            \
    428     Label Done;                                                                \
    429     __ j(Cond::Br_e, &Done, NearJump);                                         \
    430     __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue));             \
    431     __ bind(&Done);                                                            \
    432                                                                                \
    433     AssembledTest test = assemble();                                           \
    434     test.setDwordTo(T0, uint32_t(Value0));                                     \
    435     test.run();                                                                \
    436                                                                                \
    437     ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue      \
    438                                                             : ValueIfFalse,    \
    439               test.contentsOfDword(T0))                                        \
    440         << TestString;                                                         \
    441     reset();                                                                   \
    442   } while (0)
    443 
    444 #define TestImplAddrImm(Value0, Value1, Size)                                  \
    445   do {                                                                         \
    446     static constexpr bool NearJump = true;                                     \
    447     static constexpr char TestString[] =                                       \
    448         "(Addr, " #Value0 ", " #Value1 ", " #Size ")";                         \
    449     static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB;                        \
    450     static constexpr uint32_t ValueIfFalse = 0x11111111;                       \
    451     const uint32_t T0 = allocateDword();                                       \
    452                                                                                \
    453     __ test(IceType_i##Size, dwordAddress(T0),                                 \
    454             Immediate((Value1)&Mask##Size));                                   \
    455     __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse));            \
    456     Label Done;                                                                \
    457     __ j(Cond::Br_e, &Done, NearJump);                                         \
    458     __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue));             \
    459     __ bind(&Done);                                                            \
    460                                                                                \
    461     AssembledTest test = assemble();                                           \
    462     test.setDwordTo(T0, uint32_t(Value0));                                     \
    463     test.run();                                                                \
    464                                                                                \
    465     ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue      \
    466                                                             : ValueIfFalse,    \
    467               test.contentsOfDword(T0))                                        \
    468         << TestString;                                                         \
    469     reset();                                                                   \
    470   } while (0)
    471 
    472 #define TestImplValues(Dst, Value0, Src, Value1, Size)                         \
    473   do {                                                                         \
    474     TestImplRegReg(Dst, Value0, Src, Value1, Size);                            \
    475     TestImplRegImm(Dst, Value0, Value1, Size);                                 \
    476     TestImplAddrReg(Value0, Src, Value1, Size);                                \
    477     TestImplAddrImm(Value0, Value1, Size);                                     \
    478   } while (0)
    479 
    480 #define TestImplSize(Dst, Src, Size)                                           \
    481   do {                                                                         \
    482     TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size);                    \
    483     TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size);                    \
    484     TestImplValues(Dst, 0x0F00000F, Src, 0xF00000F0, Size);                    \
    485   } while (0)
    486 
    487 #define TestImpl(Dst, Src)                                                     \
    488   do {                                                                         \
    489     TestImplSize(Dst, Src, 8);                                                 \
    490     TestImplSize(Dst, Src, 16);                                                \
    491     TestImplSize(Dst, Src, 32);                                                \
    492   } while (0)
    493 
    494   TestImpl(r1, r2);
    495   TestImpl(r2, r3);
    496   TestImpl(r3, r4);
    497   TestImpl(r4, r5);
    498   TestImpl(r5, r6);
    499   TestImpl(r6, r7);
    500   TestImpl(r7, r8);
    501   TestImpl(r8, r10);
    502   TestImpl(r10, r11);
    503   TestImpl(r11, r12);
    504   TestImpl(r12, r13);
    505   TestImpl(r13, r14);
    506   TestImpl(r14, r15);
    507   TestImpl(r15, r1);
    508 
    509 #undef TestImpl
    510 #undef TestImplSize
    511 #undef TestImplValues
    512 #undef TestImplAddrImm
    513 #undef TestImplAddrReg
    514 #undef TestImplRegImm
    515 #undef TestImplRegReg
    516 }
    517 
    518 // No mull/div because x86.
    519 // No shift because x86.
    520 TEST_F(AssemblerX8664Test, Arith_most) {
    521   static constexpr uint32_t Mask8 = 0xFF;
    522   static constexpr uint32_t Mask16 = 0xFFFF;
    523   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
    524 
    525 #define TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op)         \
    526   do {                                                                         \
    527     static constexpr char TestString[] =                                       \
    528         "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1                \
    529         ", " #Type #Size "_t, " #Op ")";                                       \
    530                                                                                \
    531     __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0));           \
    532     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1));           \
    533     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());        \
    534                                                                                \
    535     AssembledTest test = assemble();                                           \
    536     test.run();                                                                \
    537                                                                                \
    538     ASSERT_EQ(Mask##Size &static_cast<uint32_t>(                               \
    539                   static_cast<Type##Size##_t>((Value0)&Mask##Size)             \
    540                       Op static_cast<Type##Size##_t>((Value1)&Mask##Size)),    \
    541               Mask##Size &test.Dst())                                          \
    542         << TestString;                                                         \
    543     reset();                                                                   \
    544   } while (0)
    545 
    546 #define TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op)             \
    547   do {                                                                         \
    548     static constexpr char TestString[] =                                       \
    549         "(" #Inst ", " #Dst ", " #Value0 ", Addr, " #Value1 ", " #Type #Size   \
    550         "_t, " #Op ")";                                                        \
    551     const uint32_t T0 = allocateDword();                                       \
    552     const uint32_t V0 = Value1;                                                \
    553                                                                                \
    554     __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0));           \
    555     __ mov(IceType_i##Size, dwordAddress(T0), Immediate(Value1));              \
    556     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0));           \
    557                                                                                \
    558     AssembledTest test = assemble();                                           \
    559     test.setDwordTo(T0, V0);                                                   \
    560     test.run();                                                                \
    561                                                                                \
    562     ASSERT_EQ(Mask##Size &static_cast<uint32_t>(                               \
    563                   static_cast<Type##Size##_t>((Value0)&Mask##Size)             \
    564                       Op static_cast<Type##Size##_t>((Value1)&Mask##Size)),    \
    565               Mask##Size &test.Dst())                                          \
    566         << TestString;                                                         \
    567     reset();                                                                   \
    568   } while (0)
    569 
    570 #define TestImplRegImm(Inst, Dst, Value0, Imm, Type, Size, Op)                 \
    571   do {                                                                         \
    572     static constexpr char TestString[] =                                       \
    573         "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Type #Size       \
    574         "_t, " #Op ")";                                                        \
    575                                                                                \
    576     __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0));           \
    577     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(),                              \
    578             Immediate((Imm)&Mask##Size));                                      \
    579                                                                                \
    580     AssembledTest test = assemble();                                           \
    581     test.run();                                                                \
    582                                                                                \
    583     ASSERT_EQ(Mask##Size &static_cast<uint32_t>(                               \
    584                   static_cast<Type##Size##_t>((Value0)&Mask##Size)             \
    585                       Op static_cast<Type##Size##_t>((Imm)&Mask##Size)),       \
    586               Mask##Size &test.Dst())                                          \
    587         << TestString;                                                         \
    588     reset();                                                                   \
    589   } while (0)
    590 
    591 #define TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op)             \
    592   do {                                                                         \
    593     static constexpr char TestString[] =                                       \
    594         "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Type #Size   \
    595         "_t, " #Op ")";                                                        \
    596     const uint32_t T0 = allocateDword();                                       \
    597     const uint32_t V0 = Value0;                                                \
    598                                                                                \
    599     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1));           \
    600     __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src());           \
    601                                                                                \
    602     AssembledTest test = assemble();                                           \
    603     test.setDwordTo(T0, V0);                                                   \
    604     test.run();                                                                \
    605                                                                                \
    606     ASSERT_EQ(Mask##Size &static_cast<uint32_t>(                               \
    607                   static_cast<Type##Size##_t>((Value0)&Mask##Size)             \
    608                       Op static_cast<Type##Size##_t>((Value1)&Mask##Size)),    \
    609               Mask##Size &test.contentsOfDword(T0))                            \
    610         << TestString;                                                         \
    611     reset();                                                                   \
    612   } while (0)
    613 
    614 #define TestImplAddrImm(Inst, Value0, Imm, Type, Size, Op)                     \
    615   do {                                                                         \
    616     static constexpr char TestString[] =                                       \
    617         "(" #Inst ", Addr, " #Value0 ", Imm, " #Imm ", " #Type #Size           \
    618         "_t, " #Op ")";                                                        \
    619     const uint32_t T0 = allocateDword();                                       \
    620     const uint32_t V0 = Value0;                                                \
    621                                                                                \
    622     __ Inst(IceType_i##Size, dwordAddress(T0), Immediate((Imm)&Mask##Size));   \
    623                                                                                \
    624     AssembledTest test = assemble();                                           \
    625     test.setDwordTo(T0, V0);                                                   \
    626     test.run();                                                                \
    627                                                                                \
    628     ASSERT_EQ(Mask##Size &static_cast<uint32_t>(                               \
    629                   static_cast<Type##Size##_t>((Value0)&Mask##Size)             \
    630                       Op static_cast<Type##Size##_t>((Imm)&Mask##Size)),       \
    631               Mask##Size &test.contentsOfDword(T0))                            \
    632         << TestString;                                                         \
    633     reset();                                                                   \
    634   } while (0)
    635 
    636 #define TestImplOp(Inst, Dst, Value0, Src, Value1, Type, Size, Op)             \
    637   do {                                                                         \
    638     TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op);            \
    639     TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op);                \
    640     TestImplRegImm(Inst, Dst, Value0, Value1, Type, Size, Op);                 \
    641     TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op);                \
    642     TestImplAddrImm(Inst, Value0, Value1, Type, Size, Op);                     \
    643   } while (0)
    644 
    645 #define TestImplValues(Dst, Value0, Src, Value1, Size)                         \
    646   do {                                                                         \
    647     TestImplOp(And, Dst, Value0, Src, Value1, int, Size, &);                   \
    648     TestImplOp(And, Dst, Value0, Src, Value1, uint, Size, &);                  \
    649     TestImplOp(Or, Dst, Value0, Src, Value1, int, Size, | );                   \
    650     TestImplOp(Or, Dst, Value0, Src, Value1, uint, Size, | );                  \
    651     TestImplOp(Xor, Dst, Value0, Src, Value1, int, Size, ^);                   \
    652     TestImplOp(Xor, Dst, Value0, Src, Value1, uint, Size, ^);                  \
    653     TestImplOp(add, Dst, Value0, Src, Value1, int, Size, +);                   \
    654     TestImplOp(add, Dst, Value0, Src, Value1, uint, Size, +);                  \
    655     TestImplOp(sub, Dst, Value0, Src, Value1, int, Size, -);                   \
    656     TestImplOp(sub, Dst, Value0, Src, Value1, uint, Size, -);                  \
    657   } while (0)
    658 
    659 #define TestImplSize(Dst, Src, Size)                                           \
    660   do {                                                                         \
    661     TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size);                    \
    662     TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size);                    \
    663     TestImplValues(Dst, 0x0F00000F, Src, 0xF0000070, Size);                    \
    664     TestImplValues(Dst, 0x0F00F00F, Src, 0xF000F070, Size);                    \
    665   } while (0)
    666 
    667 #define TestImpl(Dst, Src)                                                     \
    668   do {                                                                         \
    669     TestImplSize(Dst, Src, 8);                                                 \
    670     TestImplSize(Dst, Src, 16);                                                \
    671     TestImplSize(Dst, Src, 32);                                                \
    672   } while (0)
    673 
    674   TestImpl(r1, r2);
    675   TestImpl(r2, r3);
    676   TestImpl(r3, r4);
    677   TestImpl(r4, r5);
    678   TestImpl(r5, r6);
    679   TestImpl(r6, r7);
    680   TestImpl(r7, r8);
    681   TestImpl(r8, r10);
    682   TestImpl(r10, r11);
    683   TestImpl(r11, r12);
    684   TestImpl(r12, r13);
    685   TestImpl(r13, r14);
    686   TestImpl(r14, r15);
    687   TestImpl(r15, r1);
    688 
    689 #undef TestImpl
    690 #undef TestImplSize
    691 #undef TestImplValues
    692 #undef TestImplOp
    693 #undef TestImplAddrImm
    694 #undef TestImplAddrReg
    695 #undef TestImplRegImm
    696 #undef TestImplRegAddr
    697 #undef TestImplRegReg
    698 }
    699 
    700 TEST_F(AssemblerX8664Test, Arith_BorrowNCarry) {
    701   const uint32_t Mask8 = 0x000000FF;
    702   const uint32_t Mask16 = 0x0000FFFF;
    703   const uint32_t Mask32 = 0xFFFFFFFF;
    704 
    705   const uint64_t ResultMask8 = 0x000000000000FFFFull;
    706   const uint64_t ResultMask16 = 0x00000000FFFFFFFFull;
    707   const uint64_t ResultMask32 = 0xFFFFFFFFFFFFFFFFull;
    708 
    709 #define TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1,   \
    710                        Op, Size)                                               \
    711   do {                                                                         \
    712     static_assert(Size == 8 || Size == 16 || Size == 32,                       \
    713                   "Invalid size " #Size);                                      \
    714     static constexpr char TestString[] =                                       \
    715         "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 ", " #Src0   \
    716         ", " #Src1 ", " #Value1 ", " #Op ", " #Size ")";                       \
    717     __ mov(IceType_i##Size, Encoded_GPR_##Dst0(),                              \
    718            Immediate(uint64_t(Value0) & Mask##Size));                          \
    719     __ mov(IceType_i##Size, Encoded_GPR_##Dst1(),                              \
    720            Immediate((uint64_t(Value0) >> Size) & Mask##Size));                \
    721     __ mov(IceType_i##Size, Encoded_GPR_##Src0(),                              \
    722            Immediate(uint64_t(Value1) & Mask##Size));                          \
    723     __ mov(IceType_i##Size, Encoded_GPR_##Src1(),                              \
    724            Immediate((uint64_t(Value1) >> Size) & Mask##Size));                \
    725     __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), Encoded_GPR_##Src0());     \
    726     __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), Encoded_GPR_##Src1());     \
    727                                                                                \
    728     AssembledTest test = assemble();                                           \
    729     test.run();                                                                \
    730                                                                                \
    731     static constexpr uint64_t Result =                                         \
    732         (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) &             \
    733                                                 ResultMask##Size);             \
    734     static constexpr uint32_t Expected0 = Result & Mask##Size;                 \
    735     static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size;       \
    736     ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0";                  \
    737     ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1";                  \
    738     reset();                                                                   \
    739   } while (0)
    740 
    741 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size)    \
    742   do {                                                                         \
    743     static_assert(Size == 8 || Size == 16 || Size == 32,                       \
    744                   "Invalid size " #Size);                                      \
    745     static constexpr char TestString[] =                                       \
    746         "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0              \
    747         ", Addr, " #Value1 ", " #Op ", " #Size ")";                            \
    748     const uint32_t T0 = allocateDword();                                       \
    749     const uint32_t V0 = uint64_t(Value1) & Mask##Size;                         \
    750     const uint32_t T1 = allocateDword();                                       \
    751     const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size;               \
    752     __ mov(IceType_i##Size, Encoded_GPR_##Dst0(),                              \
    753            Immediate(uint64_t(Value0) & Mask##Size));                          \
    754     __ mov(IceType_i##Size, Encoded_GPR_##Dst1(),                              \
    755            Immediate((uint64_t(Value0) >> Size) & Mask##Size));                \
    756     __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), dwordAddress(T0));         \
    757     __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), dwordAddress(T1));         \
    758                                                                                \
    759     AssembledTest test = assemble();                                           \
    760     test.setDwordTo(T0, V0);                                                   \
    761     test.setDwordTo(T1, V1);                                                   \
    762     test.run();                                                                \
    763                                                                                \
    764     static constexpr uint64_t Result =                                         \
    765         (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) &             \
    766                                                 ResultMask##Size);             \
    767     static constexpr uint32_t Expected0 = Result & Mask##Size;                 \
    768     static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size;       \
    769     ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0";                  \
    770     ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1";                  \
    771     reset();                                                                   \
    772   } while (0)
    773 
    774 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size)        \
    775   do {                                                                         \
    776     static_assert(Size == 8 || Size == 16 || Size == 32,                       \
    777                   "Invalid size " #Size);                                      \
    778     static constexpr char TestString[] =                                       \
    779         "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0              \
    780         ", Imm(" #Imm "), " #Op ", " #Size ")";                                \
    781     __ mov(IceType_i##Size, Encoded_GPR_##Dst0(),                              \
    782            Immediate(uint64_t(Value0) & Mask##Size));                          \
    783     __ mov(IceType_i##Size, Encoded_GPR_##Dst1(),                              \
    784            Immediate((uint64_t(Value0) >> Size) & Mask##Size));                \
    785     __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(),                            \
    786              Immediate(uint64_t(Imm) & Mask##Size));                           \
    787     __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(),                            \
    788              Immediate((uint64_t(Imm) >> Size) & Mask##Size));                 \
    789                                                                                \
    790     AssembledTest test = assemble();                                           \
    791     test.run();                                                                \
    792                                                                                \
    793     static constexpr uint64_t Result =                                         \
    794         (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) &                \
    795                                                 ResultMask##Size);             \
    796     static constexpr uint32_t Expected0 = Result & Mask##Size;                 \
    797     static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size;       \
    798     ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0";                  \
    799     ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1";                  \
    800     reset();                                                                   \
    801   } while (0)
    802 
    803 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size)    \
    804   do {                                                                         \
    805     static_assert(Size == 8 || Size == 16 || Size == 32,                       \
    806                   "Invalid size " #Size);                                      \
    807     static constexpr char TestString[] =                                       \
    808         "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1        \
    809         ", " #Value1 ", " #Op ", " #Size ")";                                  \
    810     const uint32_t T0 = allocateDword();                                       \
    811     const uint32_t V0 = uint64_t(Value0) & Mask##Size;                         \
    812     const uint32_t T1 = allocateDword();                                       \
    813     const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size;               \
    814     __ mov(IceType_i##Size, Encoded_GPR_##Src0(),                              \
    815            Immediate(uint64_t(Value1) & Mask##Size));                          \
    816     __ mov(IceType_i##Size, Encoded_GPR_##Src1(),                              \
    817            Immediate((uint64_t(Value1) >> Size) & Mask##Size));                \
    818     __ Inst0(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src0());         \
    819     __ Inst1(IceType_i##Size, dwordAddress(T1), Encoded_GPR_##Src1());         \
    820                                                                                \
    821     AssembledTest test = assemble();                                           \
    822     test.setDwordTo(T0, V0);                                                   \
    823     test.setDwordTo(T1, V1);                                                   \
    824     test.run();                                                                \
    825                                                                                \
    826     static constexpr uint64_t Result =                                         \
    827         (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) &             \
    828                                                 ResultMask##Size);             \
    829     static constexpr uint32_t Expected0 = Result & Mask##Size;                 \
    830     static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size;       \
    831     ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0";     \
    832     ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1";     \
    833     reset();                                                                   \
    834   } while (0)
    835 
    836 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size)                   \
    837   do {                                                                         \
    838     static_assert(Size == 8 || Size == 16 || Size == 32,                       \
    839                   "Invalid size " #Size);                                      \
    840     static constexpr char TestString[] =                                       \
    841         "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op      \
    842         ", " #Size ")";                                                        \
    843     const uint32_t T0 = allocateDword();                                       \
    844     const uint32_t V0 = uint64_t(Value0) & Mask##Size;                         \
    845     const uint32_t T1 = allocateDword();                                       \
    846     const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size;               \
    847     __ Inst0(IceType_i##Size, dwordAddress(T0),                                \
    848              Immediate(uint64_t(Imm) & Mask##Size));                           \
    849     __ Inst1(IceType_i##Size, dwordAddress(T1),                                \
    850              Immediate((uint64_t(Imm) >> Size) & Mask##Size));                 \
    851                                                                                \
    852     AssembledTest test = assemble();                                           \
    853     test.setDwordTo(T0, V0);                                                   \
    854     test.setDwordTo(T1, V1);                                                   \
    855     test.run();                                                                \
    856                                                                                \
    857     static constexpr uint64_t Result =                                         \
    858         (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) &                \
    859                                                 ResultMask##Size);             \
    860     static constexpr uint32_t Expected0 = Result & Mask##Size;                 \
    861     static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size;       \
    862     ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0";     \
    863     ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1";     \
    864     reset();                                                                   \
    865   } while (0)
    866 
    867 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op,   \
    868                    Size)                                                       \
    869   do {                                                                         \
    870     TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op,   \
    871                    Size);                                                      \
    872     TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size);       \
    873     TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size);        \
    874     TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size);       \
    875     TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size);                   \
    876   } while (0)
    877 
    878 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size)           \
    879   do {                                                                         \
    880     TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size);     \
    881     TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size);     \
    882   } while (0)
    883 
    884 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size)                             \
    885   do {                                                                         \
    886     TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1,              \
    887                    0xFFFFFFFF0000017Full, Size);                               \
    888   } while (0)
    889 
    890 #define TestImpl(Dst0, Dst1, Src0, Src1)                                       \
    891   do {                                                                         \
    892     TestImplSize(Dst0, Dst1, Src0, Src1, 8);                                   \
    893     TestImplSize(Dst0, Dst1, Src0, Src1, 16);                                  \
    894     TestImplSize(Dst0, Dst1, Src0, Src1, 32);                                  \
    895   } while (0)
    896 
    897   TestImpl(r1, r2, r3, r5);
    898   TestImpl(r2, r3, r4, r6);
    899   TestImpl(r3, r4, r5, r7);
    900   TestImpl(r4, r5, r6, r8);
    901   TestImpl(r5, r6, r7, r10);
    902   TestImpl(r6, r7, r8, r11);
    903   TestImpl(r7, r8, r10, r12);
    904   TestImpl(r8, r10, r11, r13);
    905   TestImpl(r10, r11, r12, r14);
    906   TestImpl(r11, r12, r13, r15);
    907   TestImpl(r12, r13, r14, r1);
    908   TestImpl(r13, r14, r15, r2);
    909   TestImpl(r14, r15, r1, r3);
    910   TestImpl(r15, r1, r2, r4);
    911 
    912 #undef TestImpl
    913 #undef TestImplSize
    914 #undef TestImplValues
    915 #undef TestImplOp
    916 #undef TestImplAddrImm
    917 #undef TestImplAddrReg
    918 #undef TestImplRegImm
    919 #undef TestImplRegAddr
    920 #undef TestImplRegReg
    921 }
    922 
    923 TEST_F(AssemblerX8664LowLevelTest, Cbw_Cwd_Cdq) {
    924 #define TestImpl(Inst, BytesSize, ...)                                         \
    925   do {                                                                         \
    926     __ Inst();                                                                 \
    927     ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst;                            \
    928     ASSERT_TRUE(verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__));             \
    929     reset();                                                                   \
    930   } while (0)
    931 
    932   TestImpl(cbw, 2u, 0x66, 0x98);
    933   TestImpl(cwd, 2u, 0x66, 0x99);
    934   TestImpl(cdq, 1u, 0x99);
    935 
    936 #undef TestImpl
    937 }
    938 
    939 TEST_F(AssemblerX8664Test, SingleOperandMul) {
    940   static constexpr uint32_t Mask8 = 0x000000FF;
    941   static constexpr uint32_t Mask16 = 0x0000FFFF;
    942   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
    943 
    944 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size)                     \
    945   do {                                                                         \
    946     static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(),                    \
    947                   "eax can not be src1.");                                     \
    948                                                                                \
    949     static constexpr char TestString[] =                                       \
    950         "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size    \
    951         ")";                                                                   \
    952     static constexpr Type##64_t OperandEax =                                   \
    953         static_cast<Type##Size##_t>((Value0)&Mask##Size);                      \
    954     static constexpr Type##64_t OperandOther =                                 \
    955         static_cast<Type##Size##_t>((Value1)&Mask##Size);                      \
    956     static constexpr uint32_t ExpectedEax =                                    \
    957         Mask##Size & (OperandEax * OperandOther);                              \
    958     static constexpr uint32_t ExpectedEdx =                                    \
    959         Mask##Size & ((OperandEax * OperandOther) >> Size);                    \
    960                                                                                \
    961     __ mov(IceType_i##Size, Encoded_GPR_eax(),                                 \
    962            Immediate((Value0)&Mask##Size));                                    \
    963     __ mov(IceType_i##Size, Encoded_GPR_##Src(),                               \
    964            Immediate((Value1)&Mask##Size));                                    \
    965     __ Inst(IceType_i##Size, Encoded_GPR_##Src());                             \
    966                                                                                \
    967     if (Size == 8) {                                                           \
    968       /* mov %ah, %dl */                                                       \
    969       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
    970       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
    971       __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF));                \
    972     }                                                                          \
    973                                                                                \
    974     AssembledTest test = assemble();                                           \
    975     test.run();                                                                \
    976                                                                                \
    977     ASSERT_EQ(ExpectedEax, test.eax()) << TestString;                          \
    978     ASSERT_EQ(ExpectedEdx, test.edx()) << TestString;                          \
    979     reset();                                                                   \
    980   } while (0)
    981 
    982 #define TestImplAddr(Inst, Value0, Value1, Type, Size)                         \
    983   do {                                                                         \
    984     static constexpr char TestString[] =                                       \
    985         "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")";   \
    986     static const uint32_t T0 = allocateDword();                                \
    987     static constexpr uint32_t V0 = Value1;                                     \
    988     static constexpr Type##64_t OperandEax =                                   \
    989         static_cast<Type##Size##_t>((Value0)&Mask##Size);                      \
    990     static constexpr Type##64_t OperandOther =                                 \
    991         static_cast<Type##Size##_t>((Value1)&Mask##Size);                      \
    992     static constexpr uint32_t ExpectedEax =                                    \
    993         Mask##Size & (OperandEax * OperandOther);                              \
    994     static constexpr uint32_t ExpectedEdx =                                    \
    995         Mask##Size & ((OperandEax * OperandOther) >> Size);                    \
    996                                                                                \
    997     __ mov(IceType_i##Size, Encoded_GPR_eax(),                                 \
    998            Immediate((Value0)&Mask##Size));                                    \
    999     __ Inst(IceType_i##Size, dwordAddress(T0));                                \
   1000                                                                                \
   1001     if (Size == 8) {                                                           \
   1002       /* mov %ah, %dl */                                                       \
   1003       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1004       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1005       __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF));                \
   1006     }                                                                          \
   1007                                                                                \
   1008     AssembledTest test = assemble();                                           \
   1009     test.setDwordTo(T0, V0);                                                   \
   1010     test.run();                                                                \
   1011                                                                                \
   1012     ASSERT_EQ(ExpectedEax, test.eax()) << TestString;                          \
   1013     ASSERT_EQ(ExpectedEdx, test.edx()) << TestString;                          \
   1014     reset();                                                                   \
   1015   } while (0)
   1016 
   1017 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size)                      \
   1018   do {                                                                         \
   1019     TestImplReg(Inst, Value0, Src, Value1, Type, Size);                        \
   1020     TestImplAddr(Inst, Value0, Value1, Type, Size);                            \
   1021   } while (0)
   1022 
   1023 #define TestImplValue(Value0, Src, Value1, Size)                               \
   1024   do {                                                                         \
   1025     TestImplOp(mul, Value0, Src, Value1, uint, Size);                          \
   1026     TestImplOp(imul, Value0, Src, Value1, int, Size);                          \
   1027   } while (0)
   1028 
   1029 #define TestImplSize(Src, Size)                                                \
   1030   do {                                                                         \
   1031     TestImplValue(10, Src, 1, Size);                                           \
   1032     TestImplValue(10, Src, -1, Size);                                          \
   1033     TestImplValue(-10, Src, 37, Size);                                         \
   1034     TestImplValue(-10, Src, -15, Size);                                        \
   1035   } while (0)
   1036 
   1037 #define TestImpl(Src)                                                          \
   1038   do {                                                                         \
   1039     TestImplSize(Src, 8);                                                      \
   1040     TestImplSize(Src, 16);                                                     \
   1041     TestImplSize(Src, 32);                                                     \
   1042   } while (0)
   1043 
   1044   TestImpl(r2);
   1045   TestImpl(r3);
   1046   TestImpl(r4);
   1047   TestImpl(r5);
   1048   TestImpl(r6);
   1049   TestImpl(r7);
   1050   TestImpl(r8);
   1051   TestImpl(r10);
   1052   TestImpl(r11);
   1053   TestImpl(r12);
   1054   TestImpl(r13);
   1055   TestImpl(r14);
   1056   TestImpl(r15);
   1057 
   1058 #undef TestImpl
   1059 #undef TestImplSize
   1060 #undef TestImplValue
   1061 #undef TestImplOp
   1062 #undef TestImplAddr
   1063 #undef TestImplReg
   1064 }
   1065 
   1066 TEST_F(AssemblerX8664Test, TwoOperandImul) {
   1067   static constexpr uint32_t Mask16 = 0x0000FFFF;
   1068   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
   1069 
   1070 #define TestImplRegReg(Dst, Value0, Src, Value1, Size)                         \
   1071   do {                                                                         \
   1072     static constexpr char TestString[] =                                       \
   1073         "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")";           \
   1074     static constexpr int64_t Operand0 =                                        \
   1075         static_cast<int##Size##_t>((Value0)&Mask##Size);                       \
   1076     static constexpr int64_t Operand1 =                                        \
   1077         static_cast<int##Size##_t>((Value1)&Mask##Size);                       \
   1078     static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1);   \
   1079                                                                                \
   1080     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1081            Immediate((Value0)&Mask##Size));                                    \
   1082     __ mov(IceType_i##Size, Encoded_GPR_##Src(),                               \
   1083            Immediate((Value1)&Mask##Size));                                    \
   1084     __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());        \
   1085                                                                                \
   1086     if (Size == 8) {                                                           \
   1087       /* mov %ah, %dl */                                                       \
   1088       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1089       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1090       __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF));                \
   1091     }                                                                          \
   1092                                                                                \
   1093     AssembledTest test = assemble();                                           \
   1094     test.run();                                                                \
   1095                                                                                \
   1096     ASSERT_EQ(Expected, test.Dst()) << TestString;                             \
   1097     reset();                                                                   \
   1098   } while (0)
   1099 
   1100 #define TestImplRegImm(Dst, Value0, Imm, Size)                                 \
   1101   do {                                                                         \
   1102     static constexpr char TestString[] =                                       \
   1103         "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")";                   \
   1104     static constexpr int64_t Operand0 =                                        \
   1105         static_cast<int##Size##_t>((Value0)&Mask##Size);                       \
   1106     static constexpr int64_t Operand1 =                                        \
   1107         static_cast<int##Size##_t>((Imm)&Mask##Size);                          \
   1108     static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1);   \
   1109                                                                                \
   1110     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1111            Immediate((Value0)&Mask##Size));                                    \
   1112     __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Imm));             \
   1113                                                                                \
   1114     if (Size == 8) {                                                           \
   1115       /* mov %ah, %dl */                                                       \
   1116       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1117       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1118       __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF));                \
   1119     }                                                                          \
   1120                                                                                \
   1121     AssembledTest test = assemble();                                           \
   1122     test.run();                                                                \
   1123                                                                                \
   1124     ASSERT_EQ(Expected, test.Dst()) << TestString;                             \
   1125     reset();                                                                   \
   1126   } while (0)
   1127 
   1128 #define TestImplRegAddr(Dst, Value0, Value1, Size)                             \
   1129   do {                                                                         \
   1130     static constexpr char TestString[] =                                       \
   1131         "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")";                \
   1132     static constexpr int64_t Operand0 =                                        \
   1133         static_cast<int##Size##_t>((Value0)&Mask##Size);                       \
   1134     static constexpr int64_t Operand1 =                                        \
   1135         static_cast<int##Size##_t>((Value1)&Mask##Size);                       \
   1136     static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1);   \
   1137     const uint32_t T0 = allocateDword();                                       \
   1138                                                                                \
   1139     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1140            Immediate((Value0)&Mask##Size));                                    \
   1141     __ imul(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0));           \
   1142                                                                                \
   1143     if (Size == 8) {                                                           \
   1144       /* mov %ah, %dl */                                                       \
   1145       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1146       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1147       __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF));                \
   1148     }                                                                          \
   1149                                                                                \
   1150     AssembledTest test = assemble();                                           \
   1151     test.setDwordTo(T0, static_cast<uint32_t>(Operand1));                      \
   1152     test.run();                                                                \
   1153                                                                                \
   1154     ASSERT_EQ(Expected, test.Dst()) << TestString;                             \
   1155     reset();                                                                   \
   1156   } while (0)
   1157 
   1158 #define TestImplValue(Dst, Value0, Src, Value1, Size)                          \
   1159   do {                                                                         \
   1160     TestImplRegReg(Dst, Value0, Src, Value1, Size);                            \
   1161     TestImplRegImm(Dst, Value0, Value1, Size);                                 \
   1162     TestImplRegAddr(Dst, Value0, Value1, Size);                                \
   1163   } while (0)
   1164 
   1165 #define TestImplSize(Dst, Src, Size)                                           \
   1166   do {                                                                         \
   1167     TestImplValue(Dst, 1, Src, 1, Size);                                       \
   1168     TestImplValue(Dst, -10, Src, 0x4050AA20, Size);                            \
   1169     TestImplValue(Dst, -2, Src, -55, Size);                                    \
   1170   } while (0)
   1171 
   1172 #define TestImpl(Dst, Src)                                                     \
   1173   do {                                                                         \
   1174     TestImplSize(Dst, Src, 16);                                                \
   1175     TestImplSize(Dst, Src, 32);                                                \
   1176   } while (0)
   1177 
   1178   TestImpl(r1, r2);
   1179   TestImpl(r2, r3);
   1180   TestImpl(r3, r4);
   1181   TestImpl(r4, r5);
   1182   TestImpl(r5, r6);
   1183   TestImpl(r6, r7);
   1184   TestImpl(r7, r8);
   1185   TestImpl(r8, r10);
   1186   TestImpl(r10, r11);
   1187   TestImpl(r11, r12);
   1188   TestImpl(r12, r13);
   1189   TestImpl(r13, r14);
   1190   TestImpl(r14, r15);
   1191   TestImpl(r15, r1);
   1192 
   1193 #undef TestImpl
   1194 #undef TestImplSize
   1195 #undef TestImplValue
   1196 #undef TestImplRegAddr
   1197 #undef TestImplRegImm
   1198 #undef TestImplRegReg
   1199 }
   1200 
   1201 TEST_F(AssemblerX8664Test, Div) {
   1202   static constexpr uint32_t Mask8 = 0x000000FF;
   1203   static constexpr uint32_t Mask16 = 0x0000FFFF;
   1204   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
   1205 
   1206   static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull;
   1207   static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull;
   1208   static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull;
   1209 
   1210   using Operand0Type_int8 = int16_t;
   1211   using Operand0Type_uint8 = uint16_t;
   1212   using Operand0Type_int16 = int32_t;
   1213   using Operand0Type_uint16 = uint32_t;
   1214   using Operand0Type_int32 = int64_t;
   1215   using Operand0Type_uint32 = uint64_t;
   1216 
   1217 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size)                     \
   1218   do {                                                                         \
   1219     static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(),                    \
   1220                   "eax can not be src1.");                                     \
   1221     static_assert(Encoded_GPR_edx() != Encoded_GPR_##Src(),                    \
   1222                   "edx can not be src1.");                                     \
   1223                                                                                \
   1224     static constexpr char TestString[] =                                       \
   1225         "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size    \
   1226         ")";                                                                   \
   1227     static constexpr Operand0Type_##Type##Size Operand0 =                      \
   1228         static_cast<Type##64_t>(Value0) & Operand0Mask##Size;                  \
   1229     static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size;        \
   1230     static constexpr Type##Size##_t Operand0Hi =                               \
   1231         (Operand0 >> Size) & Mask##Size;                                       \
   1232     static constexpr Type##Size##_t Operand1 =                                 \
   1233         static_cast<Type##Size##_t>(Value1) & Mask##Size;                      \
   1234     if (Size == 8) {                                                           \
   1235       /* mov Operand0Hi|Operand0Lo, %ah|%al */                                 \
   1236       __ mov(                                                                  \
   1237           IceType_i16, Encoded_GPR_eax(),                                      \
   1238           Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo)));   \
   1239     } else {                                                                   \
   1240       __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo));       \
   1241       __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi));       \
   1242     }                                                                          \
   1243     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Operand1));         \
   1244     __ Inst(IceType_i##Size, Encoded_GPR_##Src());                             \
   1245     if (Size == 8) {                                                           \
   1246       /* mov %ah, %dl */                                                       \
   1247       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1248       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1249       __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF));               \
   1250       if (Encoded_GPR_##Src() == Encoded_GPR_esi()) {                          \
   1251         __ And(IceType_i16, Encoded_GPR_edx(), Immediate(0x00FF));             \
   1252       }                                                                        \
   1253     }                                                                          \
   1254                                                                                \
   1255     AssembledTest test = assemble();                                           \
   1256     test.run();                                                                \
   1257                                                                                \
   1258     static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size;   \
   1259     static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size;   \
   1260     ASSERT_EQ(Quocient, test.eax()) << TestString;                             \
   1261     ASSERT_EQ(Reminder, test.edx()) << TestString;                             \
   1262     reset();                                                                   \
   1263   } while (0)
   1264 
   1265 #define TestImplAddr(Inst, Value0, Value1, Type, Size)                         \
   1266   do {                                                                         \
   1267     static constexpr char TestString[] =                                       \
   1268         "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")";   \
   1269     static constexpr Operand0Type_##Type##Size Operand0 =                      \
   1270         static_cast<Type##64_t>(Value0) & Operand0Mask##Size;                  \
   1271     static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size;        \
   1272     static constexpr Type##Size##_t Operand0Hi =                               \
   1273         (Operand0 >> Size) & Mask##Size;                                       \
   1274     const uint32_t T0 = allocateDword();                                       \
   1275     static constexpr Type##Size##_t V0 =                                       \
   1276         static_cast<Type##Size##_t>(Value1) & Mask##Size;                      \
   1277     if (Size == 8) {                                                           \
   1278       /* mov Operand0Hi|Operand0Lo, %ah|%al */                                 \
   1279       __ mov(                                                                  \
   1280           IceType_i16, Encoded_GPR_eax(),                                      \
   1281           Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo)));   \
   1282     } else {                                                                   \
   1283       __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo));       \
   1284       __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi));       \
   1285     }                                                                          \
   1286     __ Inst(IceType_i##Size, dwordAddress(T0));                                \
   1287     if (Size == 8) {                                                           \
   1288       /* mov %ah, %dl */                                                       \
   1289       __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax());                 \
   1290       __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8));                    \
   1291       __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF));               \
   1292     }                                                                          \
   1293                                                                                \
   1294     AssembledTest test = assemble();                                           \
   1295     test.setDwordTo(T0, static_cast<uint32_t>(V0));                            \
   1296     test.run();                                                                \
   1297                                                                                \
   1298     static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size;         \
   1299     static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size;         \
   1300     ASSERT_EQ(Quocient, test.eax()) << TestString;                             \
   1301     ASSERT_EQ(Reminder, test.edx()) << TestString;                             \
   1302     reset();                                                                   \
   1303   } while (0)
   1304 
   1305 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size)                      \
   1306   do {                                                                         \
   1307     TestImplReg(Inst, Value0, Src, Value1, Type, Size);                        \
   1308     TestImplAddr(Inst, Value0, Value1, Type, Size);                            \
   1309   } while (0)
   1310 
   1311 #define TestImplValue(Value0, Src, Value1, Size)                               \
   1312   do {                                                                         \
   1313     TestImplOp(div, Value0, Src, Value1, uint, Size);                          \
   1314     TestImplOp(idiv, Value0, Src, Value1, int, Size);                          \
   1315   } while (0)
   1316 
   1317 #define TestImplSize(Src, Size)                                                \
   1318   do {                                                                         \
   1319     TestImplValue(10, Src, 1, Size);                                           \
   1320     TestImplValue(10, Src, -1, Size);                                          \
   1321   } while (0)
   1322 
   1323 #define TestImpl(Src)                                                          \
   1324   do {                                                                         \
   1325     TestImplSize(Src, 8);                                                      \
   1326     TestImplSize(Src, 16);                                                     \
   1327     TestImplSize(Src, 32);                                                     \
   1328   } while (0)
   1329 
   1330   TestImpl(r2);
   1331   TestImpl(r3);
   1332   TestImpl(r5);
   1333   TestImpl(r6);
   1334   TestImpl(r7);
   1335   TestImpl(r8);
   1336   TestImpl(r10);
   1337   TestImpl(r11);
   1338   TestImpl(r12);
   1339   TestImpl(r13);
   1340   TestImpl(r14);
   1341   TestImpl(r15);
   1342 
   1343 #undef TestImpl
   1344 #undef TestImplSize
   1345 #undef TestImplValue
   1346 #undef TestImplOp
   1347 #undef TestImplAddr
   1348 #undef TestImplReg
   1349 }
   1350 
   1351 TEST_F(AssemblerX8664Test, Incl_Decl_Addr) {
   1352 #define TestImpl(Inst, Value0)                                                 \
   1353   do {                                                                         \
   1354     const bool IsInc = std::string(#Inst).find("incl") != std::string::npos;   \
   1355     const uint32_t T0 = allocateDword();                                       \
   1356     const uint32_t V0 = Value0;                                                \
   1357                                                                                \
   1358     __ Inst(dwordAddress(T0));                                                 \
   1359                                                                                \
   1360     AssembledTest test = assemble();                                           \
   1361     test.setDwordTo(T0, V0);                                                   \
   1362     test.run();                                                                \
   1363                                                                                \
   1364     ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)),                \
   1365               test.contentsOfDword(T0));                                       \
   1366     reset();                                                                   \
   1367   } while (0)
   1368 
   1369 #define TestInc(Value0)                                                        \
   1370   do {                                                                         \
   1371     TestImpl(incl, Value0);                                                    \
   1372   } while (0)
   1373 
   1374 #define TestDec(Value0)                                                        \
   1375   do {                                                                         \
   1376     TestImpl(decl, Value0);                                                    \
   1377   } while (0)
   1378 
   1379   TestInc(230);
   1380 
   1381   TestDec(30);
   1382 
   1383 #undef TestInc
   1384 #undef TestDec
   1385 #undef TestImpl
   1386 }
   1387 
   1388 TEST_F(AssemblerX8664Test, Shifts) {
   1389   static constexpr uint32_t Mask8 = 0x000000FF;
   1390   static constexpr uint32_t Mask16 = 0x0000FFFF;
   1391   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
   1392 
   1393 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size)                 \
   1394   do {                                                                         \
   1395     static constexpr char TestString[] =                                       \
   1396         "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type    \
   1397         ", " #Size ")";                                                        \
   1398     const bool IsRol = std::string(#Inst).find("rol") != std::string::npos;    \
   1399     const uint##Size##_t Expected =                                            \
   1400         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) |            \
   1401                       (!IsRol ? 0 : (Value0) >> (Size - Imm)));                \
   1402                                                                                \
   1403     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1404            Immediate((Value0)&Mask##Size));                                    \
   1405     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(),                              \
   1406             Immediate((Imm)&Mask##Size));                                      \
   1407                                                                                \
   1408     AssembledTest test = assemble();                                           \
   1409     test.run();                                                                \
   1410                                                                                \
   1411     ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString;      \
   1412     reset();                                                                   \
   1413   } while (0)
   1414 
   1415 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1,     \
   1416                           Type, Size)                                          \
   1417   do {                                                                         \
   1418     static constexpr char TestString[] =                                       \
   1419         "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1                \
   1420         ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")";        \
   1421     const uint##Size##_t Expected =                                            \
   1422         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) |         \
   1423                       (static_cast<Type##64_t>(Value1) Op1(Size - Count)));    \
   1424                                                                                \
   1425     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1426            Immediate((Value0)&Mask##Size));                                    \
   1427     __ mov(IceType_i##Size, Encoded_GPR_##Src(),                               \
   1428            Immediate((Value1)&Mask##Size));                                    \
   1429     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src(),         \
   1430             Immediate(Count));                                                 \
   1431                                                                                \
   1432     AssembledTest test = assemble();                                           \
   1433     test.run();                                                                \
   1434                                                                                \
   1435     ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString;      \
   1436     reset();                                                                   \
   1437   } while (0)
   1438 
   1439 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size)                \
   1440   do {                                                                         \
   1441     static constexpr char TestString[] =                                       \
   1442         "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type       \
   1443         ", " #Size ")";                                                        \
   1444     const bool IsRol = std::string(#Inst).find("rol") != std::string::npos;    \
   1445     const uint##Size##_t Expected =                                            \
   1446         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) |          \
   1447                       (!IsRol ? 0 : Value0 >> (Size - Count)));                \
   1448                                                                                \
   1449     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1450            Immediate((Value0)&Mask##Size));                                    \
   1451     __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size));      \
   1452     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_ecx());          \
   1453                                                                                \
   1454     AssembledTest test = assemble();                                           \
   1455     test.run();                                                                \
   1456                                                                                \
   1457     ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString;      \
   1458     reset();                                                                   \
   1459   } while (0)
   1460 
   1461 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1,      \
   1462                          Type, Size)                                           \
   1463   do {                                                                         \
   1464     static constexpr char TestString[] =                                       \
   1465         "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count    \
   1466         ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")";                         \
   1467     const uint##Size##_t Expected =                                            \
   1468         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) |         \
   1469                       (static_cast<Type##64_t>(Value1) Op1(Size - Count)));    \
   1470                                                                                \
   1471     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1472            Immediate((Value0)&Mask##Size));                                    \
   1473     __ mov(IceType_i##Size, Encoded_GPR_##Src(),                               \
   1474            Immediate((Value1)&Mask##Size));                                    \
   1475     __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F));       \
   1476     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());        \
   1477                                                                                \
   1478     AssembledTest test = assemble();                                           \
   1479     test.run();                                                                \
   1480                                                                                \
   1481     ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString;      \
   1482     reset();                                                                   \
   1483   } while (0)
   1484 
   1485 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size)                    \
   1486   do {                                                                         \
   1487     static constexpr char TestString[] =                                       \
   1488         "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type           \
   1489         ", " #Size ")";                                                        \
   1490     const bool IsRol = std::string(#Inst).find("rol") != std::string::npos;    \
   1491     const uint##Size##_t Expected =                                            \
   1492         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) |          \
   1493                       (!IsRol ? 0 : Value0 >> (Size - Count)));                \
   1494     const uint32_t T0 = allocateDword();                                       \
   1495     const uint32_t V0 = Value0;                                                \
   1496                                                                                \
   1497     __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size));      \
   1498     __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_ecx());             \
   1499                                                                                \
   1500     AssembledTest test = assemble();                                           \
   1501     test.setDwordTo(T0, V0);                                                   \
   1502     test.run();                                                                \
   1503                                                                                \
   1504     ASSERT_EQ(static_cast<uint32_t>(Expected),                                 \
   1505               Mask##Size &test.contentsOfDword(T0))                            \
   1506         << TestString;                                                         \
   1507     reset();                                                                   \
   1508   } while (0)
   1509 
   1510 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type,    \
   1511                           Size)                                                \
   1512   do {                                                                         \
   1513     static constexpr char TestString[] =                                       \
   1514         "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count        \
   1515         ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")";                         \
   1516     const uint##Size##_t Expected =                                            \
   1517         Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) |         \
   1518                       (static_cast<Type##64_t>(Value1) Op1(Size - Count)));    \
   1519     const uint32_t T0 = allocateDword();                                       \
   1520                                                                                \
   1521     __ mov(IceType_i##Size, Encoded_GPR_##Src(),                               \
   1522            Immediate((Value1)&Mask##Size));                                    \
   1523     __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F));       \
   1524     __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src());           \
   1525                                                                                \
   1526     AssembledTest test = assemble();                                           \
   1527     test.setDwordTo(T0, static_cast<uint32_t>(Value0));                        \
   1528     test.run();                                                                \
   1529                                                                                \
   1530     ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0))       \
   1531         << TestString;                                                         \
   1532     reset();                                                                   \
   1533   } while (0)
   1534 
   1535 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size)                   \
   1536   do {                                                                         \
   1537     static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(),                    \
   1538                   "ecx should not be specified as Dst");                       \
   1539     TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size);                  \
   1540     TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size);                  \
   1541     TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size);                   \
   1542     TestImplAddrCl(Inst, Value0, Count, Op, Type, Size);                       \
   1543   } while (0)
   1544 
   1545 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0,     \
   1546                                Op1, Type, Size)                                \
   1547   do {                                                                         \
   1548     static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(),                    \
   1549                   "ecx should not be specified as Dst");                       \
   1550     static_assert(Encoded_GPR_##Src() != Encoded_GPR_ecx(),                    \
   1551                   "ecx should not be specified as Src");                       \
   1552     TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type,   \
   1553                       Size);                                                   \
   1554     TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type,    \
   1555                      Size);                                                    \
   1556     TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \
   1557   } while (0)
   1558 
   1559 #define TestImplValue(Dst, Value0, Count, Size)                                \
   1560   do {                                                                         \
   1561     TestImplOp(rol, Dst, Value0, Count, <<, uint, Size);                       \
   1562     TestImplOp(shl, Dst, Value0, Count, <<, uint, Size);                       \
   1563     TestImplOp(shr, Dst, Value0, Count, >>, uint, Size);                       \
   1564     TestImplOp(sar, Dst, Value0, Count, >>, int, Size);                        \
   1565   } while (0)
   1566 
   1567 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size)       \
   1568   do {                                                                         \
   1569     TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>,      \
   1570                            uint, Size);                                        \
   1571     TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<,      \
   1572                            uint, Size);                                        \
   1573   } while (0)
   1574 
   1575 #define TestImplSize(Dst, Size)                                                \
   1576   do {                                                                         \
   1577     TestImplValue(Dst, 0x8F, 3, Size);                                         \
   1578     TestImplValue(Dst, 0x8FFF, 7, Size);                                       \
   1579     TestImplValue(Dst, 0x8FFFF, 7, Size);                                      \
   1580   } while (0)
   1581 
   1582 #define TestImplThreeOperandSize(Dst, Src, Size)                               \
   1583   do {                                                                         \
   1584     TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size);              \
   1585   } while (0)
   1586 
   1587 #define TestImpl(Dst, Src)                                                     \
   1588   do {                                                                         \
   1589     TestImplSize(Dst, 8);                                                      \
   1590     TestImplSize(Dst, 16);                                                     \
   1591     TestImplThreeOperandSize(Dst, Src, 16);                                    \
   1592     TestImplSize(Dst, 32);                                                     \
   1593     TestImplThreeOperandSize(Dst, Src, 32);                                    \
   1594   } while (0)
   1595 
   1596   TestImpl(r1, r2);
   1597   TestImpl(r2, r4);
   1598   TestImpl(r4, r5);
   1599   TestImpl(r5, r6);
   1600   TestImpl(r6, r7);
   1601   TestImpl(r7, r8);
   1602   TestImpl(r8, r10);
   1603   TestImpl(r10, r11);
   1604   TestImpl(r11, r12);
   1605   TestImpl(r12, r13);
   1606   TestImpl(r13, r14);
   1607   TestImpl(r14, r15);
   1608   TestImpl(r15, r1);
   1609 
   1610 #undef TestImpl
   1611 #undef TestImplThreeOperandSize
   1612 #undef TestImplSize
   1613 #undef TestImplValue
   1614 #undef TestImplThreeOperandValue
   1615 #undef TestImplOp
   1616 #undef TestImplThreeOperandOp
   1617 #undef TestImplAddrCl
   1618 #undef TestImplRegRegCl
   1619 #undef TestImplRegCl
   1620 #undef TestImplRegRegImm
   1621 #undef TestImplRegImm
   1622 }
   1623 
   1624 TEST_F(AssemblerX8664Test, Neg) {
   1625   static constexpr uint32_t Mask8 = 0x000000ff;
   1626   static constexpr uint32_t Mask16 = 0x0000ffff;
   1627   static constexpr uint32_t Mask32 = 0xffffffff;
   1628 
   1629 #define TestImplReg(Dst, Size)                                                 \
   1630   do {                                                                         \
   1631     static constexpr int32_t Value = 0xFF00A543;                               \
   1632     __ mov(IceType_i##Size, Encoded_GPR_##Dst(),                               \
   1633            Immediate(static_cast<int##Size##_t>(Value) & Mask##Size));         \
   1634     __ neg(IceType_i##Size, Encoded_GPR_##Dst());                              \
   1635     __ mov(IceType_i##Size, Encoded_GPR_eax(), Encoded_GPR_##Dst());           \
   1636     __ And(IceType_i32, Encoded_GPR_eax(), Immediate(Mask##Size));             \
   1637                                                                                \
   1638     AssembledTest test = assemble();                                           \
   1639     test.run();                                                                \
   1640                                                                                \
   1641     ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size),           \
   1642               test.eax())                                                      \
   1643         << "(" #Dst ", " #Size ")";                                            \
   1644     reset();                                                                   \
   1645   } while (0)
   1646 
   1647 #define TestImplAddr(Size)                                                     \
   1648   do {                                                                         \
   1649     static constexpr int32_t Value = 0xFF00A543;                               \
   1650     const uint32_t T0 = allocateDword();                                       \
   1651     __ neg(IceType_i##Size, dwordAddress(T0));                                 \
   1652                                                                                \
   1653     AssembledTest test = assemble();                                           \
   1654     test.setDwordTo(T0, Value &Mask##Size);                                    \
   1655     test.run();                                                                \
   1656                                                                                \
   1657     ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size),           \
   1658               test.contentsOfDword(T0))                                        \
   1659         << "(Addr, " #Size ")";                                                \
   1660     reset();                                                                   \
   1661   } while (0)
   1662 
   1663 #define TestImpl(Size)                                                         \
   1664   do {                                                                         \
   1665     TestImplAddr(Size);                                                        \
   1666     TestImplReg(r1, Size);                                                     \
   1667     TestImplReg(r2, Size);                                                     \
   1668     TestImplReg(r3, Size);                                                     \
   1669     TestImplReg(r4, Size);                                                     \
   1670     TestImplReg(r5, Size);                                                     \
   1671     TestImplReg(r6, Size);                                                     \
   1672     TestImplReg(r7, Size);                                                     \
   1673     TestImplReg(r8, Size);                                                     \
   1674     TestImplReg(r10, Size);                                                    \
   1675     TestImplReg(r11, Size);                                                    \
   1676     TestImplReg(r12, Size);                                                    \
   1677     TestImplReg(r13, Size);                                                    \
   1678     TestImplReg(r14, Size);                                                    \
   1679     TestImplReg(r15, Size);                                                    \
   1680   } while (0)
   1681 
   1682   TestImpl(8);
   1683   TestImpl(16);
   1684   TestImpl(32);
   1685 
   1686 #undef TestImpl
   1687 #undef TestImplAddr
   1688 #undef TestImplReg
   1689 }
   1690 
   1691 TEST_F(AssemblerX8664Test, Not) {
   1692 #define TestImpl(Dst)                                                          \
   1693   do {                                                                         \
   1694     static constexpr uint32_t Value = 0xFF00A543;                              \
   1695     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value));                \
   1696     __ notl(Encoded_GPR_##Dst());                                              \
   1697                                                                                \
   1698     AssembledTest test = assemble();                                           \
   1699     test.run();                                                                \
   1700                                                                                \
   1701     ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")";                             \
   1702     reset();                                                                   \
   1703   } while (0)
   1704 
   1705   TestImpl(r1);
   1706   TestImpl(r2);
   1707   TestImpl(r3);
   1708   TestImpl(r4);
   1709   TestImpl(r5);
   1710   TestImpl(r6);
   1711   TestImpl(r7);
   1712   TestImpl(r8);
   1713   TestImpl(r10);
   1714   TestImpl(r11);
   1715   TestImpl(r12);
   1716   TestImpl(r13);
   1717   TestImpl(r14);
   1718   TestImpl(r15);
   1719 
   1720 #undef TestImpl
   1721 }
   1722 
   1723 TEST_F(AssemblerX8664Test, Bswap) {
   1724 #define TestImpl(Dst)                                                          \
   1725   do {                                                                         \
   1726     static constexpr uint32_t Value = 0xFF00A543;                              \
   1727     static constexpr uint32_t Expected = 0x43A500FF;                           \
   1728     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value));                \
   1729     __ bswap(IceType_i32, Encoded_GPR_##Dst());                                \
   1730                                                                                \
   1731     AssembledTest test = assemble();                                           \
   1732     test.run();                                                                \
   1733                                                                                \
   1734     ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")";                           \
   1735     reset();                                                                   \
   1736   } while (0)
   1737 
   1738   TestImpl(r1);
   1739   TestImpl(r2);
   1740   TestImpl(r3);
   1741   TestImpl(r4);
   1742   TestImpl(r5);
   1743   TestImpl(r6);
   1744   TestImpl(r7);
   1745   TestImpl(r8);
   1746   TestImpl(r10);
   1747   TestImpl(r11);
   1748   TestImpl(r12);
   1749   TestImpl(r13);
   1750   TestImpl(r14);
   1751   TestImpl(r15);
   1752 
   1753 #undef TestImpl
   1754 }
   1755 
   1756 TEST_F(AssemblerX8664Test, Bt) {
   1757 #define TestImpl(Dst, Value0, Src, Value1)                                     \
   1758   do {                                                                         \
   1759     static constexpr char TestString[] =                                       \
   1760         "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")";                      \
   1761     static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0;   \
   1762                                                                                \
   1763     __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value0));               \
   1764     __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value1));               \
   1765     __ bt(Encoded_GPR_##Dst(), Encoded_GPR_##Src());                           \
   1766     __ setcc(Cond::Br_b, ByteRegister::Encoded_8_Reg_al);                      \
   1767     __ And(IceType_i32, Encoded_GPR_eax(), Immediate(0xFFu));                  \
   1768                                                                                \
   1769     AssembledTest test = assemble();                                           \
   1770     test.run();                                                                \
   1771                                                                                \
   1772     ASSERT_EQ(Expected, test.eax()) << TestString;                             \
   1773     reset();                                                                   \
   1774   } while (0)
   1775 
   1776   TestImpl(r1, 0x08000000, r2, 27u);
   1777   TestImpl(r2, 0x08000000, r3, 23u);
   1778   TestImpl(r3, 0x00000000, r4, 1u);
   1779   TestImpl(r4, 0x08000300, r5, 9u);
   1780   TestImpl(r5, 0x08000300, r6, 10u);
   1781   TestImpl(r6, 0x7FFFEFFF, r7, 13u);
   1782   TestImpl(r7, 0x08000000, r8, 27u);
   1783   TestImpl(r8, 0x08000000, r10, 23u);
   1784   TestImpl(r10, 0x00000000, r11, 1u);
   1785   TestImpl(r11, 0x08000300, r12, 9u);
   1786   TestImpl(r12, 0x08000300, r13, 10u);
   1787   TestImpl(r13, 0x7FFFEFFF, r14, 13u);
   1788   TestImpl(r14, 0x08000000, r15, 27u);
   1789   TestImpl(r15, 0x08000000, r1, 23u);
   1790 
   1791 #undef TestImpl
   1792 }
   1793 
   1794 template <uint32_t Value, uint32_t Bits> class BitScanHelper {
   1795   BitScanHelper() = delete;
   1796 
   1797 public:
   1798   static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32");
   1799   using ValueType =
   1800       typename std::conditional<Bits == 16, uint16_t, uint32_t>::type;
   1801 
   1802 private:
   1803   static constexpr ValueType BitIndex(bool Forward, ValueType Index) {
   1804     return (Value == 0)
   1805                ? BitScanHelper<Value, Bits>::NoBitSet
   1806                : (Value & (1u << Index)
   1807                       ? Index
   1808                       : BitIndex(Forward, (Forward ? Index + 1 : Index - 1)));
   1809   }
   1810 
   1811 public:
   1812   static constexpr ValueType NoBitSet = static_cast<ValueType>(-1);
   1813   static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0);
   1814   static constexpr ValueType bsr =
   1815       BitIndex(/*Forward*/ false, /*Index=*/Bits - 1);
   1816 };
   1817 
   1818 TEST_F(AssemblerX8664Test, BitScanOperations) {
   1819 #define TestImplRegReg(Inst, Dst, Src, Value1, Size)                           \
   1820   do {                                                                         \
   1821     static constexpr char TestString[] =                                       \
   1822         "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")";             \
   1823     static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst;    \
   1824     const uint32_t ZeroFlag = allocateDword();                                 \
   1825     __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1));           \
   1826     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());        \
   1827     __ setcc(Cond::Br_e, dwordAddress(ZeroFlag));                              \
   1828                                                                                \
   1829     AssembledTest test = assemble();                                           \
   1830     test.setDwordTo(ZeroFlag, 0u);                                             \
   1831     test.run();                                                                \
   1832                                                                                \
   1833     ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet),             \
   1834               test.contentsOfDword(ZeroFlag))                                  \
   1835         << TestString;                                                         \
   1836     if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) {                 \
   1837       ASSERT_EQ(Expected, test.Dst()) << TestString;                           \
   1838     }                                                                          \
   1839     reset();                                                                   \
   1840   } while (0)
   1841 
   1842 #define TestImplRegAddr(Inst, Dst, Value1, Size)                               \
   1843   do {                                                                         \
   1844     static constexpr char TestString[] =                                       \
   1845         "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")";                 \
   1846     static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst;    \
   1847     const uint32_t T0 = allocateDword();                                       \
   1848     const uint32_t ZeroFlag = allocateDword();                                 \
   1849     __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0));           \
   1850     __ setcc(Cond::Br_e, dwordAddress(ZeroFlag));                              \
   1851                                                                                \
   1852     AssembledTest test = assemble();                                           \
   1853     test.setDwordTo(T0, Value1);                                               \
   1854     test.setDwordTo(ZeroFlag, 0u);                                             \
   1855     test.run();                                                                \
   1856                                                                                \
   1857     ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet),             \
   1858               test.contentsOfDword(ZeroFlag))                                  \
   1859         << TestString;                                                         \
   1860     if (Expected != BitScanHelper<Value1, Size>::NoBitSet) {                   \
   1861       ASSERT_EQ(Expected, test.Dst()) << TestString;                           \
   1862     }                                                                          \
   1863     reset();                                                                   \
   1864   } while (0)
   1865 
   1866 #define TestImplSize(Dst, Src, Value1, Size)                                   \
   1867   do {                                                                         \
   1868     TestImplRegReg(bsf, Dst, Src, Value1, Size);                               \
   1869     TestImplRegAddr(bsf, Dst, Value1, Size);                                   \
   1870     TestImplRegReg(bsr, Dst, Src, Value1, Size);                               \
   1871     TestImplRegAddr(bsf, Dst, Value1, Size);                                   \
   1872   } while (0)
   1873 
   1874 #define TestImplValue(Dst, Src, Value1)                                        \
   1875   do {                                                                         \
   1876     TestImplSize(Dst, Src, Value1, 16);                                        \
   1877     TestImplSize(Dst, Src, Value1, 32);                                        \
   1878   } while (0)
   1879 
   1880 #define TestImpl(Dst, Src)                                                     \
   1881   do {                                                                         \
   1882     TestImplValue(Dst, Src, 0x80000001);                                       \
   1883     TestImplValue(Dst, Src, 0x00000000);                                       \
   1884     TestImplValue(Dst, Src, 0x80001000);                                       \
   1885     TestImplValue(Dst, Src, 0x00FFFF00);                                       \
   1886   } while (0)
   1887 
   1888   TestImpl(r1, r2);
   1889   TestImpl(r2, r3);
   1890   TestImpl(r3, r4);
   1891   TestImpl(r4, r5);
   1892   TestImpl(r5, r6);
   1893   TestImpl(r6, r7);
   1894   TestImpl(r7, r8);
   1895   TestImpl(r8, r10);
   1896   TestImpl(r10, r11);
   1897   TestImpl(r11, r12);
   1898   TestImpl(r12, r13);
   1899   TestImpl(r13, r14);
   1900   TestImpl(r14, r15);
   1901   TestImpl(r15, r1);
   1902 
   1903 #undef TestImpl
   1904 #undef TestImplValue
   1905 #undef TestImplSize
   1906 #undef TestImplRegAddr
   1907 #undef TestImplRegReg
   1908 }
   1909 
   1910 } // end of anonymous namespace
   1911 } // end of namespace Test
   1912 } // end of namespace X8664
   1913 } // end of namespace Ice
   1914