|  | //===- subzero/unittest/AssemblerX8664/DataMov.cpp ------------------------===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | #include "AssemblerX8664/TestUtil.h" | 
|  |  | 
|  | namespace Ice { | 
|  | namespace X8664 { | 
|  | namespace Test { | 
|  | namespace { | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovRegImm) { | 
|  | static constexpr uint32_t Mask8 = 0x000000FF; | 
|  | static constexpr uint32_t Mask16 = 0x0000FFFF; | 
|  | static constexpr uint32_t Mask32 = 0xFFFFFFFF; | 
|  |  | 
|  | #define MovRegImm(Reg, Suffix, Size)                                           \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Reg ", " #Size ")";              \ | 
|  | static constexpr uint32_t Value = (0xABCD7645) & Mask##Size;               \ | 
|  | static constexpr uint32_t Marker = 0xBEEFFEEB;                             \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Reg##q(), Immediate(Marker));            \ | 
|  | __ mov(IceType_i##Size, Encoded_GPR_##Reg##Suffix(), Immediate(Value));    \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Reg##Suffix()) << TestString;                        \ | 
|  | ASSERT_EQ((Marker & ~Mask##Size) | Value, test.Reg##d()) << TestString;    \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Reg)                                                          \ | 
|  | do {                                                                         \ | 
|  | MovRegImm(Reg, l, 8);                                                      \ | 
|  | MovRegImm(Reg, w, 16);                                                     \ | 
|  | MovRegImm(Reg, d, 32);                                                     \ | 
|  | /* MovRegImm64 not implemented */                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1); | 
|  | TestImpl(r2); | 
|  | TestImpl(r3); | 
|  | TestImpl(r4); | 
|  | TestImpl(r5); | 
|  | TestImpl(r6); | 
|  | TestImpl(r7); | 
|  | TestImpl(r8); | 
|  | TestImpl(r10); | 
|  | TestImpl(r11); | 
|  | TestImpl(r12); | 
|  | TestImpl(r13); | 
|  | TestImpl(r14); | 
|  | TestImpl(r15); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef MovRegImm | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovMemImm) { | 
|  | const uint32_t T0 = allocateDword(); | 
|  | constexpr uint32_t ExpectedT0 = 0x00111100ul; | 
|  | const uint32_t T1 = allocateDword(); | 
|  | constexpr uint32_t ExpectedT1 = 0x00222200ul; | 
|  | const uint32_t T2 = allocateDword(); | 
|  | constexpr uint32_t ExpectedT2 = 0x03333000ul; | 
|  | const uint32_t T3 = allocateDword(); | 
|  | constexpr uint32_t ExpectedT3 = 0x00444400ul; | 
|  |  | 
|  | __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); | 
|  | __ mov(IceType_i16, dwordAddress(T1), Immediate(ExpectedT1)); | 
|  | __ mov(IceType_i8, dwordAddress(T2), Immediate(ExpectedT2)); | 
|  | __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); | 
|  |  | 
|  | AssembledTest test = assemble(); | 
|  | test.run(); | 
|  | EXPECT_EQ(0ul, test.eax()); | 
|  | EXPECT_EQ(0ul, test.ebx()); | 
|  | EXPECT_EQ(0ul, test.ecx()); | 
|  | EXPECT_EQ(0ul, test.edx()); | 
|  | EXPECT_EQ(0ul, test.edi()); | 
|  | EXPECT_EQ(0ul, test.esi()); | 
|  | EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); | 
|  | EXPECT_EQ(ExpectedT1 & 0xFFFF, test.contentsOfDword(T1)); | 
|  | EXPECT_EQ(ExpectedT2 & 0xFF, test.contentsOfDword(T2)); | 
|  | EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovMemReg) { | 
|  | static constexpr uint64_t Mask8 = 0x00000000000000FF; | 
|  | static constexpr uint64_t Mask16 = 0x000000000000FFFF; | 
|  | static constexpr uint64_t Mask32 = 0x00000000FFFFFFFF; | 
|  | static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFF; | 
|  |  | 
|  | #define TestMemReg(Src, Size)                                                  \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Size ")";              \ | 
|  | static constexpr uint32_t Value = 0x1a4d567e & Mask##Size;                 \ | 
|  | static constexpr uint64_t Marker = 0xD0DA33EEBEEFFEEB;                     \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value));                \ | 
|  | __ mov(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src());            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, Marker);                                               \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ((Marker & ~Mask##Size) | Value, test.contentsOfQword(T0))        \ | 
|  | << TestString;                                                         \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Src)                                                          \ | 
|  | do {                                                                         \ | 
|  | TestMemReg(Src, 8);                                                        \ | 
|  | TestMemReg(Src, 16);                                                       \ | 
|  | TestMemReg(Src, 32);                                                       \ | 
|  | TestMemReg(Src, 64);                                                       \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1); | 
|  | TestImpl(r2); | 
|  | TestImpl(r3); | 
|  | TestImpl(r4); | 
|  | TestImpl(r5); | 
|  | TestImpl(r6); | 
|  | TestImpl(r7); | 
|  | TestImpl(r8); | 
|  | TestImpl(r10); | 
|  | TestImpl(r11); | 
|  | TestImpl(r12); | 
|  | TestImpl(r13); | 
|  | TestImpl(r14); | 
|  | TestImpl(r15); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestMemReg | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovRegReg) { | 
|  | static constexpr uint64_t Mask8 = 0x00000000000000FFull; | 
|  | static constexpr uint64_t Mask16 = 0x000000000000FFFFull; | 
|  | static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull; | 
|  | static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull; | 
|  |  | 
|  | static constexpr uint64_t MaskResult8 = 0x00000000000000FFull; | 
|  | static constexpr uint64_t MaskResult16 = 0x000000000000FFFFull; | 
|  | static constexpr uint64_t MaskResult32 = 0xFFFFFFFFFFFFFFFFull; | 
|  | static constexpr uint64_t MaskResult64 = 0xFFFFFFFFFFFFFFFFull; | 
|  |  | 
|  | #define TestRegReg(Dst, Src, Suffix, Size)                                     \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #Dst ", " #Src ", " #Suffix ", " #Size ")";                        \ | 
|  | const uint8_t T0 = allocateQword();                                        \ | 
|  | static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size;      \ | 
|  | const uint8_t T1 = allocateQword();                                        \ | 
|  | static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull;                  \ | 
|  | \ | 
|  | __ mov(IceType_i64, Encoded_GPR_##Src(), dwordAddress(T0));                \ | 
|  | __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1));                \ | 
|  | __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src());         \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, Value);                                                \ | 
|  | test.setQwordTo(T1, Marker);                                               \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ((Marker & ~MaskResult##Size) | Value, test.Dst()) << TestString; \ | 
|  | ASSERT_EQ(Value, test.Dst##Suffix()) << TestString;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst, Src)                                                     \ | 
|  | do {                                                                         \ | 
|  | TestRegReg(Dst, Src, l, 8);                                                \ | 
|  | TestRegReg(Dst, Src, w, 16);                                               \ | 
|  | TestRegReg(Dst, Src, d, 32);                                               \ | 
|  | TestRegReg(Dst, Src, q, 64);                                               \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1, r2); | 
|  | TestImpl(r2, r3); | 
|  | TestImpl(r3, r4); | 
|  | TestImpl(r4, r5); | 
|  | TestImpl(r5, r6); | 
|  | TestImpl(r6, r7); | 
|  | TestImpl(r7, r8); | 
|  | TestImpl(r8, r10); | 
|  | TestImpl(r10, r11); | 
|  | TestImpl(r11, r12); | 
|  | TestImpl(r12, r13); | 
|  | TestImpl(r13, r14); | 
|  | TestImpl(r14, r15); | 
|  | TestImpl(r15, r1); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestRegReg | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovRegMem) { | 
|  | static constexpr uint64_t Mask8 = 0x00000000000000FFull; | 
|  | static constexpr uint64_t Mask16 = 0x000000000000FFFFull; | 
|  | static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull; | 
|  | static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull; | 
|  |  | 
|  | static constexpr uint64_t MaskResult8 = ~0x00000000000000FFull; | 
|  | static constexpr uint64_t MaskResult16 = ~0x000000000000FFFFull; | 
|  | static constexpr uint64_t MaskResult32 = ~0xFFFFFFFFFFFFFFFFull; | 
|  | static constexpr uint64_t MaskResult64 = ~0xFFFFFFFFFFFFFFFFull; | 
|  |  | 
|  | #define TestRegAddr(Dst, Suffix, Size)                                         \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #Dst ", Addr, " #Suffix ", " #Size ")";                            \ | 
|  | const uint8_t T0 = allocateQword();                                        \ | 
|  | static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size;      \ | 
|  | const uint8_t T1 = allocateQword();                                        \ | 
|  | static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull;                  \ | 
|  | \ | 
|  | __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1));                \ | 
|  | __ mov(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0));            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, Value);                                                \ | 
|  | test.setQwordTo(T1, Marker);                                               \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ((Marker & MaskResult##Size) | Value, test.Dst()) << TestString;  \ | 
|  | ASSERT_EQ(Value, test.Dst##Suffix()) << TestString;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst)                                                          \ | 
|  | do {                                                                         \ | 
|  | TestRegAddr(Dst, l, 8);                                                    \ | 
|  | TestRegAddr(Dst, w, 16);                                                   \ | 
|  | TestRegAddr(Dst, d, 32);                                                   \ | 
|  | TestRegAddr(Dst, q, 64);                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1); | 
|  | TestImpl(r2); | 
|  | TestImpl(r3); | 
|  | TestImpl(r4); | 
|  | TestImpl(r5); | 
|  | TestImpl(r6); | 
|  | TestImpl(r7); | 
|  | TestImpl(r8); | 
|  | TestImpl(r10); | 
|  | TestImpl(r11); | 
|  | TestImpl(r12); | 
|  | TestImpl(r13); | 
|  | TestImpl(r14); | 
|  | TestImpl(r15); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestRegAddr | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Movabs) { | 
|  | #define TestImplValue(Dst, Value)                                              \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", " #Value ")";             \ | 
|  | uint64_t V = (Value);                                                      \ | 
|  | __ movabs(Encoded_GPR_##Dst##q(), V);                                      \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V, test.DST()) << TestString;                                    \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst)                                                          \ | 
|  | do {                                                                         \ | 
|  | for (uint64_t V = {0, 1, 0xFFFFFFull, 0x80000000ull,                       \ | 
|  | 0xFFFFFFFFFFFFFFFFull}) {                               \ | 
|  | TestImpl(Dst, V);                                                        \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestImplValue | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Movzx) { | 
|  | static constexpr uint32_t Mask8 = 0x000000FF; | 
|  | static constexpr uint32_t Mask16 = 0x0000FFFF; | 
|  |  | 
|  | #define TestImplRegReg(Dst, Src, Suffix, Size)                                 \ | 
|  | do {                                                                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull;                      \ | 
|  | static constexpr uint32_t Value = (0xBEEF) & Mask##Size;                   \ | 
|  | __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0));             \ | 
|  | __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value));    \ | 
|  | __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(),                          \ | 
|  | Encoded_GPR_##Src##Suffix());                                     \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")";      \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImplRegAddr(Dst, Suffix, Size)                                     \ | 
|  | do {                                                                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull;                      \ | 
|  | static constexpr uint32_t Value = (0xBEEF) & Mask##Size;                   \ | 
|  | __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0));       \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, (V0 & ~Mask##Size) | Value);                           \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")";          \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst, Src)                                                     \ | 
|  | do {                                                                         \ | 
|  | TestImplRegReg(Dst, Src, l, 8);                                            \ | 
|  | TestImplRegAddr(Dst, l, 8);                                                \ | 
|  | TestImplRegReg(Dst, Src, w, 16);                                           \ | 
|  | TestImplRegAddr(Dst, w, 16);                                               \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1, r2); | 
|  | TestImpl(r2, r3); | 
|  | TestImpl(r3, r4); | 
|  | TestImpl(r4, r5); | 
|  | TestImpl(r5, r6); | 
|  | TestImpl(r6, r7); | 
|  | TestImpl(r7, r8); | 
|  | TestImpl(r8, r10); | 
|  | TestImpl(r10, r11); | 
|  | TestImpl(r11, r12); | 
|  | TestImpl(r12, r13); | 
|  | TestImpl(r13, r14); | 
|  | TestImpl(r14, r15); | 
|  | TestImpl(r15, r1); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestImplRegAddr | 
|  | #undef TestImplRegReg | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Movsx) { | 
|  | static constexpr uint64_t Mask8 = 0x000000FF; | 
|  | static constexpr uint64_t Mask16 = 0x0000FFFF; | 
|  | static constexpr uint64_t Mask32 = 0xFFFFFFFF; | 
|  |  | 
|  | #define TestImplRegReg(Dst, Src, Suffix, Size)                                 \ | 
|  | do {                                                                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull;                      \ | 
|  | static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size;               \ | 
|  | __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0));             \ | 
|  | __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value));    \ | 
|  | __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(),                          \ | 
|  | Encoded_GPR_##Src##Suffix());                                     \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q())             \ | 
|  | << "(" #Dst ", " #Src ", " #Size ")";                                  \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImplRegAddr(Dst, Suffix, Size)                                     \ | 
|  | do {                                                                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | static constexpr uint64_t V0 = 0xC0BEBEEF & Mask##Size;                    \ | 
|  | static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size;               \ | 
|  | __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0));       \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q())             \ | 
|  | << "(" #Dst ", Addr, " #Size ")";                                      \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst, Src)                                                     \ | 
|  | do {                                                                         \ | 
|  | TestImplRegReg(Dst, Src, l, 8);                                            \ | 
|  | TestImplRegAddr(Dst, l, 8);                                                \ | 
|  | TestImplRegReg(Dst, Src, w, 16);                                           \ | 
|  | TestImplRegAddr(Dst, w, 16);                                               \ | 
|  | TestImplRegReg(Dst, Src, w, 32);                                           \ | 
|  | TestImplRegAddr(Dst, w, 32);                                               \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1, r2); | 
|  | TestImpl(r2, r3); | 
|  | TestImpl(r3, r4); | 
|  | TestImpl(r4, r5); | 
|  | TestImpl(r5, r6); | 
|  | TestImpl(r6, r7); | 
|  | TestImpl(r7, r8); | 
|  | TestImpl(r8, r10); | 
|  | TestImpl(r10, r11); | 
|  | TestImpl(r11, r12); | 
|  | TestImpl(r12, r13); | 
|  | TestImpl(r13, r14); | 
|  | TestImpl(r14, r15); | 
|  | TestImpl(r15, r1); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestImplRegAddr | 
|  | #undef TestImplRegReg | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Cmov) { | 
|  | #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1)                \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1      \ | 
|  | ", " #Value1 ")";                                                      \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0));              \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1));              \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0));              \ | 
|  | __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1());           \ | 
|  | __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(),                   \ | 
|  | Encoded_GPR_##Src1());                                             \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString;      \ | 
|  | \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1)                     \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0                 \ | 
|  | ", Addr, " #Value1 ")";                                                \ | 
|  | const uint32_t T0 = allocateDword();                                       \ | 
|  | const uint32_t V0 = Value1;                                                \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0));              \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0));              \ | 
|  | __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0));               \ | 
|  | __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(),                   \ | 
|  | dwordAddress(T0));                                                 \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString;      \ | 
|  | \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1)                 \ | 
|  | do {                                                                         \ | 
|  | TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1);                   \ | 
|  | TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1);                        \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dest, Src0, Src1)                                             \ | 
|  | do {                                                                         \ | 
|  | TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u);                     \ | 
|  | TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u);                    \ | 
|  | TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u);                      \ | 
|  | TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u);                            \ | 
|  | TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u);                        \ | 
|  | TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u);                           \ | 
|  | TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \ | 
|  | TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                     \ | 
|  | TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \ | 
|  | TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                     \ | 
|  | TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                     \ | 
|  | TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u);                    \ | 
|  | TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u);                    \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(r1, r2, r3); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestValue | 
|  | #undef TestRegAddr | 
|  | #undef TestRegReg | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664LowLevelTest, RepMovsb) { | 
|  | __ rep_movsb(); | 
|  |  | 
|  | static constexpr uint32_t ByteCount = 2; | 
|  | static constexpr uint8_t Prefix = 0xF3; | 
|  | static constexpr uint8_t Opcode = 0xA4; | 
|  |  | 
|  | ASSERT_EQ(ByteCount, codeBytesSize()); | 
|  | verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode); | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovssXmmAddr) { | 
|  | #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value)                   \ | 
|  | do {                                                                         \ | 
|  | static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \ | 
|  | "Invalid fp length #FloatLength");                           \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | \ | 
|  | static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")";       \ | 
|  | static constexpr bool IsDouble = std::is_same<Type, double>::value;        \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const Type V0 = Value;                                                     \ | 
|  | \ | 
|  | __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0));   \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | if (IsDouble) {                                                            \ | 
|  | test.setQwordTo(T0, static_cast<double>(V0));                            \ | 
|  | } else {                                                                   \ | 
|  | test.setDwordTo(T0, static_cast<float>(V0));                             \ | 
|  | }                                                                          \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is "    \ | 
|  | << Value;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovssXmmAddr(FloatLength)                                          \ | 
|  | do {                                                                         \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value);                   \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value);                  \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value);                  \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value);                  \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value);                  \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value);                  \ | 
|  | TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value);                  \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovssXmmAddr(32); | 
|  | TestMovssXmmAddr(64); | 
|  |  | 
|  | #undef TestMovssXmmAddr | 
|  | #undef TestMovssXmmAddrType | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovssAddrXmm) { | 
|  | #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value)                   \ | 
|  | do {                                                                         \ | 
|  | static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \ | 
|  | "Invalid fp length #FloatLength");                           \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | \ | 
|  | static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")";       \ | 
|  | static constexpr bool IsDouble = std::is_same<Type, double>::value;        \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const Type V0 = Value;                                                     \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | static_assert(std::numeric_limits<Type>::has_quiet_NaN,                    \ | 
|  | "f" #FloatLength " does not have quiet nan.");               \ | 
|  | const Type V1 = std::numeric_limits<Type>::quiet_NaN();                    \ | 
|  | \ | 
|  | __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0));   \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | if (IsDouble) {                                                            \ | 
|  | test.setQwordTo(T0, static_cast<double>(V0));                            \ | 
|  | test.setQwordTo(T1, static_cast<double>(V1));                            \ | 
|  | } else {                                                                   \ | 
|  | test.setDwordTo(T0, static_cast<float>(V0));                             \ | 
|  | test.setDwordTo(T1, static_cast<float>(V1));                             \ | 
|  | }                                                                          \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is "    \ | 
|  | << Value;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovssAddrXmm(FloatLength)                                          \ | 
|  | do {                                                                         \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value);                   \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value);                  \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value);                  \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value);                  \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value);                  \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value);                  \ | 
|  | TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value);                  \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovssAddrXmm(32); | 
|  | TestMovssAddrXmm(64); | 
|  |  | 
|  | #undef TestMovssAddrXmm | 
|  | #undef TestMovssAddrXmmType | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovssXmmXmm) { | 
|  | #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value)               \ | 
|  | do {                                                                         \ | 
|  | static_assert((FloatLength) == 32 || (FloatLength) == 64,                  \ | 
|  | "Invalid fp length #FloatLength");                           \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #FloatLength ", " #Src ", " #Dst ")";                              \ | 
|  | static constexpr bool IsDouble = std::is_same<Type, double>::value;        \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const Type V0 = Value;                                                     \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | static_assert(std::numeric_limits<Type>::has_quiet_NaN,                    \ | 
|  | "f" #FloatLength " does not have quiet nan.");               \ | 
|  | const Type V1 = std::numeric_limits<Type>::quiet_NaN();                    \ | 
|  | \ | 
|  | __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0));   \ | 
|  | __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1));   \ | 
|  | __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(),                      \ | 
|  | Encoded_Xmm_##Src());                                             \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | if (IsDouble) {                                                            \ | 
|  | test.setQwordTo(T0, static_cast<double>(V0));                            \ | 
|  | test.setQwordTo(T1, static_cast<double>(V1));                            \ | 
|  | } else {                                                                   \ | 
|  | test.setDwordTo(T0, static_cast<float>(V0));                             \ | 
|  | test.setDwordTo(T1, static_cast<float>(V1));                             \ | 
|  | }                                                                          \ | 
|  | test.run();                                                                \ | 
|  | ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is "    \ | 
|  | << Value;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovssXmmXmm(FloatLength)                                           \ | 
|  | do {                                                                         \ | 
|  | using Type = std::conditional<FloatLength == 32, float, double>::type;     \ | 
|  | for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) {        \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value);              \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value);             \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value);            \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value);            \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value);            \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value);            \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value);            \ | 
|  | TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value);             \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovssXmmXmm(32); | 
|  | TestMovssXmmXmm(64); | 
|  |  | 
|  | #undef TestMovssXmmXmm | 
|  | #undef TestMovssXmmXmmType | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovdToXmm) { | 
|  | #define TestMovdXmmReg32(Src, Dst, Value)                                      \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = 0xFFFFFFFF00000000ull;                                 \ | 
|  | \ | 
|  | __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value));                \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i32, Encoded_Xmm_##Dst(), Encoded_GPR_##Src());            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdXmmReg64(Src, Dst, Value)                                      \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = 0xFFFFFFFF00000000ull;                                 \ | 
|  | const uint64_t Expected = (static_cast<uint64_t>(Value) << 32) | (Value);  \ | 
|  | \ | 
|  | __ movabs(Encoded_GPR_##Src(), Expected);                                  \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i64, Encoded_Xmm_##Dst(), Encoded_GPR_##Src());            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Expected, test.Dst<uint64_t>()) << TestString << " value is "    \ | 
|  | << Value;                        \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdXmmReg(Src, Dst, Value)                                        \ | 
|  | do {                                                                         \ | 
|  | TestMovdXmmReg32(Src, Dst, Value);                                         \ | 
|  | TestMovdXmmReg64(Src, Dst, Value);                                         \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdXmmAddr32(Dst, Value)                                          \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Dst ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint32_t V0 = Value;                                                 \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = 0xFFFFFFFF00000000ull;                                 \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1));              \ | 
|  | __ movd(IceType_i32, Encoded_Xmm_##Dst(), dwordAddress(T0));               \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setDwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdXmmAddr64(Dst, Value)                                          \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Dst ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint32_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value);        \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = 0xFFFFFFFF00000000ull;                                 \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1));              \ | 
|  | __ movd(IceType_i64, Encoded_Xmm_##Dst(), dwordAddress(T0));               \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setDwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdXmmAddr(Dst, Value)                                            \ | 
|  | do {                                                                         \ | 
|  | TestMovdXmmAddr32(Dst, Value);                                             \ | 
|  | TestMovdXmmAddr64(Dst, Value);                                             \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovd(Dst)                                                          \ | 
|  | do {                                                                         \ | 
|  | for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {   \ | 
|  | TestMovdXmmReg(r1, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r2, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r3, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r4, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r5, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r6, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r7, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r8, Dst, Value);                                          \ | 
|  | TestMovdXmmReg(r10, Dst, Value);                                         \ | 
|  | TestMovdXmmReg(r11, Dst, Value);                                         \ | 
|  | TestMovdXmmReg(r12, Dst, Value);                                         \ | 
|  | TestMovdXmmReg(r13, Dst, Value);                                         \ | 
|  | TestMovdXmmReg(r14, Dst, Value);                                         \ | 
|  | TestMovdXmmReg(r15, Dst, Value);                                         \ | 
|  | TestMovdXmmAddr(Dst, Value);                                             \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovd(xmm0); | 
|  | TestMovd(xmm1); | 
|  | TestMovd(xmm2); | 
|  | TestMovd(xmm3); | 
|  | TestMovd(xmm4); | 
|  | TestMovd(xmm5); | 
|  | TestMovd(xmm6); | 
|  | TestMovd(xmm7); | 
|  | TestMovd(xmm8); | 
|  | TestMovd(xmm9); | 
|  | TestMovd(xmm10); | 
|  | TestMovd(xmm11); | 
|  | TestMovd(xmm12); | 
|  | TestMovd(xmm13); | 
|  | TestMovd(xmm14); | 
|  | TestMovd(xmm15); | 
|  |  | 
|  | #undef TestMovd | 
|  | #undef TestMovdXmmAddr | 
|  | #undef TestMovdXmmAddr64 | 
|  | #undef TestMovdXmmAddr32 | 
|  | #undef TestMovdXmmReg | 
|  | #undef TestMovdXmmReg64 | 
|  | #undef TestMovdXmmReg32 | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovdFromXmm) { | 
|  | #define TestMovdRegXmm32(Src, Dst, Value)                                      \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \ | 
|  | const uint32_t T0 = allocateDword();                                       \ | 
|  | const uint32_t V0 = Value;                                                 \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i32, Encoded_GPR_##Dst(), Encoded_Xmm_##Src());            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setDwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is "   \ | 
|  | << Value;                       \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdRegXmm64(Src, Dst, Value)                                      \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \ | 
|  | const uint32_t T0 = allocateDword();                                       \ | 
|  | const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value);        \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i64, Encoded_GPR_##Dst(), Encoded_Xmm_##Src());            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.contentsOfQword(T0)) << TestString << " value is "      \ | 
|  | << Value;                          \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdRegXmm(Src, Dst, Value)                                        \ | 
|  | do {                                                                         \ | 
|  | TestMovdRegXmm32(Src, Dst, Value);                                         \ | 
|  | TestMovdRegXmm64(Src, Dst, Value);                                         \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdAddrXmm32(Src, Value)                                          \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateDword();                                       \ | 
|  | const uint32_t V0 = Value;                                                 \ | 
|  | const uint32_t T1 = allocateDword();                                       \ | 
|  | const uint32_t V1 = ~(Value);                                              \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i32, dwordAddress(T1), Encoded_Xmm_##Src());               \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setDwordTo(T0, V0);                                                   \ | 
|  | test.setDwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is "   \ | 
|  | << Value;                       \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdAddrXmm64(Src, Value)                                          \ | 
|  | do {                                                                         \ | 
|  | assert(((Value)&0xFFFFFFFF) == (Value));                                   \ | 
|  | static constexpr char TestString[] = "(" #Src ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | Value;          \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = ~V0;                                                   \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0));              \ | 
|  | __ movd(IceType_i64, dwordAddress(T1), Encoded_Xmm_##Src());               \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.contentsOfQword(T1)) << TestString << " value is "      \ | 
|  | << Value;                          \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovdAddrXmm(Src, Value)                                            \ | 
|  | do {                                                                         \ | 
|  | TestMovdAddrXmm32(Src, Value);                                             \ | 
|  | TestMovdAddrXmm64(Src, Value);                                             \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovd(Src)                                                          \ | 
|  | do {                                                                         \ | 
|  | for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {   \ | 
|  | TestMovdRegXmm(Src, r1, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r2, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r3, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r4, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r5, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r6, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r7, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r8, Value);                                          \ | 
|  | TestMovdRegXmm(Src, r10, Value);                                         \ | 
|  | TestMovdRegXmm(Src, r11, Value);                                         \ | 
|  | TestMovdRegXmm(Src, r12, Value);                                         \ | 
|  | TestMovdRegXmm(Src, r13, Value);                                         \ | 
|  | TestMovdRegXmm(Src, r14, Value);                                         \ | 
|  | TestMovdRegXmm(Src, r15, Value);                                         \ | 
|  | TestMovdAddrXmm(Src, Value);                                             \ | 
|  | }                                                                          \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovd(xmm0); | 
|  | TestMovd(xmm1); | 
|  | TestMovd(xmm2); | 
|  | TestMovd(xmm3); | 
|  | TestMovd(xmm4); | 
|  | TestMovd(xmm5); | 
|  | TestMovd(xmm6); | 
|  | TestMovd(xmm7); | 
|  | TestMovd(xmm8); | 
|  | TestMovd(xmm9); | 
|  | TestMovd(xmm10); | 
|  | TestMovd(xmm11); | 
|  | TestMovd(xmm12); | 
|  | TestMovd(xmm13); | 
|  | TestMovd(xmm14); | 
|  | TestMovd(xmm15); | 
|  |  | 
|  | #undef TestMovd | 
|  | #undef TestMovdAddrXmm | 
|  | #undef TestMovdAddrXmm64 | 
|  | #undef TestMovdAddrXmm32 | 
|  | #undef TestMovdRegXmm | 
|  | #undef TestMovdRegXmm64 | 
|  | #undef TestMovdRegXmm32 | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovqXmmAddr) { | 
|  | #define TestMovd(Dst, Value)                                                   \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = Value;                                                 \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = ~(Value);                                              \ | 
|  | \ | 
|  | __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1));              \ | 
|  | __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0));                            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { | 
|  | TestMovd(xmm0, Value); | 
|  | TestMovd(xmm1, Value); | 
|  | TestMovd(xmm2, Value); | 
|  | TestMovd(xmm3, Value); | 
|  | TestMovd(xmm4, Value); | 
|  | TestMovd(xmm5, Value); | 
|  | TestMovd(xmm6, Value); | 
|  | TestMovd(xmm7, Value); | 
|  | TestMovd(xmm8, Value); | 
|  | TestMovd(xmm9, Value); | 
|  | TestMovd(xmm10, Value); | 
|  | TestMovd(xmm11, Value); | 
|  | TestMovd(xmm12, Value); | 
|  | TestMovd(xmm13, Value); | 
|  | TestMovd(xmm14, Value); | 
|  | TestMovd(xmm15, Value); | 
|  | } | 
|  |  | 
|  | #undef TestMovd | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovqAddrXmm) { | 
|  | #define TestMovd(Dst, Value)                                                   \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", Addr)";                   \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = Value;                                                 \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = ~(Value);                                              \ | 
|  | \ | 
|  | __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0));                            \ | 
|  | __ movq(dwordAddress(T1), Encoded_Xmm_##Dst());                            \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { | 
|  | TestMovd(xmm0, Value); | 
|  | TestMovd(xmm1, Value); | 
|  | TestMovd(xmm2, Value); | 
|  | TestMovd(xmm3, Value); | 
|  | TestMovd(xmm4, Value); | 
|  | TestMovd(xmm5, Value); | 
|  | TestMovd(xmm6, Value); | 
|  | TestMovd(xmm7, Value); | 
|  | TestMovd(xmm8, Value); | 
|  | TestMovd(xmm9, Value); | 
|  | TestMovd(xmm10, Value); | 
|  | TestMovd(xmm11, Value); | 
|  | TestMovd(xmm12, Value); | 
|  | TestMovd(xmm13, Value); | 
|  | TestMovd(xmm14, Value); | 
|  | TestMovd(xmm15, Value); | 
|  | } | 
|  |  | 
|  | #undef TestMovd | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovqXmmXmm) { | 
|  | #define TestMovd(Src, Dst, Value)                                              \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Src ", " #Dst ")";               \ | 
|  | const uint32_t T0 = allocateQword();                                       \ | 
|  | const uint64_t V0 = Value;                                                 \ | 
|  | const uint32_t T1 = allocateQword();                                       \ | 
|  | const uint64_t V1 = ~(Value);                                              \ | 
|  | \ | 
|  | __ movq(Encoded_Xmm_##Src(), dwordAddress(T0));                            \ | 
|  | __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1));                            \ | 
|  | __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src());                         \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | \ | 
|  | test.setQwordTo(T0, V0);                                                   \ | 
|  | test.setQwordTo(T1, V1);                                                   \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is "       \ | 
|  | << Value;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { | 
|  | TestMovd(xmm0, xmm1, Value); | 
|  | TestMovd(xmm1, xmm2, Value); | 
|  | TestMovd(xmm2, xmm3, Value); | 
|  | TestMovd(xmm3, xmm4, Value); | 
|  | TestMovd(xmm4, xmm5, Value); | 
|  | TestMovd(xmm5, xmm6, Value); | 
|  | TestMovd(xmm6, xmm7, Value); | 
|  | TestMovd(xmm7, xmm8, Value); | 
|  | TestMovd(xmm8, xmm9, Value); | 
|  | TestMovd(xmm9, xmm10, Value); | 
|  | TestMovd(xmm10, xmm11, Value); | 
|  | TestMovd(xmm11, xmm12, Value); | 
|  | TestMovd(xmm12, xmm13, Value); | 
|  | TestMovd(xmm13, xmm14, Value); | 
|  | TestMovd(xmm14, xmm15, Value); | 
|  | TestMovd(xmm15, xmm0, Value); | 
|  | } | 
|  |  | 
|  | #undef TestMovd | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovupsXmmAddr) { | 
|  | #define TestMovups(Dst)                                                        \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ")";                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \ | 
|  | std::numeric_limits<float>::infinity());                   \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0));                          \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovups(xmm0); | 
|  | TestMovups(xmm1); | 
|  | TestMovups(xmm2); | 
|  | TestMovups(xmm3); | 
|  | TestMovups(xmm4); | 
|  | TestMovups(xmm5); | 
|  | TestMovups(xmm6); | 
|  | TestMovups(xmm7); | 
|  | TestMovups(xmm8); | 
|  | TestMovups(xmm9); | 
|  | TestMovups(xmm10); | 
|  | TestMovups(xmm11); | 
|  | TestMovups(xmm12); | 
|  | TestMovups(xmm13); | 
|  | TestMovups(xmm14); | 
|  | TestMovups(xmm15); | 
|  |  | 
|  | #undef TestMovups | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovupsAddrXmm) { | 
|  | #define TestMovups(Src)                                                        \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Src ")";                         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \ | 
|  | std::numeric_limits<float>::infinity());                   \ | 
|  | const uint32_t T1 = allocateDqword();                                      \ | 
|  | const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T0));                          \ | 
|  | __ movups(dwordAddress(T1), Encoded_Xmm_##Src());                          \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.setDqwordTo(T1, V1);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString;                    \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovups(xmm0); | 
|  | TestMovups(xmm1); | 
|  | TestMovups(xmm2); | 
|  | TestMovups(xmm3); | 
|  | TestMovups(xmm4); | 
|  | TestMovups(xmm5); | 
|  | TestMovups(xmm6); | 
|  | TestMovups(xmm7); | 
|  | TestMovups(xmm8); | 
|  | TestMovups(xmm9); | 
|  | TestMovups(xmm10); | 
|  | TestMovups(xmm11); | 
|  | TestMovups(xmm12); | 
|  | TestMovups(xmm13); | 
|  | TestMovups(xmm14); | 
|  | TestMovups(xmm15); | 
|  |  | 
|  | #undef TestMovups | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovupsXmmXmm) { | 
|  | #define TestMovups(Dst, Src)                                                   \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", " #Src ")";               \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \ | 
|  | std::numeric_limits<float>::infinity());                   \ | 
|  | const uint32_t T1 = allocateDqword();                                      \ | 
|  | const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T0));                          \ | 
|  | __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1));                          \ | 
|  | __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src());                       \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.setDqwordTo(T1, V1);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovups(xmm0, xmm1); | 
|  | TestMovups(xmm1, xmm2); | 
|  | TestMovups(xmm2, xmm3); | 
|  | TestMovups(xmm3, xmm4); | 
|  | TestMovups(xmm4, xmm5); | 
|  | TestMovups(xmm5, xmm6); | 
|  | TestMovups(xmm6, xmm7); | 
|  | TestMovups(xmm7, xmm8); | 
|  | TestMovups(xmm8, xmm9); | 
|  | TestMovups(xmm9, xmm10); | 
|  | TestMovups(xmm10, xmm11); | 
|  | TestMovups(xmm11, xmm12); | 
|  | TestMovups(xmm12, xmm13); | 
|  | TestMovups(xmm13, xmm14); | 
|  | TestMovups(xmm14, xmm15); | 
|  | TestMovups(xmm15, xmm0); | 
|  |  | 
|  | #undef TestMovups | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, MovapsXmmXmm) { | 
|  | #define TestMovaps(Dst, Src)                                                   \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", " #Src ")";               \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(),       \ | 
|  | std::numeric_limits<float>::infinity());                   \ | 
|  | const uint32_t T1 = allocateDqword();                                      \ | 
|  | const Dqword V1(0.0, 0.0, 0.0, 0.0);                                       \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T0));                          \ | 
|  | __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1));                          \ | 
|  | __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src());                       \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.setDqwordTo(T1, V1);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString;                           \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovaps(xmm0, xmm1); | 
|  | TestMovaps(xmm1, xmm2); | 
|  | TestMovaps(xmm2, xmm3); | 
|  | TestMovaps(xmm3, xmm4); | 
|  | TestMovaps(xmm4, xmm5); | 
|  | TestMovaps(xmm5, xmm6); | 
|  | TestMovaps(xmm6, xmm7); | 
|  | TestMovaps(xmm7, xmm8); | 
|  | TestMovaps(xmm8, xmm9); | 
|  | TestMovaps(xmm9, xmm10); | 
|  | TestMovaps(xmm10, xmm11); | 
|  | TestMovaps(xmm11, xmm12); | 
|  | TestMovaps(xmm12, xmm13); | 
|  | TestMovaps(xmm13, xmm14); | 
|  | TestMovaps(xmm14, xmm15); | 
|  | TestMovaps(xmm15, xmm0); | 
|  |  | 
|  | #undef TestMovaps | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Movhlps_Movlhps) { | 
|  | #define TestImplSingle(Dst, Src, Inst, Expect)                                 \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")";    \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),                           \ | 
|  | uint64_t(0xCCCCCCCCDDDDDDDDull));                          \ | 
|  | const uint32_t T1 = allocateDqword();                                      \ | 
|  | const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),                           \ | 
|  | uint64_t(0x9999999988888888ull));                          \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0));                          \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T1));                          \ | 
|  | __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src());                         \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.setDqwordTo(T1, V1);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString;                \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestImpl(Dst, Src)                                                     \ | 
|  | do {                                                                         \ | 
|  | TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull),        \ | 
|  | uint64_t(0xCCCCCCCCDDDDDDDDull)));      \ | 
|  | TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull),        \ | 
|  | uint64_t(0xEEEEEEEEFFFFFFFFull)));      \ | 
|  | } while (0) | 
|  |  | 
|  | TestImpl(xmm0, xmm1); | 
|  | TestImpl(xmm1, xmm2); | 
|  | TestImpl(xmm2, xmm3); | 
|  | TestImpl(xmm3, xmm4); | 
|  | TestImpl(xmm4, xmm5); | 
|  | TestImpl(xmm5, xmm6); | 
|  | TestImpl(xmm6, xmm7); | 
|  | TestImpl(xmm7, xmm8); | 
|  | TestImpl(xmm8, xmm9); | 
|  | TestImpl(xmm9, xmm10); | 
|  | TestImpl(xmm10, xmm11); | 
|  | TestImpl(xmm11, xmm12); | 
|  | TestImpl(xmm12, xmm13); | 
|  | TestImpl(xmm13, xmm14); | 
|  | TestImpl(xmm14, xmm15); | 
|  | TestImpl(xmm15, xmm0); | 
|  |  | 
|  | #undef TestImpl | 
|  | #undef TestImplSingle | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Movmsk) { | 
|  | #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst)                     \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] =                                       \ | 
|  | "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")";         \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0 Value1;                                                    \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T0));                          \ | 
|  | __ Inst(IceType_v4f32, Encoded_GPR_##GPR(), Encoded_Xmm_##Src());          \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | ASSERT_EQ(Expected, test.GPR()) << TestString;                             \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestMovmsk(GPR, Src)                                                   \ | 
|  | do {                                                                         \ | 
|  | TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmsk);        \ | 
|  | } while (0) | 
|  |  | 
|  | TestMovmsk(r1, xmm0); | 
|  | TestMovmsk(r2, xmm1); | 
|  | TestMovmsk(r3, xmm2); | 
|  | TestMovmsk(r4, xmm3); | 
|  | TestMovmsk(r5, xmm4); | 
|  | TestMovmsk(r6, xmm5); | 
|  | TestMovmsk(r7, xmm6); | 
|  | TestMovmsk(r8, xmm7); | 
|  | TestMovmsk(r10, xmm8); | 
|  | TestMovmsk(r11, xmm9); | 
|  | TestMovmsk(r12, xmm10); | 
|  | TestMovmsk(r13, xmm11); | 
|  | TestMovmsk(r14, xmm12); | 
|  | TestMovmsk(r15, xmm13); | 
|  | TestMovmsk(r1, xmm14); | 
|  | TestMovmsk(r2, xmm15); | 
|  |  | 
|  | #undef TestMovmskGPRXmm | 
|  | #undef TestMovmsk | 
|  | } | 
|  |  | 
|  | TEST_F(AssemblerX8664Test, Pmovsxdq) { | 
|  | #define TestPmovsxdqXmmXmm(Dst, Src, Value1)                                   \ | 
|  | do {                                                                         \ | 
|  | static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")";  \ | 
|  | const uint32_t T0 = allocateDqword();                                      \ | 
|  | const Dqword V0 Value1;                                                    \ | 
|  | const uint32_t T1 = allocateDqword();                                      \ | 
|  | const Dqword V1(uint64_t(0), uint64_t(0));                                 \ | 
|  | \ | 
|  | __ movups(Encoded_Xmm_##Src(), dwordAddress(T0));                          \ | 
|  | __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1));                          \ | 
|  | __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src());                     \ | 
|  | \ | 
|  | AssembledTest test = assemble();                                           \ | 
|  | test.setDqwordTo(T0, V0);                                                  \ | 
|  | test.setDqwordTo(T1, V1);                                                  \ | 
|  | test.run();                                                                \ | 
|  | \ | 
|  | const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1]));           \ | 
|  | ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString;                     \ | 
|  | reset();                                                                   \ | 
|  | } while (0) | 
|  |  | 
|  | #define TestPmovsxdq(Dst, Src)                                                 \ | 
|  | do {                                                                         \ | 
|  | TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull),             \ | 
|  | uint64_t(0xAAAAAAAAEEEEEEEEull)));           \ | 
|  | TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull),             \ | 
|  | uint64_t(0xAAAAAAAAEEEEEEEEull)));           \ | 
|  | TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull),             \ | 
|  | uint64_t(0xAAAAAAAAEEEEEEEEull)));           \ | 
|  | TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull),             \ | 
|  | uint64_t(0xAAAAAAAAEEEEEEEEull)));           \ | 
|  | } while (0) | 
|  |  | 
|  | TestPmovsxdq(xmm0, xmm1); | 
|  | TestPmovsxdq(xmm1, xmm2); | 
|  | TestPmovsxdq(xmm2, xmm3); | 
|  | TestPmovsxdq(xmm3, xmm4); | 
|  | TestPmovsxdq(xmm4, xmm5); | 
|  | TestPmovsxdq(xmm5, xmm6); | 
|  | TestPmovsxdq(xmm6, xmm7); | 
|  | TestPmovsxdq(xmm7, xmm8); | 
|  | TestPmovsxdq(xmm8, xmm9); | 
|  | TestPmovsxdq(xmm9, xmm10); | 
|  | TestPmovsxdq(xmm10, xmm11); | 
|  | TestPmovsxdq(xmm11, xmm12); | 
|  | TestPmovsxdq(xmm12, xmm13); | 
|  | TestPmovsxdq(xmm13, xmm14); | 
|  | TestPmovsxdq(xmm14, xmm15); | 
|  | TestPmovsxdq(xmm15, xmm0); | 
|  |  | 
|  | #undef TestPmovsxdq | 
|  | #undef TestPmovsxdqXmmXmm | 
|  | } | 
|  |  | 
|  | } // end of anonymous namespace | 
|  | } // end of namespace Test | 
|  | } // end of namespace X8664 | 
|  | } // end of namespace Ice |