1 //===- subzero/unittest/AssemblerX8664/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 "AssemblerX8664/TestUtil.h"
10
11 namespace Ice {
12 namespace X8664 {
13 namespace Test {
14 namespace {
15
TEST_F(AssemblerX8664Test,MovRegImm)16 TEST_F(AssemblerX8664Test, MovRegImm) {
17 static constexpr uint32_t Mask8 = 0x000000FF;
18 static constexpr uint32_t Mask16 = 0x0000FFFF;
19 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
20
21 #define MovRegImm(Reg, Suffix, Size) \
22 do { \
23 static constexpr char TestString[] = "(" #Reg ", " #Size ")"; \
24 static constexpr uint32_t Value = (0xABCD7645) & Mask##Size; \
25 static constexpr uint32_t Marker = 0xBEEFFEEB; \
26 __ mov(IceType_i32, Encoded_GPR_##Reg##q(), Immediate(Marker)); \
27 __ mov(IceType_i##Size, Encoded_GPR_##Reg##Suffix(), Immediate(Value)); \
28 \
29 AssembledTest test = assemble(); \
30 test.run(); \
31 \
32 ASSERT_EQ(Value, test.Reg##Suffix()) << TestString; \
33 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.Reg##d()) << TestString; \
34 reset(); \
35 } while (0)
36
37 #define TestImpl(Reg) \
38 do { \
39 MovRegImm(Reg, l, 8); \
40 MovRegImm(Reg, w, 16); \
41 MovRegImm(Reg, d, 32); \
42 /* MovRegImm64 not implemented */ \
43 } while (0)
44
45 TestImpl(r1);
46 TestImpl(r2);
47 TestImpl(r3);
48 TestImpl(r4);
49 TestImpl(r5);
50 TestImpl(r6);
51 TestImpl(r7);
52 TestImpl(r8);
53 TestImpl(r10);
54 TestImpl(r11);
55 TestImpl(r12);
56 TestImpl(r13);
57 TestImpl(r14);
58 TestImpl(r15);
59
60 #undef TestImpl
61 #undef MovRegImm
62 }
63
TEST_F(AssemblerX8664Test,MovMemImm)64 TEST_F(AssemblerX8664Test, MovMemImm) {
65 const uint32_t T0 = allocateDword();
66 constexpr uint32_t ExpectedT0 = 0x00111100ul;
67 const uint32_t T1 = allocateDword();
68 constexpr uint32_t ExpectedT1 = 0x00222200ul;
69 const uint32_t T2 = allocateDword();
70 constexpr uint32_t ExpectedT2 = 0x03333000ul;
71 const uint32_t T3 = allocateDword();
72 constexpr uint32_t ExpectedT3 = 0x00444400ul;
73
74 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
75 __ mov(IceType_i16, dwordAddress(T1), Immediate(ExpectedT1));
76 __ mov(IceType_i8, dwordAddress(T2), Immediate(ExpectedT2));
77 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
78
79 AssembledTest test = assemble();
80 test.run();
81 EXPECT_EQ(0ul, test.eax());
82 EXPECT_EQ(0ul, test.ebx());
83 EXPECT_EQ(0ul, test.ecx());
84 EXPECT_EQ(0ul, test.edx());
85 EXPECT_EQ(0ul, test.edi());
86 EXPECT_EQ(0ul, test.esi());
87 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
88 EXPECT_EQ(ExpectedT1 & 0xFFFF, test.contentsOfDword(T1));
89 EXPECT_EQ(ExpectedT2 & 0xFF, test.contentsOfDword(T2));
90 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
91 }
92
TEST_F(AssemblerX8664Test,MovMemReg)93 TEST_F(AssemblerX8664Test, MovMemReg) {
94 static constexpr uint64_t Mask8 = 0x00000000000000FF;
95 static constexpr uint64_t Mask16 = 0x000000000000FFFF;
96 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFF;
97 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFF;
98
99 #define TestMemReg(Src, Size) \
100 do { \
101 static constexpr char TestString[] = "(" #Src ", " #Size ")"; \
102 static constexpr uint32_t Value = 0x1a4d567e & Mask##Size; \
103 static constexpr uint64_t Marker = 0xD0DA33EEBEEFFEEB; \
104 const uint32_t T0 = allocateQword(); \
105 \
106 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \
107 __ mov(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
108 \
109 AssembledTest test = assemble(); \
110 test.setQwordTo(T0, Marker); \
111 test.run(); \
112 \
113 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.contentsOfQword(T0)) \
114 << TestString; \
115 reset(); \
116 } while (0)
117
118 #define TestImpl(Src) \
119 do { \
120 TestMemReg(Src, 8); \
121 TestMemReg(Src, 16); \
122 TestMemReg(Src, 32); \
123 TestMemReg(Src, 64); \
124 } while (0)
125
126 TestImpl(r1);
127 TestImpl(r2);
128 TestImpl(r3);
129 TestImpl(r4);
130 TestImpl(r5);
131 TestImpl(r6);
132 TestImpl(r7);
133 TestImpl(r8);
134 TestImpl(r10);
135 TestImpl(r11);
136 TestImpl(r12);
137 TestImpl(r13);
138 TestImpl(r14);
139 TestImpl(r15);
140
141 #undef TestImpl
142 #undef TestMemReg
143 }
144
TEST_F(AssemblerX8664Test,MovRegReg)145 TEST_F(AssemblerX8664Test, MovRegReg) {
146 static constexpr uint64_t Mask8 = 0x00000000000000FFull;
147 static constexpr uint64_t Mask16 = 0x000000000000FFFFull;
148 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull;
149 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull;
150
151 static constexpr uint64_t MaskResult8 = 0x00000000000000FFull;
152 static constexpr uint64_t MaskResult16 = 0x000000000000FFFFull;
153 static constexpr uint64_t MaskResult32 = 0xFFFFFFFFFFFFFFFFull;
154 static constexpr uint64_t MaskResult64 = 0xFFFFFFFFFFFFFFFFull;
155
156 #define TestRegReg(Dst, Src, Suffix, Size) \
157 do { \
158 static constexpr char TestString[] = \
159 "(" #Dst ", " #Src ", " #Suffix ", " #Size ")"; \
160 const uint8_t T0 = allocateQword(); \
161 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \
162 const uint8_t T1 = allocateQword(); \
163 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \
164 \
165 __ mov(IceType_i64, Encoded_GPR_##Src(), dwordAddress(T0)); \
166 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \
167 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
168 \
169 AssembledTest test = assemble(); \
170 test.setQwordTo(T0, Value); \
171 test.setQwordTo(T1, Marker); \
172 test.run(); \
173 \
174 ASSERT_EQ((Marker & ~MaskResult##Size) | Value, test.Dst()) << TestString; \
175 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \
176 reset(); \
177 } while (0)
178
179 #define TestImpl(Dst, Src) \
180 do { \
181 TestRegReg(Dst, Src, l, 8); \
182 TestRegReg(Dst, Src, w, 16); \
183 TestRegReg(Dst, Src, d, 32); \
184 TestRegReg(Dst, Src, q, 64); \
185 } while (0)
186
187 TestImpl(r1, r2);
188 TestImpl(r2, r3);
189 TestImpl(r3, r4);
190 TestImpl(r4, r5);
191 TestImpl(r5, r6);
192 TestImpl(r6, r7);
193 TestImpl(r7, r8);
194 TestImpl(r8, r10);
195 TestImpl(r10, r11);
196 TestImpl(r11, r12);
197 TestImpl(r12, r13);
198 TestImpl(r13, r14);
199 TestImpl(r14, r15);
200 TestImpl(r15, r1);
201
202 #undef TestImpl
203 #undef TestRegReg
204 }
205
TEST_F(AssemblerX8664Test,MovRegMem)206 TEST_F(AssemblerX8664Test, MovRegMem) {
207 static constexpr uint64_t Mask8 = 0x00000000000000FFull;
208 static constexpr uint64_t Mask16 = 0x000000000000FFFFull;
209 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull;
210 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull;
211
212 static constexpr uint64_t MaskResult8 = ~0x00000000000000FFull;
213 static constexpr uint64_t MaskResult16 = ~0x000000000000FFFFull;
214 static constexpr uint64_t MaskResult32 = ~0xFFFFFFFFFFFFFFFFull;
215 static constexpr uint64_t MaskResult64 = ~0xFFFFFFFFFFFFFFFFull;
216
217 #define TestRegAddr(Dst, Suffix, Size) \
218 do { \
219 static constexpr char TestString[] = \
220 "(" #Dst ", Addr, " #Suffix ", " #Size ")"; \
221 const uint8_t T0 = allocateQword(); \
222 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \
223 const uint8_t T1 = allocateQword(); \
224 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \
225 \
226 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \
227 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
228 \
229 AssembledTest test = assemble(); \
230 test.setQwordTo(T0, Value); \
231 test.setQwordTo(T1, Marker); \
232 test.run(); \
233 \
234 ASSERT_EQ((Marker & MaskResult##Size) | Value, test.Dst()) << TestString; \
235 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \
236 reset(); \
237 } while (0)
238
239 #define TestImpl(Dst) \
240 do { \
241 TestRegAddr(Dst, l, 8); \
242 TestRegAddr(Dst, w, 16); \
243 TestRegAddr(Dst, d, 32); \
244 TestRegAddr(Dst, q, 64); \
245 } while (0)
246
247 TestImpl(r1);
248 TestImpl(r2);
249 TestImpl(r3);
250 TestImpl(r4);
251 TestImpl(r5);
252 TestImpl(r6);
253 TestImpl(r7);
254 TestImpl(r8);
255 TestImpl(r10);
256 TestImpl(r11);
257 TestImpl(r12);
258 TestImpl(r13);
259 TestImpl(r14);
260 TestImpl(r15);
261
262 #undef TestImpl
263 #undef TestRegAddr
264 }
265
TEST_F(AssemblerX8664Test,Movabs)266 TEST_F(AssemblerX8664Test, Movabs) {
267 #define TestImplValue(Dst, Value) \
268 do { \
269 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
270 uint64_t V = (Value); \
271 __ movabs(Encoded_GPR_##Dst##q(), V); \
272 \
273 AssembledTest test = assemble(); \
274 \
275 test.run(); \
276 \
277 ASSERT_EQ(V, test.DST()) << TestString; \
278 } while (0)
279
280 #define TestImpl(Dst) \
281 do { \
282 for (uint64_t V = {0, 1, 0xFFFFFFull, 0x80000000ull, \
283 0xFFFFFFFFFFFFFFFFull}) { \
284 TestImpl(Dst, V); \
285 } \
286 } while (0)
287
288 #undef TestImpl
289 #undef TestImplValue
290 }
291
TEST_F(AssemblerX8664Test,Movzx)292 TEST_F(AssemblerX8664Test, Movzx) {
293 static constexpr uint32_t Mask8 = 0x000000FF;
294 static constexpr uint32_t Mask16 = 0x0000FFFF;
295
296 #define TestImplRegReg(Dst, Src, Suffix, Size) \
297 do { \
298 const uint32_t T0 = allocateDqword(); \
299 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
300 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \
301 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
302 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \
303 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), \
304 Encoded_GPR_##Src##Suffix()); \
305 AssembledTest test = assemble(); \
306 test.setQwordTo(T0, V0); \
307 test.run(); \
308 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")"; \
309 reset(); \
310 } while (0)
311
312 #define TestImplRegAddr(Dst, Suffix, Size) \
313 do { \
314 const uint32_t T0 = allocateDqword(); \
315 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
316 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \
317 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \
318 \
319 AssembledTest test = assemble(); \
320 test.setQwordTo(T0, (V0 & ~Mask##Size) | Value); \
321 test.run(); \
322 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")"; \
323 reset(); \
324 } while (0)
325
326 #define TestImpl(Dst, Src) \
327 do { \
328 TestImplRegReg(Dst, Src, l, 8); \
329 TestImplRegAddr(Dst, l, 8); \
330 TestImplRegReg(Dst, Src, w, 16); \
331 TestImplRegAddr(Dst, w, 16); \
332 } while (0)
333
334 TestImpl(r1, r2);
335 TestImpl(r2, r3);
336 TestImpl(r3, r4);
337 TestImpl(r4, r5);
338 TestImpl(r5, r6);
339 TestImpl(r6, r7);
340 TestImpl(r7, r8);
341 TestImpl(r8, r10);
342 TestImpl(r10, r11);
343 TestImpl(r11, r12);
344 TestImpl(r12, r13);
345 TestImpl(r13, r14);
346 TestImpl(r14, r15);
347 TestImpl(r15, r1);
348
349 #undef TestImpl
350 #undef TestImplRegAddr
351 #undef TestImplRegReg
352 }
353
TEST_F(AssemblerX8664Test,Movsx)354 TEST_F(AssemblerX8664Test, Movsx) {
355 static constexpr uint64_t Mask8 = 0x000000FF;
356 static constexpr uint64_t Mask16 = 0x0000FFFF;
357 static constexpr uint64_t Mask32 = 0xFFFFFFFF;
358
359 #define TestImplRegReg(Dst, Src, Suffix, Size) \
360 do { \
361 const uint32_t T0 = allocateDqword(); \
362 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
363 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \
364 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
365 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \
366 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), \
367 Encoded_GPR_##Src##Suffix()); \
368 AssembledTest test = assemble(); \
369 test.setQwordTo(T0, V0); \
370 test.run(); \
371 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \
372 << "(" #Dst ", " #Src ", " #Size ")"; \
373 reset(); \
374 } while (0)
375
376 #define TestImplRegAddr(Dst, Suffix, Size) \
377 do { \
378 const uint32_t T0 = allocateDqword(); \
379 static constexpr uint64_t V0 = 0xC0BEBEEF & Mask##Size; \
380 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \
381 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \
382 \
383 AssembledTest test = assemble(); \
384 test.setQwordTo(T0, V0); \
385 test.run(); \
386 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \
387 << "(" #Dst ", Addr, " #Size ")"; \
388 reset(); \
389 } while (0)
390
391 #define TestImpl(Dst, Src) \
392 do { \
393 TestImplRegReg(Dst, Src, l, 8); \
394 TestImplRegAddr(Dst, l, 8); \
395 TestImplRegReg(Dst, Src, w, 16); \
396 TestImplRegAddr(Dst, w, 16); \
397 TestImplRegReg(Dst, Src, w, 32); \
398 TestImplRegAddr(Dst, w, 32); \
399 } while (0)
400
401 TestImpl(r1, r2);
402 TestImpl(r2, r3);
403 TestImpl(r3, r4);
404 TestImpl(r4, r5);
405 TestImpl(r5, r6);
406 TestImpl(r6, r7);
407 TestImpl(r7, r8);
408 TestImpl(r8, r10);
409 TestImpl(r10, r11);
410 TestImpl(r11, r12);
411 TestImpl(r12, r13);
412 TestImpl(r13, r14);
413 TestImpl(r14, r15);
414 TestImpl(r15, r1);
415
416 #undef TestImpl
417 #undef TestImplRegAddr
418 #undef TestImplRegReg
419 }
420
TEST_F(AssemblerX8664Test,Cmov)421 TEST_F(AssemblerX8664Test, Cmov) {
422 #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
423 do { \
424 static constexpr char TestString[] = \
425 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \
426 ", " #Value1 ")"; \
427 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
428 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
429 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
430 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
431 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
432 Encoded_GPR_##Src1()); \
433 \
434 AssembledTest test = assemble(); \
435 test.run(); \
436 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
437 \
438 reset(); \
439 } while (0)
440
441 #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1) \
442 do { \
443 static constexpr char TestString[] = \
444 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 \
445 ", Addr, " #Value1 ")"; \
446 const uint32_t T0 = allocateDword(); \
447 const uint32_t V0 = Value1; \
448 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
449 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
450 __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0)); \
451 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
452 dwordAddress(T0)); \
453 \
454 AssembledTest test = assemble(); \
455 test.setDwordTo(T0, V0); \
456 test.run(); \
457 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
458 \
459 reset(); \
460 } while (0)
461
462 #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
463 do { \
464 TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1); \
465 TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1); \
466 } while (0)
467
468 #define TestImpl(Dest, Src0, Src1) \
469 do { \
470 TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
471 TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \
472 TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \
473 TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
474 TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \
475 TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
476 TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
477 TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
478 TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \
479 TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \
480 TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
481 TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \
482 TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
483 TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
484 TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
485 TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
486 TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
487 TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
488 TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
489 TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
490 TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
491 TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
492 TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
493 TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
494 TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
495 TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
496 TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
497 TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
498 TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
499 TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
500 } while (0)
501
502 TestImpl(r1, r2, r3);
503
504 #undef TestImpl
505 #undef TestValue
506 #undef TestRegAddr
507 #undef TestRegReg
508 }
509
TEST_F(AssemblerX8664LowLevelTest,RepMovsb)510 TEST_F(AssemblerX8664LowLevelTest, RepMovsb) {
511 __ rep_movsb();
512
513 static constexpr uint32_t ByteCount = 2;
514 static constexpr uint8_t Prefix = 0xF3;
515 static constexpr uint8_t Opcode = 0xA4;
516
517 ASSERT_EQ(ByteCount, codeBytesSize());
518 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode);
519 }
520
TEST_F(AssemblerX8664Test,MovssXmmAddr)521 TEST_F(AssemblerX8664Test, MovssXmmAddr) {
522 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \
523 do { \
524 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
525 "Invalid fp length #FloatLength"); \
526 using Type = std::conditional<FloatLength == 32, float, double>::type; \
527 \
528 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
529 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
530 const uint32_t T0 = allocateQword(); \
531 const Type V0 = Value; \
532 \
533 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
534 \
535 AssembledTest test = assemble(); \
536 if (IsDouble) { \
537 test.setQwordTo(T0, static_cast<double>(V0)); \
538 } else { \
539 test.setDwordTo(T0, static_cast<float>(V0)); \
540 } \
541 test.run(); \
542 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
543 << Value; \
544 reset(); \
545 } while (0)
546
547 #define TestMovssXmmAddr(FloatLength) \
548 do { \
549 using Type = std::conditional<FloatLength == 32, float, double>::type; \
550 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
551 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \
552 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \
553 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \
554 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \
555 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \
556 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \
557 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \
558 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \
559 TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value); \
560 TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value); \
561 TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value); \
562 TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value); \
563 TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value); \
564 TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value); \
565 TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value); \
566 TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value); \
567 } \
568 } while (0)
569
570 TestMovssXmmAddr(32);
571 TestMovssXmmAddr(64);
572
573 #undef TestMovssXmmAddr
574 #undef TestMovssXmmAddrType
575 }
576
TEST_F(AssemblerX8664Test,MovssAddrXmm)577 TEST_F(AssemblerX8664Test, MovssAddrXmm) {
578 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \
579 do { \
580 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
581 "Invalid fp length #FloatLength"); \
582 using Type = std::conditional<FloatLength == 32, float, double>::type; \
583 \
584 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
585 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
586 const uint32_t T0 = allocateQword(); \
587 const Type V0 = Value; \
588 const uint32_t T1 = allocateQword(); \
589 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
590 "f" #FloatLength " does not have quiet nan."); \
591 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
592 \
593 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
594 \
595 AssembledTest test = assemble(); \
596 if (IsDouble) { \
597 test.setQwordTo(T0, static_cast<double>(V0)); \
598 test.setQwordTo(T1, static_cast<double>(V1)); \
599 } else { \
600 test.setDwordTo(T0, static_cast<float>(V0)); \
601 test.setDwordTo(T1, static_cast<float>(V1)); \
602 } \
603 test.run(); \
604 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
605 << Value; \
606 reset(); \
607 } while (0)
608
609 #define TestMovssAddrXmm(FloatLength) \
610 do { \
611 using Type = std::conditional<FloatLength == 32, float, double>::type; \
612 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
613 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \
614 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \
615 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \
616 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \
617 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \
618 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \
619 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \
620 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \
621 TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value); \
622 TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value); \
623 TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value); \
624 TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value); \
625 TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value); \
626 TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value); \
627 TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value); \
628 TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value); \
629 } \
630 } while (0)
631
632 TestMovssAddrXmm(32);
633 TestMovssAddrXmm(64);
634
635 #undef TestMovssAddrXmm
636 #undef TestMovssAddrXmmType
637 }
638
TEST_F(AssemblerX8664Test,MovssXmmXmm)639 TEST_F(AssemblerX8664Test, MovssXmmXmm) {
640 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \
641 do { \
642 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
643 "Invalid fp length #FloatLength"); \
644 using Type = std::conditional<FloatLength == 32, float, double>::type; \
645 \
646 static constexpr char TestString[] = \
647 "(" #FloatLength ", " #Src ", " #Dst ")"; \
648 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
649 const uint32_t T0 = allocateQword(); \
650 const Type V0 = Value; \
651 const uint32_t T1 = allocateQword(); \
652 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
653 "f" #FloatLength " does not have quiet nan."); \
654 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
655 \
656 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0)); \
657 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
658 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), \
659 Encoded_Xmm_##Src()); \
660 \
661 AssembledTest test = assemble(); \
662 if (IsDouble) { \
663 test.setQwordTo(T0, static_cast<double>(V0)); \
664 test.setQwordTo(T1, static_cast<double>(V1)); \
665 } else { \
666 test.setDwordTo(T0, static_cast<float>(V0)); \
667 test.setDwordTo(T1, static_cast<float>(V1)); \
668 } \
669 test.run(); \
670 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \
671 << Value; \
672 reset(); \
673 } while (0)
674
675 #define TestMovssXmmXmm(FloatLength) \
676 do { \
677 using Type = std::conditional<FloatLength == 32, float, double>::type; \
678 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
679 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \
680 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \
681 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \
682 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \
683 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \
684 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \
685 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \
686 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value); \
687 TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value); \
688 TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value); \
689 TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value); \
690 TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value); \
691 TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value); \
692 TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value); \
693 TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value); \
694 TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value); \
695 } \
696 } while (0)
697
698 TestMovssXmmXmm(32);
699 TestMovssXmmXmm(64);
700
701 #undef TestMovssXmmXmm
702 #undef TestMovssXmmXmmType
703 }
704
TEST_F(AssemblerX8664Test,MovdToXmm)705 TEST_F(AssemblerX8664Test, MovdToXmm) {
706 #define TestMovdXmmReg32(Src, Dst, Value) \
707 do { \
708 assert(((Value)&0xFFFFFFFF) == (Value)); \
709 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
710 const uint32_t T0 = allocateQword(); \
711 const uint64_t V0 = 0xFFFFFFFF00000000ull; \
712 \
713 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \
714 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
715 __ movd(IceType_i32, Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \
716 \
717 AssembledTest test = assemble(); \
718 \
719 test.setQwordTo(T0, V0); \
720 test.run(); \
721 \
722 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
723 << Value; \
724 reset(); \
725 } while (0)
726
727 #define TestMovdXmmReg64(Src, Dst, Value) \
728 do { \
729 assert(((Value)&0xFFFFFFFF) == (Value)); \
730 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
731 const uint32_t T0 = allocateQword(); \
732 const uint64_t V0 = 0xFFFFFFFF00000000ull; \
733 const uint64_t Expected = (static_cast<uint64_t>(Value) << 32) | (Value); \
734 \
735 __ movabs(Encoded_GPR_##Src(), Expected); \
736 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
737 __ movd(IceType_i64, Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \
738 \
739 AssembledTest test = assemble(); \
740 \
741 test.setQwordTo(T0, V0); \
742 test.run(); \
743 \
744 ASSERT_EQ(Expected, test.Dst<uint64_t>()) << TestString << " value is " \
745 << Value; \
746 reset(); \
747 } while (0)
748
749 #define TestMovdXmmReg(Src, Dst, Value) \
750 do { \
751 TestMovdXmmReg32(Src, Dst, Value); \
752 TestMovdXmmReg64(Src, Dst, Value); \
753 } while (0)
754
755 #define TestMovdXmmAddr32(Dst, Value) \
756 do { \
757 assert(((Value)&0xFFFFFFFF) == (Value)); \
758 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
759 const uint32_t T0 = allocateQword(); \
760 const uint32_t V0 = Value; \
761 const uint32_t T1 = allocateQword(); \
762 const uint64_t V1 = 0xFFFFFFFF00000000ull; \
763 \
764 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
765 __ movd(IceType_i32, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
766 \
767 AssembledTest test = assemble(); \
768 \
769 test.setDwordTo(T0, V0); \
770 test.setQwordTo(T1, V1); \
771 test.run(); \
772 \
773 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
774 << Value; \
775 reset(); \
776 } while (0)
777
778 #define TestMovdXmmAddr64(Dst, Value) \
779 do { \
780 assert(((Value)&0xFFFFFFFF) == (Value)); \
781 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
782 const uint32_t T0 = allocateQword(); \
783 const uint32_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value); \
784 const uint32_t T1 = allocateQword(); \
785 const uint64_t V1 = 0xFFFFFFFF00000000ull; \
786 \
787 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
788 __ movd(IceType_i64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
789 \
790 AssembledTest test = assemble(); \
791 \
792 test.setDwordTo(T0, V0); \
793 test.setQwordTo(T1, V1); \
794 test.run(); \
795 \
796 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
797 << Value; \
798 reset(); \
799 } while (0)
800
801 #define TestMovdXmmAddr(Dst, Value) \
802 do { \
803 TestMovdXmmAddr32(Dst, Value); \
804 TestMovdXmmAddr64(Dst, Value); \
805 } while (0)
806
807 #define TestMovd(Dst) \
808 do { \
809 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
810 TestMovdXmmReg(r1, Dst, Value); \
811 TestMovdXmmReg(r2, Dst, Value); \
812 TestMovdXmmReg(r3, Dst, Value); \
813 TestMovdXmmReg(r4, Dst, Value); \
814 TestMovdXmmReg(r5, Dst, Value); \
815 TestMovdXmmReg(r6, Dst, Value); \
816 TestMovdXmmReg(r7, Dst, Value); \
817 TestMovdXmmReg(r8, Dst, Value); \
818 TestMovdXmmReg(r10, Dst, Value); \
819 TestMovdXmmReg(r11, Dst, Value); \
820 TestMovdXmmReg(r12, Dst, Value); \
821 TestMovdXmmReg(r13, Dst, Value); \
822 TestMovdXmmReg(r14, Dst, Value); \
823 TestMovdXmmReg(r15, Dst, Value); \
824 TestMovdXmmAddr(Dst, Value); \
825 } \
826 } while (0)
827
828 TestMovd(xmm0);
829 TestMovd(xmm1);
830 TestMovd(xmm2);
831 TestMovd(xmm3);
832 TestMovd(xmm4);
833 TestMovd(xmm5);
834 TestMovd(xmm6);
835 TestMovd(xmm7);
836 TestMovd(xmm8);
837 TestMovd(xmm9);
838 TestMovd(xmm10);
839 TestMovd(xmm11);
840 TestMovd(xmm12);
841 TestMovd(xmm13);
842 TestMovd(xmm14);
843 TestMovd(xmm15);
844
845 #undef TestMovd
846 #undef TestMovdXmmAddr
847 #undef TestMovdXmmAddr64
848 #undef TestMovdXmmAddr32
849 #undef TestMovdXmmReg
850 #undef TestMovdXmmReg64
851 #undef TestMovdXmmReg32
852 }
853
TEST_F(AssemblerX8664Test,MovdFromXmm)854 TEST_F(AssemblerX8664Test, MovdFromXmm) {
855 #define TestMovdRegXmm32(Src, Dst, Value) \
856 do { \
857 assert(((Value)&0xFFFFFFFF) == (Value)); \
858 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
859 const uint32_t T0 = allocateDword(); \
860 const uint32_t V0 = Value; \
861 \
862 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
863 __ movd(IceType_i32, Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \
864 \
865 AssembledTest test = assemble(); \
866 \
867 test.setDwordTo(T0, V0); \
868 test.run(); \
869 \
870 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \
871 << Value; \
872 reset(); \
873 } while (0)
874
875 #define TestMovdRegXmm64(Src, Dst, Value) \
876 do { \
877 assert(((Value)&0xFFFFFFFF) == (Value)); \
878 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
879 const uint32_t T0 = allocateDword(); \
880 const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | (Value); \
881 \
882 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
883 __ movd(IceType_i64, Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \
884 \
885 AssembledTest test = assemble(); \
886 \
887 test.setQwordTo(T0, V0); \
888 test.run(); \
889 \
890 ASSERT_EQ(V0, test.contentsOfQword(T0)) << TestString << " value is " \
891 << Value; \
892 reset(); \
893 } while (0)
894
895 #define TestMovdRegXmm(Src, Dst, Value) \
896 do { \
897 TestMovdRegXmm32(Src, Dst, Value); \
898 TestMovdRegXmm64(Src, Dst, Value); \
899 } while (0)
900
901 #define TestMovdAddrXmm32(Src, Value) \
902 do { \
903 assert(((Value)&0xFFFFFFFF) == (Value)); \
904 static constexpr char TestString[] = "(" #Src ", Addr)"; \
905 const uint32_t T0 = allocateDword(); \
906 const uint32_t V0 = Value; \
907 const uint32_t T1 = allocateDword(); \
908 const uint32_t V1 = ~(Value); \
909 \
910 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
911 __ movd(IceType_i32, dwordAddress(T1), Encoded_Xmm_##Src()); \
912 \
913 AssembledTest test = assemble(); \
914 \
915 test.setDwordTo(T0, V0); \
916 test.setDwordTo(T1, V1); \
917 test.run(); \
918 \
919 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \
920 << Value; \
921 reset(); \
922 } while (0)
923
924 #define TestMovdAddrXmm64(Src, Value) \
925 do { \
926 assert(((Value)&0xFFFFFFFF) == (Value)); \
927 static constexpr char TestString[] = "(" #Src ", Addr)"; \
928 const uint32_t T0 = allocateQword(); \
929 const uint64_t V0 = (static_cast<uint64_t>(Value) << 32) | Value; \
930 const uint32_t T1 = allocateQword(); \
931 const uint64_t V1 = ~V0; \
932 \
933 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
934 __ movd(IceType_i64, dwordAddress(T1), Encoded_Xmm_##Src()); \
935 \
936 AssembledTest test = assemble(); \
937 \
938 test.setQwordTo(T0, V0); \
939 test.setQwordTo(T1, V1); \
940 test.run(); \
941 \
942 ASSERT_EQ(V0, test.contentsOfQword(T1)) << TestString << " value is " \
943 << Value; \
944 reset(); \
945 } while (0)
946
947 #define TestMovdAddrXmm(Src, Value) \
948 do { \
949 TestMovdAddrXmm32(Src, Value); \
950 TestMovdAddrXmm64(Src, Value); \
951 } while (0)
952
953 #define TestMovd(Src) \
954 do { \
955 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
956 TestMovdRegXmm(Src, r1, Value); \
957 TestMovdRegXmm(Src, r2, Value); \
958 TestMovdRegXmm(Src, r3, Value); \
959 TestMovdRegXmm(Src, r4, Value); \
960 TestMovdRegXmm(Src, r5, Value); \
961 TestMovdRegXmm(Src, r6, Value); \
962 TestMovdRegXmm(Src, r7, Value); \
963 TestMovdRegXmm(Src, r8, Value); \
964 TestMovdRegXmm(Src, r10, Value); \
965 TestMovdRegXmm(Src, r11, Value); \
966 TestMovdRegXmm(Src, r12, Value); \
967 TestMovdRegXmm(Src, r13, Value); \
968 TestMovdRegXmm(Src, r14, Value); \
969 TestMovdRegXmm(Src, r15, Value); \
970 TestMovdAddrXmm(Src, Value); \
971 } \
972 } while (0)
973
974 TestMovd(xmm0);
975 TestMovd(xmm1);
976 TestMovd(xmm2);
977 TestMovd(xmm3);
978 TestMovd(xmm4);
979 TestMovd(xmm5);
980 TestMovd(xmm6);
981 TestMovd(xmm7);
982 TestMovd(xmm8);
983 TestMovd(xmm9);
984 TestMovd(xmm10);
985 TestMovd(xmm11);
986 TestMovd(xmm12);
987 TestMovd(xmm13);
988 TestMovd(xmm14);
989 TestMovd(xmm15);
990
991 #undef TestMovd
992 #undef TestMovdAddrXmm
993 #undef TestMovdAddrXmm64
994 #undef TestMovdAddrXmm32
995 #undef TestMovdRegXmm
996 #undef TestMovdRegXmm64
997 #undef TestMovdRegXmm32
998 }
999
TEST_F(AssemblerX8664Test,MovqXmmAddr)1000 TEST_F(AssemblerX8664Test, MovqXmmAddr) {
1001 #define TestMovd(Dst, Value) \
1002 do { \
1003 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
1004 const uint32_t T0 = allocateQword(); \
1005 const uint64_t V0 = Value; \
1006 const uint32_t T1 = allocateQword(); \
1007 const uint64_t V1 = ~(Value); \
1008 \
1009 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
1010 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
1011 \
1012 AssembledTest test = assemble(); \
1013 \
1014 test.setQwordTo(T0, V0); \
1015 test.setQwordTo(T1, V1); \
1016 test.run(); \
1017 \
1018 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
1019 << Value; \
1020 reset(); \
1021 } while (0)
1022
1023 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
1024 TestMovd(xmm0, Value);
1025 TestMovd(xmm1, Value);
1026 TestMovd(xmm2, Value);
1027 TestMovd(xmm3, Value);
1028 TestMovd(xmm4, Value);
1029 TestMovd(xmm5, Value);
1030 TestMovd(xmm6, Value);
1031 TestMovd(xmm7, Value);
1032 TestMovd(xmm8, Value);
1033 TestMovd(xmm9, Value);
1034 TestMovd(xmm10, Value);
1035 TestMovd(xmm11, Value);
1036 TestMovd(xmm12, Value);
1037 TestMovd(xmm13, Value);
1038 TestMovd(xmm14, Value);
1039 TestMovd(xmm15, Value);
1040 }
1041
1042 #undef TestMovd
1043 }
1044
TEST_F(AssemblerX8664Test,MovqAddrXmm)1045 TEST_F(AssemblerX8664Test, MovqAddrXmm) {
1046 #define TestMovd(Dst, Value) \
1047 do { \
1048 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
1049 const uint32_t T0 = allocateQword(); \
1050 const uint64_t V0 = Value; \
1051 const uint32_t T1 = allocateQword(); \
1052 const uint64_t V1 = ~(Value); \
1053 \
1054 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
1055 __ movq(dwordAddress(T1), Encoded_Xmm_##Dst()); \
1056 \
1057 AssembledTest test = assemble(); \
1058 \
1059 test.setQwordTo(T0, V0); \
1060 test.setQwordTo(T1, V1); \
1061 test.run(); \
1062 \
1063 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
1064 << Value; \
1065 reset(); \
1066 } while (0)
1067
1068 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
1069 TestMovd(xmm0, Value);
1070 TestMovd(xmm1, Value);
1071 TestMovd(xmm2, Value);
1072 TestMovd(xmm3, Value);
1073 TestMovd(xmm4, Value);
1074 TestMovd(xmm5, Value);
1075 TestMovd(xmm6, Value);
1076 TestMovd(xmm7, Value);
1077 TestMovd(xmm8, Value);
1078 TestMovd(xmm9, Value);
1079 TestMovd(xmm10, Value);
1080 TestMovd(xmm11, Value);
1081 TestMovd(xmm12, Value);
1082 TestMovd(xmm13, Value);
1083 TestMovd(xmm14, Value);
1084 TestMovd(xmm15, Value);
1085 }
1086
1087 #undef TestMovd
1088 }
1089
TEST_F(AssemblerX8664Test,MovqXmmXmm)1090 TEST_F(AssemblerX8664Test, MovqXmmXmm) {
1091 #define TestMovd(Src, Dst, Value) \
1092 do { \
1093 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
1094 const uint32_t T0 = allocateQword(); \
1095 const uint64_t V0 = Value; \
1096 const uint32_t T1 = allocateQword(); \
1097 const uint64_t V1 = ~(Value); \
1098 \
1099 __ movq(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1100 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
1101 __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
1102 \
1103 AssembledTest test = assemble(); \
1104 \
1105 test.setQwordTo(T0, V0); \
1106 test.setQwordTo(T1, V1); \
1107 test.run(); \
1108 \
1109 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
1110 << Value; \
1111 reset(); \
1112 } while (0)
1113
1114 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
1115 TestMovd(xmm0, xmm1, Value);
1116 TestMovd(xmm1, xmm2, Value);
1117 TestMovd(xmm2, xmm3, Value);
1118 TestMovd(xmm3, xmm4, Value);
1119 TestMovd(xmm4, xmm5, Value);
1120 TestMovd(xmm5, xmm6, Value);
1121 TestMovd(xmm6, xmm7, Value);
1122 TestMovd(xmm7, xmm8, Value);
1123 TestMovd(xmm8, xmm9, Value);
1124 TestMovd(xmm9, xmm10, Value);
1125 TestMovd(xmm10, xmm11, Value);
1126 TestMovd(xmm11, xmm12, Value);
1127 TestMovd(xmm12, xmm13, Value);
1128 TestMovd(xmm13, xmm14, Value);
1129 TestMovd(xmm14, xmm15, Value);
1130 TestMovd(xmm15, xmm0, Value);
1131 }
1132
1133 #undef TestMovd
1134 }
1135
TEST_F(AssemblerX8664Test,MovupsXmmAddr)1136 TEST_F(AssemblerX8664Test, MovupsXmmAddr) {
1137 #define TestMovups(Dst) \
1138 do { \
1139 static constexpr char TestString[] = "(" #Dst ")"; \
1140 const uint32_t T0 = allocateDqword(); \
1141 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
1142 std::numeric_limits<float>::infinity()); \
1143 \
1144 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
1145 \
1146 AssembledTest test = assemble(); \
1147 test.setDqwordTo(T0, V0); \
1148 test.run(); \
1149 \
1150 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
1151 reset(); \
1152 } while (0)
1153
1154 TestMovups(xmm0);
1155 TestMovups(xmm1);
1156 TestMovups(xmm2);
1157 TestMovups(xmm3);
1158 TestMovups(xmm4);
1159 TestMovups(xmm5);
1160 TestMovups(xmm6);
1161 TestMovups(xmm7);
1162 TestMovups(xmm8);
1163 TestMovups(xmm9);
1164 TestMovups(xmm10);
1165 TestMovups(xmm11);
1166 TestMovups(xmm12);
1167 TestMovups(xmm13);
1168 TestMovups(xmm14);
1169 TestMovups(xmm15);
1170
1171 #undef TestMovups
1172 }
1173
TEST_F(AssemblerX8664Test,MovupsAddrXmm)1174 TEST_F(AssemblerX8664Test, MovupsAddrXmm) {
1175 #define TestMovups(Src) \
1176 do { \
1177 static constexpr char TestString[] = "(" #Src ")"; \
1178 const uint32_t T0 = allocateDqword(); \
1179 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
1180 std::numeric_limits<float>::infinity()); \
1181 const uint32_t T1 = allocateDqword(); \
1182 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
1183 \
1184 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1185 __ movups(dwordAddress(T1), Encoded_Xmm_##Src()); \
1186 \
1187 AssembledTest test = assemble(); \
1188 test.setDqwordTo(T0, V0); \
1189 test.setDqwordTo(T1, V1); \
1190 test.run(); \
1191 \
1192 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \
1193 reset(); \
1194 } while (0)
1195
1196 TestMovups(xmm0);
1197 TestMovups(xmm1);
1198 TestMovups(xmm2);
1199 TestMovups(xmm3);
1200 TestMovups(xmm4);
1201 TestMovups(xmm5);
1202 TestMovups(xmm6);
1203 TestMovups(xmm7);
1204 TestMovups(xmm8);
1205 TestMovups(xmm9);
1206 TestMovups(xmm10);
1207 TestMovups(xmm11);
1208 TestMovups(xmm12);
1209 TestMovups(xmm13);
1210 TestMovups(xmm14);
1211 TestMovups(xmm15);
1212
1213 #undef TestMovups
1214 }
1215
TEST_F(AssemblerX8664Test,MovupsXmmXmm)1216 TEST_F(AssemblerX8664Test, MovupsXmmXmm) {
1217 #define TestMovups(Dst, Src) \
1218 do { \
1219 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
1220 const uint32_t T0 = allocateDqword(); \
1221 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
1222 std::numeric_limits<float>::infinity()); \
1223 const uint32_t T1 = allocateDqword(); \
1224 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
1225 \
1226 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1227 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
1228 __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
1229 \
1230 AssembledTest test = assemble(); \
1231 test.setDqwordTo(T0, V0); \
1232 test.setDqwordTo(T1, V1); \
1233 test.run(); \
1234 \
1235 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
1236 reset(); \
1237 } while (0)
1238
1239 TestMovups(xmm0, xmm1);
1240 TestMovups(xmm1, xmm2);
1241 TestMovups(xmm2, xmm3);
1242 TestMovups(xmm3, xmm4);
1243 TestMovups(xmm4, xmm5);
1244 TestMovups(xmm5, xmm6);
1245 TestMovups(xmm6, xmm7);
1246 TestMovups(xmm7, xmm8);
1247 TestMovups(xmm8, xmm9);
1248 TestMovups(xmm9, xmm10);
1249 TestMovups(xmm10, xmm11);
1250 TestMovups(xmm11, xmm12);
1251 TestMovups(xmm12, xmm13);
1252 TestMovups(xmm13, xmm14);
1253 TestMovups(xmm14, xmm15);
1254 TestMovups(xmm15, xmm0);
1255
1256 #undef TestMovups
1257 }
1258
TEST_F(AssemblerX8664Test,MovapsXmmXmm)1259 TEST_F(AssemblerX8664Test, MovapsXmmXmm) {
1260 #define TestMovaps(Dst, Src) \
1261 do { \
1262 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
1263 const uint32_t T0 = allocateDqword(); \
1264 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
1265 std::numeric_limits<float>::infinity()); \
1266 const uint32_t T1 = allocateDqword(); \
1267 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
1268 \
1269 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1270 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
1271 __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
1272 \
1273 AssembledTest test = assemble(); \
1274 test.setDqwordTo(T0, V0); \
1275 test.setDqwordTo(T1, V1); \
1276 test.run(); \
1277 \
1278 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
1279 reset(); \
1280 } while (0)
1281
1282 TestMovaps(xmm0, xmm1);
1283 TestMovaps(xmm1, xmm2);
1284 TestMovaps(xmm2, xmm3);
1285 TestMovaps(xmm3, xmm4);
1286 TestMovaps(xmm4, xmm5);
1287 TestMovaps(xmm5, xmm6);
1288 TestMovaps(xmm6, xmm7);
1289 TestMovaps(xmm7, xmm8);
1290 TestMovaps(xmm8, xmm9);
1291 TestMovaps(xmm9, xmm10);
1292 TestMovaps(xmm10, xmm11);
1293 TestMovaps(xmm11, xmm12);
1294 TestMovaps(xmm12, xmm13);
1295 TestMovaps(xmm13, xmm14);
1296 TestMovaps(xmm14, xmm15);
1297 TestMovaps(xmm15, xmm0);
1298
1299 #undef TestMovaps
1300 }
1301
TEST_F(AssemblerX8664Test,Movhlps_Movlhps)1302 TEST_F(AssemblerX8664Test, Movhlps_Movlhps) {
1303 #define TestImplSingle(Dst, Src, Inst, Expect) \
1304 do { \
1305 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
1306 const uint32_t T0 = allocateDqword(); \
1307 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \
1308 uint64_t(0xCCCCCCCCDDDDDDDDull)); \
1309 const uint32_t T1 = allocateDqword(); \
1310 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \
1311 uint64_t(0x9999999988888888ull)); \
1312 \
1313 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
1314 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
1315 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
1316 \
1317 AssembledTest test = assemble(); \
1318 test.setDqwordTo(T0, V0); \
1319 test.setDqwordTo(T1, V1); \
1320 test.run(); \
1321 \
1322 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
1323 reset(); \
1324 } while (0)
1325
1326 #define TestImpl(Dst, Src) \
1327 do { \
1328 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \
1329 uint64_t(0xCCCCCCCCDDDDDDDDull))); \
1330 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \
1331 uint64_t(0xEEEEEEEEFFFFFFFFull))); \
1332 } while (0)
1333
1334 TestImpl(xmm0, xmm1);
1335 TestImpl(xmm1, xmm2);
1336 TestImpl(xmm2, xmm3);
1337 TestImpl(xmm3, xmm4);
1338 TestImpl(xmm4, xmm5);
1339 TestImpl(xmm5, xmm6);
1340 TestImpl(xmm6, xmm7);
1341 TestImpl(xmm7, xmm8);
1342 TestImpl(xmm8, xmm9);
1343 TestImpl(xmm9, xmm10);
1344 TestImpl(xmm10, xmm11);
1345 TestImpl(xmm11, xmm12);
1346 TestImpl(xmm12, xmm13);
1347 TestImpl(xmm13, xmm14);
1348 TestImpl(xmm14, xmm15);
1349 TestImpl(xmm15, xmm0);
1350
1351 #undef TestImpl
1352 #undef TestImplSingle
1353 }
1354
TEST_F(AssemblerX8664Test,Movmsk)1355 TEST_F(AssemblerX8664Test, Movmsk) {
1356 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \
1357 do { \
1358 static constexpr char TestString[] = \
1359 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \
1360 const uint32_t T0 = allocateDqword(); \
1361 const Dqword V0 Value1; \
1362 \
1363 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1364 __ Inst(IceType_v4f32, Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \
1365 \
1366 AssembledTest test = assemble(); \
1367 test.setDqwordTo(T0, V0); \
1368 test.run(); \
1369 \
1370 ASSERT_EQ(Expected, test.GPR()) << TestString; \
1371 reset(); \
1372 } while (0)
1373
1374 #define TestMovmsk(GPR, Src) \
1375 do { \
1376 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmsk); \
1377 } while (0)
1378
1379 TestMovmsk(r1, xmm0);
1380 TestMovmsk(r2, xmm1);
1381 TestMovmsk(r3, xmm2);
1382 TestMovmsk(r4, xmm3);
1383 TestMovmsk(r5, xmm4);
1384 TestMovmsk(r6, xmm5);
1385 TestMovmsk(r7, xmm6);
1386 TestMovmsk(r8, xmm7);
1387 TestMovmsk(r10, xmm8);
1388 TestMovmsk(r11, xmm9);
1389 TestMovmsk(r12, xmm10);
1390 TestMovmsk(r13, xmm11);
1391 TestMovmsk(r14, xmm12);
1392 TestMovmsk(r15, xmm13);
1393 TestMovmsk(r1, xmm14);
1394 TestMovmsk(r2, xmm15);
1395
1396 #undef TestMovmskGPRXmm
1397 #undef TestMovmsk
1398 }
1399
TEST_F(AssemblerX8664Test,Pmovsxdq)1400 TEST_F(AssemblerX8664Test, Pmovsxdq) {
1401 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \
1402 do { \
1403 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \
1404 const uint32_t T0 = allocateDqword(); \
1405 const Dqword V0 Value1; \
1406 const uint32_t T1 = allocateDqword(); \
1407 const Dqword V1(uint64_t(0), uint64_t(0)); \
1408 \
1409 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
1410 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
1411 __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
1412 \
1413 AssembledTest test = assemble(); \
1414 test.setDqwordTo(T0, V0); \
1415 test.setDqwordTo(T1, V1); \
1416 test.run(); \
1417 \
1418 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \
1419 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1420 reset(); \
1421 } while (0)
1422
1423 #define TestPmovsxdq(Dst, Src) \
1424 do { \
1425 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \
1426 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
1427 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \
1428 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
1429 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \
1430 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
1431 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \
1432 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
1433 } while (0)
1434
1435 TestPmovsxdq(xmm0, xmm1);
1436 TestPmovsxdq(xmm1, xmm2);
1437 TestPmovsxdq(xmm2, xmm3);
1438 TestPmovsxdq(xmm3, xmm4);
1439 TestPmovsxdq(xmm4, xmm5);
1440 TestPmovsxdq(xmm5, xmm6);
1441 TestPmovsxdq(xmm6, xmm7);
1442 TestPmovsxdq(xmm7, xmm8);
1443 TestPmovsxdq(xmm8, xmm9);
1444 TestPmovsxdq(xmm9, xmm10);
1445 TestPmovsxdq(xmm10, xmm11);
1446 TestPmovsxdq(xmm11, xmm12);
1447 TestPmovsxdq(xmm12, xmm13);
1448 TestPmovsxdq(xmm13, xmm14);
1449 TestPmovsxdq(xmm14, xmm15);
1450 TestPmovsxdq(xmm15, xmm0);
1451
1452 #undef TestPmovsxdq
1453 #undef TestPmovsxdqXmmXmm
1454 }
1455
1456 } // end of anonymous namespace
1457 } // end of namespace Test
1458 } // end of namespace X8664
1459 } // end of namespace Ice
1460