Home | History | Annotate | Download | only in AssemblerX8632
      1 //===- subzero/unittest/AssemblerX8632/DataMov.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(AssemblerX8632Test, MovRegImm) {
     17   constexpr uint32_t ExpectedEax = 0x000000FFul;
     18   constexpr uint32_t ExpectedEbx = 0x0000FF00ul;
     19   constexpr uint32_t ExpectedEcx = 0x00FF0000ul;
     20   constexpr uint32_t ExpectedEdx = 0xFF000000ul;
     21   constexpr uint32_t ExpectedEdi = 0x6AAA0006ul;
     22   constexpr uint32_t ExpectedEsi = 0x6000AAA6ul;
     23 
     24   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedEax));
     25   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedEbx));
     26   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedEcx));
     27   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedEdx));
     28   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedEdi));
     29   __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedEsi));
     30 
     31   AssembledTest test = assemble();
     32   test.run();
     33   EXPECT_EQ(ExpectedEax, test.eax());
     34   EXPECT_EQ(ExpectedEbx, test.ebx());
     35   EXPECT_EQ(ExpectedEcx, test.ecx());
     36   EXPECT_EQ(ExpectedEdx, test.edx());
     37   EXPECT_EQ(ExpectedEdi, test.edi());
     38   EXPECT_EQ(ExpectedEsi, test.esi());
     39 }
     40 
     41 TEST_F(AssemblerX8632Test, MovMemImm) {
     42   const uint32_t T0 = allocateDword();
     43   constexpr uint32_t ExpectedT0 = 0x00111100ul;
     44   const uint32_t T1 = allocateDword();
     45   constexpr uint32_t ExpectedT1 = 0x00222200ul;
     46   const uint32_t T2 = allocateDword();
     47   constexpr uint32_t ExpectedT2 = 0x03333000ul;
     48   const uint32_t T3 = allocateDword();
     49   constexpr uint32_t ExpectedT3 = 0x00444400ul;
     50 
     51   __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
     52   __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1));
     53   __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2));
     54   __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
     55 
     56   AssembledTest test = assemble();
     57   test.run();
     58   EXPECT_EQ(0ul, test.eax());
     59   EXPECT_EQ(0ul, test.ebx());
     60   EXPECT_EQ(0ul, test.ecx());
     61   EXPECT_EQ(0ul, test.edx());
     62   EXPECT_EQ(0ul, test.edi());
     63   EXPECT_EQ(0ul, test.esi());
     64   EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
     65   EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1));
     66   EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2));
     67   EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
     68 }
     69 
     70 TEST_F(AssemblerX8632Test, MovMemReg) {
     71   const uint32_t T0 = allocateDword();
     72   constexpr uint32_t ExpectedT0 = 0x00111100ul;
     73   const uint32_t T1 = allocateDword();
     74   constexpr uint32_t ExpectedT1 = 0x00222200ul;
     75   const uint32_t T2 = allocateDword();
     76   constexpr uint32_t ExpectedT2 = 0x00333300ul;
     77   const uint32_t T3 = allocateDword();
     78   constexpr uint32_t ExpectedT3 = 0x00444400ul;
     79   const uint32_t T4 = allocateDword();
     80   constexpr uint32_t ExpectedT4 = 0x00555500ul;
     81   const uint32_t T5 = allocateDword();
     82   constexpr uint32_t ExpectedT5 = 0x00666600ul;
     83 
     84   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedT0));
     85   __ mov(IceType_i32, dwordAddress(T0), GPRRegister::Encoded_Reg_eax);
     86   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedT1));
     87   __ mov(IceType_i32, dwordAddress(T1), GPRRegister::Encoded_Reg_ebx);
     88   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedT2));
     89   __ mov(IceType_i32, dwordAddress(T2), GPRRegister::Encoded_Reg_ecx);
     90   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedT3));
     91   __ mov(IceType_i32, dwordAddress(T3), GPRRegister::Encoded_Reg_edx);
     92   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedT4));
     93   __ mov(IceType_i32, dwordAddress(T4), GPRRegister::Encoded_Reg_edi);
     94   __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedT5));
     95   __ mov(IceType_i32, dwordAddress(T5), GPRRegister::Encoded_Reg_esi);
     96 
     97   AssembledTest test = assemble();
     98   test.run();
     99   EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
    100   EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1));
    101   EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2));
    102   EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
    103   EXPECT_EQ(ExpectedT4, test.contentsOfDword(T4));
    104   EXPECT_EQ(ExpectedT5, test.contentsOfDword(T5));
    105 }
    106 
    107 TEST_F(AssemblerX8632Test, MovRegReg) {
    108   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x20));
    109   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx,
    110          GPRRegister::Encoded_Reg_eax);
    111   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx,
    112          GPRRegister::Encoded_Reg_ebx);
    113   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx,
    114          GPRRegister::Encoded_Reg_ecx);
    115   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi,
    116          GPRRegister::Encoded_Reg_edx);
    117   __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi,
    118          GPRRegister::Encoded_Reg_edi);
    119 
    120   __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x55000000ul));
    121   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax,
    122          GPRRegister::Encoded_Reg_esi);
    123 
    124   AssembledTest test = assemble();
    125   test.run();
    126   EXPECT_EQ(0x55000000ul, test.eax());
    127   EXPECT_EQ(0x20ul, test.ebx());
    128   EXPECT_EQ(0x20ul, test.ecx());
    129   EXPECT_EQ(0x20ul, test.edx());
    130   EXPECT_EQ(0x20ul, test.edi());
    131   EXPECT_EQ(0x55000000ul, test.esi());
    132 }
    133 
    134 TEST_F(AssemblerX8632Test, MovRegMem) {
    135   const uint32_t T0 = allocateDword();
    136   constexpr uint32_t ExpectedT0 = 0x00111100ul;
    137   const uint32_t T1 = allocateDword();
    138   constexpr uint32_t ExpectedT1 = 0x00222200ul;
    139   const uint32_t T2 = allocateDword();
    140   constexpr uint32_t ExpectedT2 = 0x00333300ul;
    141   const uint32_t T3 = allocateDword();
    142   constexpr uint32_t ExpectedT3 = 0x00444400ul;
    143   const uint32_t T4 = allocateDword();
    144   constexpr uint32_t ExpectedT4 = 0x00555500ul;
    145   const uint32_t T5 = allocateDword();
    146   constexpr uint32_t ExpectedT5 = 0x00666600ul;
    147 
    148   __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
    149   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, dwordAddress(T0));
    150 
    151   __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1));
    152   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, dwordAddress(T1));
    153 
    154   __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2));
    155   __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, dwordAddress(T2));
    156 
    157   __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
    158   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, dwordAddress(T3));
    159 
    160   __ mov(IceType_i32, dwordAddress(T4), Immediate(ExpectedT4));
    161   __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, dwordAddress(T4));
    162 
    163   __ mov(IceType_i32, dwordAddress(T5), Immediate(ExpectedT5));
    164   __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, dwordAddress(T5));
    165 
    166   AssembledTest test = assemble();
    167   test.run();
    168   EXPECT_EQ(ExpectedT0, test.eax());
    169   EXPECT_EQ(ExpectedT1, test.ebx());
    170   EXPECT_EQ(ExpectedT2, test.ecx());
    171   EXPECT_EQ(ExpectedT3, test.edx());
    172   EXPECT_EQ(ExpectedT4, test.edi());
    173   EXPECT_EQ(ExpectedT5, test.esi());
    174 }
    175 
    176 TEST_F(AssemblerX8632Test, Movzx) {
    177 #define TestMovzx8bitWithRegDest(Src, Dst, Imm)                                \
    178   do {                                                                         \
    179     static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate");    \
    180     __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm));        \
    181     __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst,                       \
    182              GPRRegister::Encoded_Reg_##Src);                                  \
    183     AssembledTest test = assemble();                                           \
    184     test.run();                                                                \
    185     ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")";            \
    186     reset();                                                                   \
    187   } while (0)
    188 
    189 #define TestMovzx16bitWithRegDest(Src, Dst, Imm)                               \
    190   do {                                                                         \
    191     static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate");  \
    192     __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm));       \
    193     __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst,                      \
    194              GPRRegister::Encoded_Reg_##Src);                                  \
    195     AssembledTest test = assemble();                                           \
    196     test.run();                                                                \
    197     ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")";            \
    198     reset();                                                                   \
    199   } while (0)
    200 
    201 #define TestMovzx8bitWithAddrSrc(Dst, Imm)                                     \
    202   do {                                                                         \
    203     static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate");    \
    204     const uint32_t T0 = allocateDword();                                       \
    205     const uint32_t V0 = Imm;                                                   \
    206     __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0));    \
    207     AssembledTest test = assemble();                                           \
    208     test.setDwordTo(T0, V0);                                                   \
    209     test.run();                                                                \
    210     ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")";                \
    211     reset();                                                                   \
    212   } while (0)
    213 
    214 #define TestMovzx16bitWithAddrSrc(Dst, Imm)                                    \
    215   do {                                                                         \
    216     static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate");  \
    217     const uint32_t T0 = allocateDword();                                       \
    218     const uint32_t V0 = Imm;                                                   \
    219     __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0));   \
    220     AssembledTest test = assemble();                                           \
    221     test.setDwordTo(T0, V0);                                                   \
    222     test.run();                                                                \
    223     ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")";                \
    224     reset();                                                                   \
    225   } while (0)
    226 
    227 #define TestMovzx(Dst)                                                         \
    228   do {                                                                         \
    229     TestMovzx8bitWithRegDest(eax, Dst, 0x81u);                                 \
    230     TestMovzx8bitWithRegDest(ebx, Dst, 0x82u);                                 \
    231     TestMovzx8bitWithRegDest(ecx, Dst, 0x83u);                                 \
    232     TestMovzx8bitWithRegDest(edx, Dst, 0x84u);                                 \
    233     /* esi is encoded as dh */                                                 \
    234     TestMovzx8bitWithRegDest(esi, Dst, 0x85u);                                 \
    235     /* edi is encoded as bh */                                                 \
    236     TestMovzx8bitWithRegDest(edi, Dst, 0x86u);                                 \
    237     /* ebp is encoded as ch */                                                 \
    238     TestMovzx8bitWithRegDest(ebp, Dst, 0x87u);                                 \
    239     /* esp is encoded as ah */                                                 \
    240     TestMovzx8bitWithRegDest(esp, Dst, 0x88u);                                 \
    241     TestMovzx8bitWithAddrSrc(Dst, 0x8Fu);                                      \
    242                                                                                \
    243     TestMovzx16bitWithRegDest(eax, Dst, 0x8118u);                              \
    244     TestMovzx16bitWithRegDest(ebx, Dst, 0x8228u);                              \
    245     TestMovzx16bitWithRegDest(ecx, Dst, 0x8338u);                              \
    246     TestMovzx16bitWithRegDest(edx, Dst, 0x8448u);                              \
    247     TestMovzx16bitWithAddrSrc(Dst, 0x8FF8u);                                   \
    248   } while (0)
    249 
    250   TestMovzx(eax);
    251   TestMovzx(ebx);
    252   TestMovzx(ecx);
    253   TestMovzx(edx);
    254   TestMovzx(esi);
    255   TestMovzx(edi);
    256 
    257 #undef TestMovzx
    258 #undef TestMovzx16bitWithAddrDest
    259 #undef TestMovzx8bitWithAddrDest
    260 #undef TestMovzx16bitWithRegDest
    261 #undef TestMovzx8bitWithRegDest
    262 }
    263 
    264 TEST_F(AssemblerX8632Test, Movsx) {
    265 #define TestMovsx8bitWithRegDest(Src, Dst, Imm)                                \
    266   do {                                                                         \
    267     static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate");    \
    268     __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm));        \
    269     __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst,                       \
    270              GPRRegister::Encoded_Reg_##Src);                                  \
    271     AssembledTest test = assemble();                                           \
    272     test.run();                                                                \
    273     ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst())                                \
    274         << "(" #Src ", " #Dst ", " #Imm ")";                                   \
    275     reset();                                                                   \
    276   } while (0)
    277 
    278 #define TestMovsx16bitWithRegDest(Src, Dst, Imm)                               \
    279   do {                                                                         \
    280     static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate");  \
    281     __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm));       \
    282     __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst,                      \
    283              GPRRegister::Encoded_Reg_##Src);                                  \
    284     AssembledTest test = assemble();                                           \
    285     test.run();                                                                \
    286     ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst())                                \
    287         << "(" #Src ", " #Dst ", " #Imm ")";                                   \
    288     reset();                                                                   \
    289   } while (0)
    290 
    291 #define TestMovsx8bitWithAddrSrc(Dst, Imm)                                     \
    292   do {                                                                         \
    293     static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate");    \
    294     const uint32_t T0 = allocateDword();                                       \
    295     const uint32_t V0 = Imm;                                                   \
    296     __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0));    \
    297     AssembledTest test = assemble();                                           \
    298     test.setDwordTo(T0, V0);                                                   \
    299     test.run();                                                                \
    300     ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst())                                \
    301         << "(Addr, " #Dst ", " #Imm ")";                                       \
    302     reset();                                                                   \
    303   } while (0)
    304 
    305 #define TestMovsx16bitWithAddrSrc(Dst, Imm)                                    \
    306   do {                                                                         \
    307     static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate");  \
    308     const uint32_t T0 = allocateDword();                                       \
    309     const uint32_t V0 = Imm;                                                   \
    310     __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0));   \
    311     AssembledTest test = assemble();                                           \
    312     test.setDwordTo(T0, V0);                                                   \
    313     test.run();                                                                \
    314     ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst())                                \
    315         << "(Addr, " #Dst ", " #Imm ")";                                       \
    316     reset();                                                                   \
    317   } while (0)
    318 
    319 #define TestMovsx(Dst)                                                         \
    320   do {                                                                         \
    321     TestMovsx8bitWithRegDest(eax, Dst, 0x81u);                                 \
    322     TestMovsx8bitWithRegDest(ebx, Dst, 0x82u);                                 \
    323     TestMovsx8bitWithRegDest(ecx, Dst, 0x83u);                                 \
    324     TestMovsx8bitWithRegDest(edx, Dst, 0x84u);                                 \
    325     /* esi is encoded as dh */                                                 \
    326     TestMovsx8bitWithRegDest(esi, Dst, 0x85u);                                 \
    327     /* edi is encoded as bh */                                                 \
    328     TestMovsx8bitWithRegDest(edi, Dst, 0x86u);                                 \
    329     /* ebp is encoded as ch */                                                 \
    330     TestMovsx8bitWithRegDest(ebp, Dst, 0x87u);                                 \
    331     /* esp is encoded as ah */                                                 \
    332     TestMovsx8bitWithRegDest(esp, Dst, 0x88u);                                 \
    333     TestMovsx8bitWithAddrSrc(Dst, 0x8Fu);                                      \
    334                                                                                \
    335     TestMovsx16bitWithRegDest(eax, Dst, 0x8118u);                              \
    336     TestMovsx16bitWithRegDest(ebx, Dst, 0x8228u);                              \
    337     TestMovsx16bitWithRegDest(ecx, Dst, 0x8338u);                              \
    338     TestMovsx16bitWithRegDest(edx, Dst, 0x8448u);                              \
    339     TestMovsx16bitWithAddrSrc(Dst, 0x8FF8u);                                   \
    340   } while (0)
    341 
    342   TestMovsx(eax);
    343   TestMovsx(ebx);
    344   TestMovsx(ecx);
    345   TestMovsx(edx);
    346   TestMovsx(esi);
    347   TestMovsx(edi);
    348 
    349 #undef TestMovsx
    350 #undef TestMovsx16bitWithAddrDest
    351 #undef TestMovsx8bitWithAddrDest
    352 #undef TestMovsx16bitWithRegDest
    353 #undef TestMovsx8bitWithRegDest
    354 }
    355 
    356 TEST_F(AssemblerX8632LowLevelTest, RepMovsb) {
    357   __ rep_movsb();
    358 
    359   static constexpr uint32_t ByteCount = 2;
    360   static constexpr uint8_t Prefix = 0xF3;
    361   static constexpr uint8_t Opcode = 0xA4;
    362 
    363   ASSERT_EQ(ByteCount, codeBytesSize());
    364   verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode);
    365 }
    366 
    367 TEST_F(AssemblerX8632Test, MovssXmmAddr) {
    368 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value)                   \
    369   do {                                                                         \
    370     static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \
    371                   "Invalid fp length #FloatLength");                           \
    372     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    373                                                                                \
    374     static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")";       \
    375     static constexpr bool IsDouble = std::is_same<Type, double>::value;        \
    376     const uint32_t T0 = allocateQword();                                       \
    377     const Type V0 = Value;                                                     \
    378                                                                                \
    379     __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm,           \
    380              dwordAddress(T0));                                                \
    381                                                                                \
    382     AssembledTest test = assemble();                                           \
    383     if (IsDouble) {                                                            \
    384       test.setQwordTo(T0, static_cast<double>(V0));                            \
    385     } else {                                                                   \
    386       test.setDwordTo(T0, static_cast<float>(V0));                             \
    387     }                                                                          \
    388     test.run();                                                                \
    389     ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is "    \
    390                                               << Value;                        \
    391     reset();                                                                   \
    392   } while (0)
    393 
    394 #define TestMovssXmmAddr(FloatLength)                                          \
    395   do {                                                                         \
    396     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    397     for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \
    398       TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value);                   \
    399       TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value);                   \
    400       TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value);                   \
    401       TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value);                   \
    402       TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value);                   \
    403       TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value);                   \
    404       TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value);                   \
    405       TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value);                   \
    406     }                                                                          \
    407   } while (0)
    408 
    409   TestMovssXmmAddr(32);
    410   TestMovssXmmAddr(64);
    411 
    412 #undef TestMovssXmmAddr
    413 #undef TestMovssXmmAddrType
    414 }
    415 
    416 TEST_F(AssemblerX8632Test, MovssAddrXmm) {
    417 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value)                   \
    418   do {                                                                         \
    419     static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \
    420                   "Invalid fp length #FloatLength");                           \
    421     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    422                                                                                \
    423     static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")";       \
    424     static constexpr bool IsDouble = std::is_same<Type, double>::value;        \
    425     const uint32_t T0 = allocateQword();                                       \
    426     const Type V0 = Value;                                                     \
    427     const uint32_t T1 = allocateQword();                                       \
    428     static_assert(std::numeric_limits<Type>::has_quiet_NaN,                    \
    429                   "f" #FloatLength " does not have quiet nan.");               \
    430     const Type V1 = std::numeric_limits<Type>::quiet_NaN();                    \
    431                                                                                \
    432     __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm,           \
    433              dwordAddress(T0));                                                \
    434                                                                                \
    435     AssembledTest test = assemble();                                           \
    436     if (IsDouble) {                                                            \
    437       test.setQwordTo(T0, static_cast<double>(V0));                            \
    438       test.setQwordTo(T1, static_cast<double>(V1));                            \
    439     } else {                                                                   \
    440       test.setDwordTo(T0, static_cast<float>(V0));                             \
    441       test.setDwordTo(T1, static_cast<float>(V1));                             \
    442     }                                                                          \
    443     test.run();                                                                \
    444     ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is "    \
    445                                               << Value;                        \
    446     reset();                                                                   \
    447   } while (0)
    448 
    449 #define TestMovssAddrXmm(FloatLength)                                          \
    450   do {                                                                         \
    451     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    452     for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \
    453       TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value);                   \
    454       TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value);                   \
    455       TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value);                   \
    456       TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value);                   \
    457       TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value);                   \
    458       TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value);                   \
    459       TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value);                   \
    460       TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value);                   \
    461     }                                                                          \
    462   } while (0)
    463 
    464   TestMovssAddrXmm(32);
    465   TestMovssAddrXmm(64);
    466 
    467 #undef TestMovssAddrXmm
    468 #undef TestMovssAddrXmmType
    469 }
    470 
    471 TEST_F(AssemblerX8632Test, MovssXmmXmm) {
    472 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value)               \
    473   do {                                                                         \
    474     static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \
    475                   "Invalid fp length #FloatLength");                           \
    476     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    477                                                                                \
    478     static constexpr char TestString[] =                                       \
    479         "(" #FloatLength ", " #Src ", " #Dst ")";                              \
    480     static constexpr bool IsDouble = std::is_same<Type, double>::value;        \
    481     const uint32_t T0 = allocateQword();                                       \
    482     const Type V0 = Value;                                                     \
    483     const uint32_t T1 = allocateQword();                                       \
    484     static_assert(std::numeric_limits<Type>::has_quiet_NaN,                    \
    485                   "f" #FloatLength " does not have quiet nan.");               \
    486     const Type V1 = std::numeric_limits<Type>::quiet_NaN();                    \
    487                                                                                \
    488     __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Src,           \
    489              dwordAddress(T0));                                                \
    490     __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst,           \
    491              dwordAddress(T1));                                                \
    492     __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst,           \
    493              XmmRegister::Encoded_Reg_##Src);                                  \
    494                                                                                \
    495     AssembledTest test = assemble();                                           \
    496     if (IsDouble) {                                                            \
    497       test.setQwordTo(T0, static_cast<double>(V0));                            \
    498       test.setQwordTo(T1, static_cast<double>(V1));                            \
    499     } else {                                                                   \
    500       test.setDwordTo(T0, static_cast<float>(V0));                             \
    501       test.setDwordTo(T1, static_cast<float>(V1));                             \
    502     }                                                                          \
    503     test.run();                                                                \
    504     ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is "    \
    505                                               << Value;                        \
    506     reset();                                                                   \
    507   } while (0)
    508 
    509 #define TestMovssXmmXmm(FloatLength)                                           \
    510   do {                                                                         \
    511     using Type = std::conditional<FloatLength == 32, float, double>::type;     \
    512     for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \
    513       TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value);              \
    514       TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value);              \
    515       TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value);              \
    516       TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value);              \
    517       TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value);              \
    518       TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value);              \
    519       TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value);              \
    520       TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm0, Value);              \
    521     }                                                                          \
    522   } while (0)
    523 
    524   TestMovssXmmXmm(32);
    525   TestMovssXmmXmm(64);
    526 
    527 #undef TestMovssXmmXmm
    528 #undef TestMovssXmmXmmType
    529 }
    530 
    531 TEST_F(AssemblerX8632Test, MovdToXmm) {
    532 #define TestMovdXmmReg(Src, Dst, Value)                                        \
    533   do {                                                                         \
    534     assert(((Value)&0xFFFFFFFF) == (Value));                                   \
    535     static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \
    536     const uint32_t T0 = allocateQword();                                       \
    537     const uint64_t V0 = 0xFFFFFFFF00000000ull;                                 \
    538                                                                                \
    539     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src, Immediate(Value));     \
    540     __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));   \
    541     __ movd(IceType_i32, XmmRegister::Encoded_Reg_##Dst,                       \
    542             GPRRegister::Encoded_Reg_##Src);                                   \
    543                                                                                \
    544     AssembledTest test = assemble();                                           \
    545                                                                                \
    546     test.setQwordTo(T0, V0);                                                   \
    547     test.run();                                                                \
    548                                                                                \
    549     ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \
    550                                            << Value;                           \
    551     reset();                                                                   \
    552   } while (0)
    553 
    554 #define TestMovdXmmAddr(Dst, Value)                                            \
    555   do {                                                                         \
    556     assert(((Value)&0xFFFFFFFF) == (Value));                                   \
    557     static constexpr char TestString[] = "(" #Dst ", Addr)";                   \
    558     const uint32_t T0 = allocateQword();                                       \
    559     const uint32_t V0 = Value;                                                 \
    560     const uint32_t T1 = allocateQword();                                       \
    561     const uint64_t V1 = 0xFFFFFFFF00000000ull;                                 \
    562                                                                                \
    563     __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));   \
    564     __ movd(IceType_i32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));    \
    565                                                                                \
    566     AssembledTest test = assemble();                                           \
    567                                                                                \
    568     test.setDwordTo(T0, V0);                                                   \
    569     test.setQwordTo(T1, V1);                                                   \
    570     test.run();                                                                \
    571                                                                                \
    572     ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \
    573                                            << Value;                           \
    574     reset();                                                                   \
    575   } while (0)
    576 
    577 #define TestMovd(Dst)                                                          \
    578   do {                                                                         \
    579     for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {   \
    580       TestMovdXmmReg(eax, Dst, Value);                                         \
    581       TestMovdXmmReg(ebx, Dst, Value);                                         \
    582       TestMovdXmmReg(ecx, Dst, Value);                                         \
    583       TestMovdXmmReg(edx, Dst, Value);                                         \
    584       TestMovdXmmReg(esi, Dst, Value);                                         \
    585       TestMovdXmmReg(edi, Dst, Value);                                         \
    586       TestMovdXmmAddr(Dst, Value);                                             \
    587     }                                                                          \
    588   } while (0)
    589 
    590   TestMovd(xmm0);
    591   TestMovd(xmm1);
    592   TestMovd(xmm2);
    593   TestMovd(xmm3);
    594   TestMovd(xmm4);
    595   TestMovd(xmm5);
    596   TestMovd(xmm6);
    597   TestMovd(xmm7);
    598 
    599 #undef TestMovdXmmAddr
    600 #undef TestMovdXmmReg
    601 #undef TestMovd
    602 }
    603 
    604 TEST_F(AssemblerX8632Test, MovdFromXmm) {
    605 #define TestMovdRegXmm(Src, Dst, Value)                                        \
    606   do {                                                                         \
    607     assert(((Value)&0xFFFFFFFF) == (Value));                                   \
    608     static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \
    609     const uint32_t T0 = allocateDword();                                       \
    610     const uint32_t V0 = Value;                                                 \
    611                                                                                \
    612     __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));   \
    613     __ movd(IceType_i32, GPRRegister::Encoded_Reg_##Dst,                       \
    614             XmmRegister::Encoded_Reg_##Src);                                   \
    615                                                                                \
    616     AssembledTest test = assemble();                                           \
    617                                                                                \
    618     test.setDwordTo(T0, V0);                                                   \
    619     test.run();                                                                \
    620                                                                                \
    621     ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is "   \
    622                                                << Value;                       \
    623     reset();                                                                   \
    624   } while (0)
    625 
    626 #define TestMovdAddrXmm(Src, Value)                                            \
    627   do {                                                                         \
    628     assert(((Value)&0xFFFFFFFF) == (Value));                                   \
    629     static constexpr char TestString[] = "(" #Src ", Addr)";                   \
    630     const uint32_t T0 = allocateDword();                                       \
    631     const uint32_t V0 = Value;                                                 \
    632     const uint32_t T1 = allocateDword();                                       \
    633     const uint32_t V1 = ~(Value);                                              \
    634                                                                                \
    635     __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));   \
    636     __ movd(IceType_i32, dwordAddress(T1), XmmRegister::Encoded_Reg_##Src);    \
    637                                                                                \
    638     AssembledTest test = assemble();                                           \
    639                                                                                \
    640     test.setDwordTo(T0, V0);                                                   \
    641     test.setDwordTo(T1, V1);                                                   \
    642     test.run();                                                                \
    643                                                                                \
    644     ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is "   \
    645                                                << Value;                       \
    646     reset();                                                                   \
    647   } while (0)
    648 
    649 #define TestMovd(Src)                                                          \
    650   do {                                                                         \
    651     for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {   \
    652       TestMovdRegXmm(Src, eax, Value);                                         \
    653       TestMovdRegXmm(Src, ebx, Value);                                         \
    654       TestMovdRegXmm(Src, ecx, Value);                                         \
    655       TestMovdRegXmm(Src, edx, Value);                                         \
    656       TestMovdRegXmm(Src, esi, Value);                                         \
    657       TestMovdRegXmm(Src, edi, Value);                                         \
    658       TestMovdAddrXmm(Src, Value);                                             \
    659     }                                                                          \
    660   } while (0)
    661 
    662   TestMovd(xmm0);
    663   TestMovd(xmm1);
    664   TestMovd(xmm2);
    665   TestMovd(xmm3);
    666   TestMovd(xmm4);
    667   TestMovd(xmm5);
    668   TestMovd(xmm6);
    669   TestMovd(xmm7);
    670 
    671 #undef TestMovdAddrXmm
    672 #undef TestMovdRegXmm
    673 #undef TestMovd
    674 }
    675 
    676 TEST_F(AssemblerX8632Test, MovqXmmAddr) {
    677 #define TestMovd(Dst, Value)                                                   \
    678   do {                                                                         \
    679     static constexpr char TestString[] = "(" #Dst ", Addr)";                   \
    680     const uint32_t T0 = allocateQword();                                       \
    681     const uint64_t V0 = Value;                                                 \
    682     const uint32_t T1 = allocateQword();                                       \
    683     const uint64_t V1 = ~(Value);                                              \
    684                                                                                \
    685     __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));   \
    686     __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));                 \
    687                                                                                \
    688     AssembledTest test = assemble();                                           \
    689                                                                                \
    690     test.setQwordTo(T0, V0);                                                   \
    691     test.setQwordTo(T1, V1);                                                   \
    692     test.run();                                                                \
    693                                                                                \
    694     ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \
    695                                            << Value;                           \
    696     reset();                                                                   \
    697   } while (0)
    698 
    699   for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
    700     TestMovd(xmm0, Value);
    701     TestMovd(xmm1, Value);
    702     TestMovd(xmm2, Value);
    703     TestMovd(xmm3, Value);
    704     TestMovd(xmm4, Value);
    705     TestMovd(xmm5, Value);
    706     TestMovd(xmm6, Value);
    707     TestMovd(xmm7, Value);
    708   }
    709 
    710 #undef TestMovd
    711 }
    712 
    713 TEST_F(AssemblerX8632Test, MovqAddrXmm) {
    714 #define TestMovd(Dst, Value)                                                   \
    715   do {                                                                         \
    716     static constexpr char TestString[] = "(" #Dst ", Addr)";                   \
    717     const uint32_t T0 = allocateQword();                                       \
    718     const uint64_t V0 = Value;                                                 \
    719     const uint32_t T1 = allocateQword();                                       \
    720     const uint64_t V1 = ~(Value);                                              \
    721                                                                                \
    722     __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));                 \
    723     __ movq(dwordAddress(T1), XmmRegister::Encoded_Reg_##Dst);                 \
    724                                                                                \
    725     AssembledTest test = assemble();                                           \
    726                                                                                \
    727     test.setQwordTo(T0, V0);                                                   \
    728     test.setQwordTo(T1, V1);                                                   \
    729     test.run();                                                                \
    730                                                                                \
    731     ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \
    732                                            << Value;                           \
    733     reset();                                                                   \
    734   } while (0)
    735 
    736   for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
    737     TestMovd(xmm0, Value);
    738     TestMovd(xmm1, Value);
    739     TestMovd(xmm2, Value);
    740     TestMovd(xmm3, Value);
    741     TestMovd(xmm4, Value);
    742     TestMovd(xmm5, Value);
    743     TestMovd(xmm6, Value);
    744     TestMovd(xmm7, Value);
    745   }
    746 
    747 #undef TestMovd
    748 }
    749 
    750 TEST_F(AssemblerX8632Test, MovqXmmXmm) {
    751 #define TestMovd(Src, Dst, Value)                                              \
    752   do {                                                                         \
    753     static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \
    754     const uint32_t T0 = allocateQword();                                       \
    755     const uint64_t V0 = Value;                                                 \
    756     const uint32_t T1 = allocateQword();                                       \
    757     const uint64_t V1 = ~(Value);                                              \
    758                                                                                \
    759     __ movq(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));                 \
    760     __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));                 \
    761     __ movq(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src);   \
    762                                                                                \
    763     AssembledTest test = assemble();                                           \
    764                                                                                \
    765     test.setQwordTo(T0, V0);                                                   \
    766     test.setQwordTo(T1, V1);                                                   \
    767     test.run();                                                                \
    768                                                                                \
    769     ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \
    770                                            << Value;                           \
    771     reset();                                                                   \
    772   } while (0)
    773 
    774   for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
    775     TestMovd(xmm0, xmm1, Value);
    776     TestMovd(xmm1, xmm2, Value);
    777     TestMovd(xmm2, xmm3, Value);
    778     TestMovd(xmm3, xmm4, Value);
    779     TestMovd(xmm4, xmm5, Value);
    780     TestMovd(xmm5, xmm6, Value);
    781     TestMovd(xmm6, xmm7, Value);
    782     TestMovd(xmm7, xmm0, Value);
    783   }
    784 
    785 #undef TestMovd
    786 }
    787 
    788 TEST_F(AssemblerX8632Test, MovupsXmmAddr) {
    789 #define TestMovups(Dst)                                                        \
    790   do {                                                                         \
    791     static constexpr char TestString[] = "(" #Dst ")";                         \
    792     const uint32_t T0 = allocateDqword();                                      \
    793     const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \
    794                     std::numeric_limits<float>::infinity());                   \
    795                                                                                \
    796     __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));               \
    797                                                                                \
    798     AssembledTest test = assemble();                                           \
    799     test.setDqwordTo(T0, V0);                                                  \
    800     test.run();                                                                \
    801                                                                                \
    802     ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \
    803     reset();                                                                   \
    804   } while (0)
    805 
    806   TestMovups(xmm0);
    807   TestMovups(xmm1);
    808   TestMovups(xmm2);
    809   TestMovups(xmm3);
    810   TestMovups(xmm4);
    811   TestMovups(xmm5);
    812   TestMovups(xmm6);
    813   TestMovups(xmm7);
    814 
    815 #undef TestMovups
    816 }
    817 
    818 TEST_F(AssemblerX8632Test, MovupsAddrXmm) {
    819 #define TestMovups(Src)                                                        \
    820   do {                                                                         \
    821     static constexpr char TestString[] = "(" #Src ")";                         \
    822     const uint32_t T0 = allocateDqword();                                      \
    823     const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \
    824                     std::numeric_limits<float>::infinity());                   \
    825     const uint32_t T1 = allocateDqword();                                      \
    826     const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \
    827                                                                                \
    828     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));               \
    829     __ movups(dwordAddress(T1), XmmRegister::Encoded_Reg_##Src);               \
    830                                                                                \
    831     AssembledTest test = assemble();                                           \
    832     test.setDqwordTo(T0, V0);                                                  \
    833     test.setDqwordTo(T1, V1);                                                  \
    834     test.run();                                                                \
    835                                                                                \
    836     ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString;                    \
    837     reset();                                                                   \
    838   } while (0)
    839 
    840   TestMovups(xmm0);
    841   TestMovups(xmm1);
    842   TestMovups(xmm2);
    843   TestMovups(xmm3);
    844   TestMovups(xmm4);
    845   TestMovups(xmm5);
    846   TestMovups(xmm6);
    847   TestMovups(xmm7);
    848 
    849 #undef TestMovups
    850 }
    851 
    852 TEST_F(AssemblerX8632Test, MovupsXmmXmm) {
    853 #define TestMovups(Dst, Src)                                                   \
    854   do {                                                                         \
    855     static constexpr char TestString[] = "(" #Dst ", " #Src ")";               \
    856     const uint32_t T0 = allocateDqword();                                      \
    857     const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \
    858                     std::numeric_limits<float>::infinity());                   \
    859     const uint32_t T1 = allocateDqword();                                      \
    860     const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \
    861                                                                                \
    862     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));               \
    863     __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));               \
    864     __ movups(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \
    865                                                                                \
    866     AssembledTest test = assemble();                                           \
    867     test.setDqwordTo(T0, V0);                                                  \
    868     test.setDqwordTo(T1, V1);                                                  \
    869     test.run();                                                                \
    870                                                                                \
    871     ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \
    872     reset();                                                                   \
    873   } while (0)
    874 
    875   TestMovups(xmm0, xmm1);
    876   TestMovups(xmm1, xmm2);
    877   TestMovups(xmm2, xmm3);
    878   TestMovups(xmm3, xmm4);
    879   TestMovups(xmm4, xmm5);
    880   TestMovups(xmm5, xmm6);
    881   TestMovups(xmm6, xmm7);
    882   TestMovups(xmm7, xmm0);
    883 
    884 #undef TestMovups
    885 }
    886 
    887 TEST_F(AssemblerX8632Test, MovapsXmmXmm) {
    888 #define TestMovaps(Dst, Src)                                                   \
    889   do {                                                                         \
    890     static constexpr char TestString[] = "(" #Dst ", " #Src ")";               \
    891     const uint32_t T0 = allocateDqword();                                      \
    892     const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \
    893                     std::numeric_limits<float>::infinity());                   \
    894     const uint32_t T1 = allocateDqword();                                      \
    895     const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \
    896                                                                                \
    897     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));               \
    898     __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));               \
    899     __ movaps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \
    900                                                                                \
    901     AssembledTest test = assemble();                                           \
    902     test.setDqwordTo(T0, V0);                                                  \
    903     test.setDqwordTo(T1, V1);                                                  \
    904     test.run();                                                                \
    905                                                                                \
    906     ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \
    907     reset();                                                                   \
    908   } while (0)
    909 
    910   TestMovaps(xmm0, xmm1);
    911   TestMovaps(xmm1, xmm2);
    912   TestMovaps(xmm2, xmm3);
    913   TestMovaps(xmm3, xmm4);
    914   TestMovaps(xmm4, xmm5);
    915   TestMovaps(xmm5, xmm6);
    916   TestMovaps(xmm6, xmm7);
    917   TestMovaps(xmm7, xmm0);
    918 
    919 #undef TestMovaps
    920 }
    921 
    922 TEST_F(AssemblerX8632Test, Movhlps_Movlhps) {
    923 #define TestImplSingle(Dst, Src, Inst, Expect)                                 \
    924   do {                                                                         \
    925     static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")";    \
    926     const uint32_t T0 = allocateDqword();                                      \
    927     const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),                           \
    928                     uint64_t(0xCCCCCCCCDDDDDDDDull));                          \
    929     const uint32_t T1 = allocateDqword();                                      \
    930     const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),                           \
    931                     uint64_t(0x9999999988888888ull));                          \
    932                                                                                \
    933     __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0));               \
    934     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1));               \
    935     __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src);   \
    936                                                                                \
    937     AssembledTest test = assemble();                                           \
    938     test.setDqwordTo(T0, V0);                                                  \
    939     test.setDqwordTo(T1, V1);                                                  \
    940     test.run();                                                                \
    941                                                                                \
    942     ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString;                \
    943     reset();                                                                   \
    944   } while (0)
    945 
    946 #define TestImpl(Dst, Src)                                                     \
    947   do {                                                                         \
    948     TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull),        \
    949                                        uint64_t(0xCCCCCCCCDDDDDDDDull)));      \
    950     TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull),        \
    951                                        uint64_t(0xEEEEEEEEFFFFFFFFull)));      \
    952   } while (0)
    953 
    954   TestImpl(xmm0, xmm1);
    955   TestImpl(xmm1, xmm2);
    956   TestImpl(xmm2, xmm3);
    957   TestImpl(xmm3, xmm4);
    958   TestImpl(xmm4, xmm5);
    959   TestImpl(xmm5, xmm6);
    960   TestImpl(xmm6, xmm7);
    961   TestImpl(xmm7, xmm0);
    962 
    963 #undef TestImpl
    964 #undef TestImplSingle
    965 }
    966 
    967 TEST_F(AssemblerX8632Test, Movmsk) {
    968 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst)                     \
    969   do {                                                                         \
    970     static constexpr char TestString[] =                                       \
    971         "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")";         \
    972     const uint32_t T0 = allocateDqword();                                      \
    973     const Dqword V0 Value1;                                                    \
    974                                                                                \
    975     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));               \
    976     __ Inst(IceType_v4f32, GPRRegister::Encoded_Reg_##GPR,                     \
    977             XmmRegister::Encoded_Reg_##Src);                                   \
    978                                                                                \
    979     AssembledTest test = assemble();                                           \
    980     test.setDqwordTo(T0, V0);                                                  \
    981     test.run();                                                                \
    982                                                                                \
    983     ASSERT_EQ(Expected, test.GPR()) << TestString;                             \
    984     reset();                                                                   \
    985   } while (0)
    986 
    987 #define TestMovmsk(GPR, Src)                                                   \
    988   do {                                                                         \
    989     TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmsk);        \
    990   } while (0)
    991 
    992   TestMovmsk(eax, xmm0);
    993   TestMovmsk(ebx, xmm1);
    994   TestMovmsk(ecx, xmm2);
    995   TestMovmsk(edx, xmm3);
    996   TestMovmsk(esi, xmm4);
    997   TestMovmsk(edi, xmm5);
    998   TestMovmsk(eax, xmm6);
    999   TestMovmsk(ebx, xmm7);
   1000 
   1001 #undef TestMovmskGPRXmm
   1002 #undef TestMovmsk
   1003 }
   1004 
   1005 TEST_F(AssemblerX8632Test, Pmovsxdq) {
   1006 #define TestPmovsxdqXmmXmm(Dst, Src, Value1)                                   \
   1007   do {                                                                         \
   1008     static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")";  \
   1009     const uint32_t T0 = allocateDqword();                                      \
   1010     const Dqword V0 Value1;                                                    \
   1011     const uint32_t T1 = allocateDqword();                                      \
   1012     const Dqword V1(uint64_t(0), uint64_t(0));                                 \
   1013                                                                                \
   1014     __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0));               \
   1015     __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1));               \
   1016     __ pmovsxdq(XmmRegister::Encoded_Reg_##Dst,                                \
   1017                 XmmRegister::Encoded_Reg_##Src);                               \
   1018                                                                                \
   1019     AssembledTest test = assemble();                                           \
   1020     test.setDqwordTo(T0, V0);                                                  \
   1021     test.setDqwordTo(T1, V1);                                                  \
   1022     test.run();                                                                \
   1023                                                                                \
   1024     const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1]));           \
   1025     ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString;                     \
   1026     reset();                                                                   \
   1027   } while (0)
   1028 
   1029 #define TestPmovsxdq(Dst, Src)                                                 \
   1030   do {                                                                         \
   1031     TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull),             \
   1032                                   uint64_t(0xAAAAAAAAEEEEEEEEull)));           \
   1033     TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull),             \
   1034                                   uint64_t(0xAAAAAAAAEEEEEEEEull)));           \
   1035     TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull),             \
   1036                                   uint64_t(0xAAAAAAAAEEEEEEEEull)));           \
   1037     TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull),             \
   1038                                   uint64_t(0xAAAAAAAAEEEEEEEEull)));           \
   1039   } while (0)
   1040 
   1041   TestPmovsxdq(xmm0, xmm1);
   1042   TestPmovsxdq(xmm1, xmm2);
   1043   TestPmovsxdq(xmm2, xmm3);
   1044   TestPmovsxdq(xmm3, xmm4);
   1045   TestPmovsxdq(xmm4, xmm5);
   1046   TestPmovsxdq(xmm5, xmm6);
   1047   TestPmovsxdq(xmm6, xmm7);
   1048   TestPmovsxdq(xmm7, xmm0);
   1049 
   1050 #undef TestPmovsxdq
   1051 #undef TestPmovsxdqXmmXmm
   1052 }
   1053 
   1054 TEST_F(AssemblerX8632Test, CmovRegReg) {
   1055 #define TestCmovRegReg(C, Src0, Value0, Src1, Value1, Dest, IsTrue)            \
   1056   do {                                                                         \
   1057     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0));   \
   1058     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1));   \
   1059     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0));   \
   1060     __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0,                       \
   1061            GPRRegister::Encoded_Reg_##Src1);                                   \
   1062     __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest,        \
   1063             GPRRegister::Encoded_Reg_##Src1);                                  \
   1064                                                                                \
   1065     AssembledTest test = assemble();                                           \
   1066     test.run();                                                                \
   1067     ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest())                     \
   1068         << "(" #C ", " #Src0 ", " #Value0 ", " #Src1 ", " #Value1 ", " #Dest   \
   1069            ", " #IsTrue ")";                                                   \
   1070                                                                                \
   1071     reset();                                                                   \
   1072   } while (0)
   1073 
   1074   TestCmovRegReg(o, eax, 0x80000000u, ebx, 0x1u, ecx, 1u);
   1075   TestCmovRegReg(o, eax, 0x1u, ebx, 0x10000000u, ecx, 0u);
   1076 
   1077   TestCmovRegReg(no, ebx, 0x1u, ecx, 0x10000000u, edx, 1u);
   1078   TestCmovRegReg(no, ebx, 0x80000000u, ecx, 0x1u, edx, 0u);
   1079 
   1080   TestCmovRegReg(b, ecx, 0x1, edx, 0x80000000u, eax, 1u);
   1081   TestCmovRegReg(b, ecx, 0x80000000u, edx, 0x1u, eax, 0u);
   1082 
   1083   TestCmovRegReg(ae, edx, 0x80000000u, edi, 0x1u, ebx, 1u);
   1084   TestCmovRegReg(ae, edx, 0x1u, edi, 0x80000000u, ebx, 0u);
   1085 
   1086   TestCmovRegReg(e, edi, 0x1u, esi, 0x1u, ecx, 1u);
   1087   TestCmovRegReg(e, edi, 0x1u, esi, 0x11111u, ecx, 0u);
   1088 
   1089   TestCmovRegReg(ne, esi, 0x80000000u, eax, 0x1u, edx, 1u);
   1090   TestCmovRegReg(ne, esi, 0x1u, eax, 0x1u, edx, 0u);
   1091 
   1092   TestCmovRegReg(be, eax, 0x1u, ebx, 0x80000000u, eax, 1u);
   1093   TestCmovRegReg(be, eax, 0x80000000u, ebx, 0x1u, eax, 0u);
   1094 
   1095   TestCmovRegReg(a, ebx, 0x80000000u, ecx, 0x1u, ebx, 1u);
   1096   TestCmovRegReg(a, ebx, 0x1u, ecx, 0x80000000u, ebx, 0u);
   1097 
   1098   TestCmovRegReg(s, ecx, 0x1u, edx, 0x80000000u, ecx, 1u);
   1099   TestCmovRegReg(s, ecx, 0x80000000u, edx, 0x1u, ecx, 0u);
   1100 
   1101   TestCmovRegReg(ns, edx, 0x80000000u, edi, 0x1u, ecx, 1u);
   1102   TestCmovRegReg(ns, edx, 0x1u, edi, 0x80000000u, ecx, 0u);
   1103 
   1104   TestCmovRegReg(p, edi, 0x80000000u, esi, 0x1u, edx, 1u);
   1105   TestCmovRegReg(p, edi, 0x1u, esi, 0x80000000u, edx, 0u);
   1106 
   1107   TestCmovRegReg(np, esi, 0x1u, edi, 0x80000000u, eax, 1u);
   1108   TestCmovRegReg(np, esi, 0x80000000u, edi, 0x1u, eax, 0u);
   1109 
   1110   TestCmovRegReg(l, edi, 0x80000000u, eax, 0x1u, ebx, 1u);
   1111   TestCmovRegReg(l, edi, 0x1u, eax, 0x80000000u, ebx, 0u);
   1112 
   1113   TestCmovRegReg(ge, eax, 0x1u, ebx, 0x80000000u, ecx, 1u);
   1114   TestCmovRegReg(ge, eax, 0x80000000u, ebx, 0x1u, ecx, 0u);
   1115 
   1116   TestCmovRegReg(le, ebx, 0x80000000u, ecx, 0x1u, edx, 1u);
   1117   TestCmovRegReg(le, ebx, 0x1u, ecx, 0x80000000u, edx, 0u);
   1118 
   1119 #undef TestCmovRegReg
   1120 }
   1121 
   1122 TEST_F(AssemblerX8632Test, CmovRegAddr) {
   1123 #define TestCmovRegAddr(C, Src0, Value0, Value1, Dest, IsTrue)                 \
   1124   do {                                                                         \
   1125     const uint32_t T0 = allocateDword();                                       \
   1126     const uint32_t V0 = Value1;                                                \
   1127     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0));   \
   1128     __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0));   \
   1129     __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, dwordAddress(T0));    \
   1130     __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest,        \
   1131             dwordAddress(T0));                                                 \
   1132                                                                                \
   1133     AssembledTest test = assemble();                                           \
   1134     test.setDwordTo(T0, V0);                                                   \
   1135     test.run();                                                                \
   1136     ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest())                     \
   1137         << "(" #C ", " #Src0 ", " #Value0 ", " #Value1 ", " #Dest ", " #IsTrue \
   1138            ")";                                                                \
   1139                                                                                \
   1140     reset();                                                                   \
   1141   } while (0)
   1142 
   1143   TestCmovRegAddr(o, eax, 0x80000000u, 0x1u, ecx, 1u);
   1144   TestCmovRegAddr(o, eax, 0x1u, 0x10000000u, ecx, 0u);
   1145 
   1146   TestCmovRegAddr(no, ebx, 0x1u, 0x10000000u, edx, 1u);
   1147   TestCmovRegAddr(no, ebx, 0x80000000u, 0x1u, edx, 0u);
   1148 
   1149   TestCmovRegAddr(b, ecx, 0x1, 0x80000000u, eax, 1u);
   1150   TestCmovRegAddr(b, ecx, 0x80000000u, 0x1u, eax, 0u);
   1151 
   1152   TestCmovRegAddr(ae, edx, 0x80000000u, 0x1u, ebx, 1u);
   1153   TestCmovRegAddr(ae, edx, 0x1u, 0x80000000u, ebx, 0u);
   1154 
   1155   TestCmovRegAddr(e, edi, 0x1u, 0x1u, ecx, 1u);
   1156   TestCmovRegAddr(e, edi, 0x1u, 0x11111u, ecx, 0u);
   1157 
   1158   TestCmovRegAddr(ne, esi, 0x80000000u, 0x1u, edx, 1u);
   1159   TestCmovRegAddr(ne, esi, 0x1u, 0x1u, edx, 0u);
   1160 
   1161   TestCmovRegAddr(be, eax, 0x1u, 0x80000000u, eax, 1u);
   1162   TestCmovRegAddr(be, eax, 0x80000000u, 0x1u, eax, 0u);
   1163 
   1164   TestCmovRegAddr(a, ebx, 0x80000000u, 0x1u, ebx, 1u);
   1165   TestCmovRegAddr(a, ebx, 0x1u, 0x80000000u, ebx, 0u);
   1166 
   1167   TestCmovRegAddr(s, ecx, 0x1u, 0x80000000u, ecx, 1u);
   1168   TestCmovRegAddr(s, ecx, 0x80000000u, 0x1u, ecx, 0u);
   1169 
   1170   TestCmovRegAddr(ns, edx, 0x80000000u, 0x1u, ecx, 1u);
   1171   TestCmovRegAddr(ns, edx, 0x1u, 0x80000000u, ecx, 0u);
   1172 
   1173   TestCmovRegAddr(p, edi, 0x80000000u, 0x1u, edx, 1u);
   1174   TestCmovRegAddr(p, edi, 0x1u, 0x80000000u, edx, 0u);
   1175 
   1176   TestCmovRegAddr(np, esi, 0x1u, 0x80000000u, eax, 1u);
   1177   TestCmovRegAddr(np, esi, 0x80000000u, 0x1u, eax, 0u);
   1178 
   1179   TestCmovRegAddr(l, edi, 0x80000000u, 0x1u, ebx, 1u);
   1180   TestCmovRegAddr(l, edi, 0x1u, 0x80000000u, ebx, 0u);
   1181 
   1182   TestCmovRegAddr(ge, eax, 0x1u, 0x80000000u, ecx, 1u);
   1183   TestCmovRegAddr(ge, eax, 0x80000000u, 0x1u, ecx, 0u);
   1184 
   1185   TestCmovRegAddr(le, ebx, 0x80000000u, 0x1u, edx, 1u);
   1186   TestCmovRegAddr(le, ebx, 0x1u, 0x80000000u, edx, 0u);
   1187 
   1188 #undef TestCmovRegAddr
   1189 }
   1190 
   1191 } // end of anonymous namespace
   1192 } // end of namespace Test
   1193 } // end of namespace X8632
   1194 } // end of namespace Ice
   1195