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