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
11namespace Ice {
12namespace X8632 {
13namespace Test {
14namespace {
15
16TEST_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
41TEST_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
70TEST_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
107TEST_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
134TEST_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
176TEST_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
264TEST_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
356TEST_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
367TEST_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
416TEST_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
471TEST_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
531TEST_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
604TEST_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
676TEST_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
713TEST_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
750TEST_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
788TEST_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
818TEST_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
852TEST_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
887TEST_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
922TEST_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
967TEST_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
1005TEST_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
1054TEST_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
1122TEST_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