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