• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST_F(AssemblerX8632Test,MovRegImm)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 
TEST_F(AssemblerX8632Test,MovMemImm)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 
TEST_F(AssemblerX8632Test,MovMemReg)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 
TEST_F(AssemblerX8632Test,MovRegReg)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 
TEST_F(AssemblerX8632Test,MovRegMem)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 
TEST_F(AssemblerX8632Test,Movzx)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 
TEST_F(AssemblerX8632Test,Movsx)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 
TEST_F(AssemblerX8632LowLevelTest,RepMovsb)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 
TEST_F(AssemblerX8632Test,MovssXmmAddr)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 
TEST_F(AssemblerX8632Test,MovssAddrXmm)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 
TEST_F(AssemblerX8632Test,MovssXmmXmm)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 
TEST_F(AssemblerX8632Test,MovdToXmm)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 
TEST_F(AssemblerX8632Test,MovdFromXmm)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 
TEST_F(AssemblerX8632Test,MovqXmmAddr)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 
TEST_F(AssemblerX8632Test,MovqAddrXmm)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 
TEST_F(AssemblerX8632Test,MovqXmmXmm)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 
TEST_F(AssemblerX8632Test,MovupsXmmAddr)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 
TEST_F(AssemblerX8632Test,MovupsAddrXmm)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 
TEST_F(AssemblerX8632Test,MovupsXmmXmm)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 
TEST_F(AssemblerX8632Test,MovapsXmmXmm)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 
TEST_F(AssemblerX8632Test,Movhlps_Movlhps)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 
TEST_F(AssemblerX8632Test,Movmsk)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 
TEST_F(AssemblerX8632Test,Pmovsxdq)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 
TEST_F(AssemblerX8632Test,CmovRegReg)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 
TEST_F(AssemblerX8632Test,CmovRegAddr)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