Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: unittest/AssemblerX8632/XmmArith.cpp

Issue 1224173006: Adds the x86-64 assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments; make format Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « unittest/AssemblerX8632/X87.cpp ('k') | unittest/AssemblerX8664/ControlFlow.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/unittest/AssemblerX8632/XmmArith.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
16 TEST_F(AssemblerX8632Test, ArithSS) {
17 #define TestArithSSXmmXmm(FloatSize, Src, Value0, Dst, Value1, Inst, Op) \
18 do { \
19 static_assert(FloatSize == 32 || FloatSize == 64, \
20 "Invalid fp size " #FloatSize); \
21 static constexpr char TestString[] = \
22 "(" #FloatSize ", " #Src ", " #Value0 ", " #Dst ", " #Value1 \
23 ", " #Inst ", " #Op ")"; \
24 static constexpr bool IsDouble = FloatSize == 64; \
25 using Type = std::conditional<IsDouble, double, float>::type; \
26 const uint32_t T0 = allocateQword(); \
27 const Type V0 = Value0; \
28 const uint32_t T1 = allocateQword(); \
29 const Type V1 = Value1; \
30 \
31 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \
32 dwordAddress(T0)); \
33 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Src, \
34 dwordAddress(T1)); \
35 __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \
36 XmmRegister::Encoded_Reg_##Src); \
37 \
38 AssembledTest test = assemble(); \
39 if (IsDouble) { \
40 test.setQwordTo(T0, static_cast<double>(V0)); \
41 test.setQwordTo(T1, static_cast<double>(V1)); \
42 } else { \
43 test.setDwordTo(T0, static_cast<float>(V0)); \
44 test.setDwordTo(T1, static_cast<float>(V1)); \
45 } \
46 \
47 test.run(); \
48 \
49 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
50 reset(); \
51 } while (0)
52
53 #define TestArithSSXmmAddr(FloatSize, Value0, Dst, Value1, Inst, Op) \
54 do { \
55 static_assert(FloatSize == 32 || FloatSize == 64, \
56 "Invalid fp size " #FloatSize); \
57 static constexpr char TestString[] = \
58 "(" #FloatSize ", Addr, " #Value0 ", " #Dst ", " #Value1 ", " #Inst \
59 ", " #Op ")"; \
60 static constexpr bool IsDouble = FloatSize == 64; \
61 using Type = std::conditional<IsDouble, double, float>::type; \
62 const uint32_t T0 = allocateQword(); \
63 const Type V0 = Value0; \
64 const uint32_t T1 = allocateQword(); \
65 const Type V1 = Value1; \
66 \
67 __ movss(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \
68 dwordAddress(T0)); \
69 __ Inst(IceType_f##FloatSize, XmmRegister::Encoded_Reg_##Dst, \
70 dwordAddress(T1)); \
71 \
72 AssembledTest test = assemble(); \
73 if (IsDouble) { \
74 test.setQwordTo(T0, static_cast<double>(V0)); \
75 test.setQwordTo(T1, static_cast<double>(V1)); \
76 } else { \
77 test.setDwordTo(T0, static_cast<float>(V0)); \
78 test.setDwordTo(T1, static_cast<float>(V1)); \
79 } \
80 \
81 test.run(); \
82 \
83 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
84 reset(); \
85 } while (0)
86
87 #define TestArithSS(FloatSize, Src, Dst0, Dst1) \
88 do { \
89 TestArithSSXmmXmm(FloatSize, Src, 1.0, Dst0, 10.0, addss, +); \
90 TestArithSSXmmAddr(FloatSize, 2.0, Dst1, 20.0, addss, +); \
91 TestArithSSXmmXmm(FloatSize, Src, 3.0, Dst0, 30.0, subss, -); \
92 TestArithSSXmmAddr(FloatSize, 4.0, Dst1, 40.0, subss, -); \
93 TestArithSSXmmXmm(FloatSize, Src, 5.0, Dst0, 50.0, mulss, *); \
94 TestArithSSXmmAddr(FloatSize, 6.0, Dst1, 60.0, mulss, *); \
95 TestArithSSXmmXmm(FloatSize, Src, 7.0, Dst0, 70.0, divss, / ); \
96 TestArithSSXmmAddr(FloatSize, 8.0, Dst1, 80.0, divss, / ); \
97 } while (0)
98
99 TestArithSS(32, xmm0, xmm1, xmm2);
100 TestArithSS(32, xmm1, xmm2, xmm3);
101 TestArithSS(32, xmm2, xmm3, xmm4);
102 TestArithSS(32, xmm3, xmm4, xmm5);
103 TestArithSS(32, xmm4, xmm5, xmm6);
104 TestArithSS(32, xmm5, xmm6, xmm7);
105 TestArithSS(32, xmm6, xmm7, xmm0);
106 TestArithSS(32, xmm7, xmm0, xmm1);
107
108 TestArithSS(64, xmm0, xmm1, xmm2);
109 TestArithSS(64, xmm1, xmm2, xmm3);
110 TestArithSS(64, xmm2, xmm3, xmm4);
111 TestArithSS(64, xmm3, xmm4, xmm5);
112 TestArithSS(64, xmm4, xmm5, xmm6);
113 TestArithSS(64, xmm5, xmm6, xmm7);
114 TestArithSS(64, xmm6, xmm7, xmm0);
115 TestArithSS(64, xmm7, xmm0, xmm1);
116
117 #undef TestArithSS
118 #undef TestArithSSXmmAddr
119 #undef TestArithSSXmmXmm
120 }
121
122 TEST_F(AssemblerX8632Test, PArith) {
123 #define TestPArithXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type, Size) \
124 do { \
125 static constexpr char TestString[] = \
126 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
127 ", " #Type ", " #Size ")"; \
128 const uint32_t T0 = allocateDqword(); \
129 const Dqword V0 Value0; \
130 \
131 const uint32_t T1 = allocateDqword(); \
132 const Dqword V1 Value1; \
133 \
134 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
135 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
136 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
137 XmmRegister::Encoded_Reg_##Src); \
138 \
139 AssembledTest test = assemble(); \
140 test.setDqwordTo(T0, V0); \
141 test.setDqwordTo(T1, V1); \
142 test.run(); \
143 \
144 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
145 << TestString; \
146 reset(); \
147 } while (0)
148
149 #define TestPArithXmmAddr(Dst, Value0, Value1, Inst, Op, Type, Size) \
150 do { \
151 static constexpr char TestString[] = \
152 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
153 ", " #Type ", " #Size ")"; \
154 const uint32_t T0 = allocateDqword(); \
155 const Dqword V0 Value0; \
156 \
157 const uint32_t T1 = allocateDqword(); \
158 const Dqword V1 Value1; \
159 \
160 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
161 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
162 dwordAddress(T1)); \
163 \
164 AssembledTest test = assemble(); \
165 test.setDqwordTo(T0, V0); \
166 test.setDqwordTo(T1, V1); \
167 test.run(); \
168 \
169 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
170 << TestString; \
171 reset(); \
172 } while (0)
173
174 #define TestPArithXmmImm(Dst, Value0, Imm, Inst, Op, Type, Size) \
175 do { \
176 static constexpr char TestString[] = \
177 "(" #Dst ", " #Value0 ", " #Imm ", " #Inst ", " #Op ", " #Type \
178 ", " #Size ")"; \
179 const uint32_t T0 = allocateDqword(); \
180 const Dqword V0 Value0; \
181 \
182 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
183 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, Immediate(Imm)); \
184 \
185 AssembledTest test = assemble(); \
186 test.setDqwordTo(T0, V0); \
187 test.run(); \
188 \
189 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op Imm, test.Dst<Dqword>()) \
190 << TestString; \
191 reset(); \
192 } while (0)
193
194 #define TestPAndnXmmXmm(Dst, Value0, Src, Value1, Type, Size) \
195 do { \
196 static constexpr char TestString[] = \
197 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", pandn, " #Type \
198 ", " #Size ")"; \
199 const uint32_t T0 = allocateDqword(); \
200 const Dqword V0 Value0; \
201 \
202 const uint32_t T1 = allocateDqword(); \
203 const Dqword V1 Value1; \
204 \
205 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
206 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
207 __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
208 XmmRegister::Encoded_Reg_##Src); \
209 \
210 AssembledTest test = assemble(); \
211 test.setDqwordTo(T0, V0); \
212 test.setDqwordTo(T1, V1); \
213 test.run(); \
214 \
215 ASSERT_EQ(~(packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
216 << TestString; \
217 reset(); \
218 } while (0)
219
220 #define TestPAndnXmmAddr(Dst, Value0, Value1, Type, Size) \
221 do { \
222 static constexpr char TestString[] = \
223 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", pandn, " #Type ", " #Size \
224 ")"; \
225 const uint32_t T0 = allocateDqword(); \
226 const Dqword V0 Value0; \
227 \
228 const uint32_t T1 = allocateDqword(); \
229 const Dqword V1 Value1; \
230 \
231 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
232 __ pandn(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
233 dwordAddress(T1)); \
234 \
235 AssembledTest test = assemble(); \
236 test.setDqwordTo(T0, V0); \
237 test.setDqwordTo(T1, V1); \
238 test.run(); \
239 \
240 ASSERT_EQ((~packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
241 << TestString; \
242 reset(); \
243 } while (0)
244
245 #define TestPArithSize(Dst, Src, Size) \
246 do { \
247 static_assert(Size == 8 || Size == 16 || Size == 32, "Invalid size."); \
248 if (Size != 8) { \
249 TestPArithXmmXmm( \
250 Dst, \
251 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
252 Src, (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
253 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
254 uint64_t(0x8080404002020101ull)), \
255 (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
256 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
257 uint64_t(0x8080404002020101ull)), \
258 3u, psra, >>, int, Size); \
259 TestPArithXmmXmm( \
260 Dst, \
261 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
262 Src, (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
263 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
264 uint64_t(0x8080404002020101ull)), \
265 (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
266 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
267 uint64_t(0x8080404002020101ull)), \
268 3u, psrl, >>, uint, Size); \
269 TestPArithXmmXmm( \
270 Dst, \
271 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
272 Src, (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
273 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
274 uint64_t(0x8080404002020101ull)), \
275 (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
276 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
277 uint64_t(0x8080404002020101ull)), \
278 3u, psll, <<, uint, Size); \
279 \
280 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
281 uint64_t(0x8080404002020101ull)), \
282 Src, (uint64_t(0xFFFFFFFF00000000ull), \
283 uint64_t(0x0123456789ABCDEull)), \
284 pmull, *, int, Size); \
285 TestPArithXmmAddr( \
286 Dst, \
287 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
288 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
289 pmull, *, int, Size); \
290 if (Size != 16) { \
291 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
292 uint64_t(0x8080404002020101ull)), \
293 Src, (uint64_t(0xFFFFFFFF00000000ull), \
294 uint64_t(0x0123456789ABCDEull)), \
295 pmuludq, *, uint, Size); \
296 TestPArithXmmAddr( \
297 Dst, (uint64_t(0x8040201008040201ull), \
298 uint64_t(0x8080404002020101ull)), \
299 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
300 pmuludq, *, uint, Size); \
301 } \
302 } \
303 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
304 uint64_t(0x8080404002020101ull)), \
305 Src, (uint64_t(0xFFFFFFFF00000000ull), \
306 uint64_t(0x0123456789ABCDEull)), \
307 padd, +, int, Size); \
308 TestPArithXmmAddr( \
309 Dst, \
310 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
311 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
312 padd, +, int, Size); \
313 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
314 uint64_t(0x8080404002020101ull)), \
315 Src, (uint64_t(0xFFFFFFFF00000000ull), \
316 uint64_t(0x0123456789ABCDEull)), \
317 psub, -, int, Size); \
318 TestPArithXmmAddr( \
319 Dst, \
320 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
321 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
322 psub, -, int, Size); \
323 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
324 uint64_t(0x8080404002020101ull)), \
325 Src, (uint64_t(0xFFFFFFFF00000000ull), \
326 uint64_t(0x0123456789ABCDEull)), \
327 pand, &, int, Size); \
328 TestPArithXmmAddr( \
329 Dst, \
330 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
331 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
332 pand, &, int, Size); \
333 \
334 TestPAndnXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
335 uint64_t(0x8080404002020101ull)), \
336 Src, (uint64_t(0xFFFFFFFF00000000ull), \
337 uint64_t(0x0123456789ABCDEull)), \
338 int, Size); \
339 TestPAndnXmmAddr( \
340 Dst, \
341 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
342 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
343 int, Size); \
344 \
345 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
346 uint64_t(0x8080404002020101ull)), \
347 Src, (uint64_t(0xFFFFFFFF00000000ull), \
348 uint64_t(0x0123456789ABCDEull)), \
349 por, |, int, Size); \
350 TestPArithXmmAddr( \
351 Dst, \
352 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
353 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
354 por, |, int, Size); \
355 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
356 uint64_t(0x8080404002020101ull)), \
357 Src, (uint64_t(0xFFFFFFFF00000000ull), \
358 uint64_t(0x0123456789ABCDEull)), \
359 pxor, ^, int, Size); \
360 TestPArithXmmAddr( \
361 Dst, \
362 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
363 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
364 pxor, ^, int, Size); \
365 } while (0)
366
367 #define TestPArith(Src, Dst) \
368 do { \
369 TestPArithSize(Src, Dst, 8); \
370 TestPArithSize(Src, Dst, 16); \
371 TestPArithSize(Src, Dst, 32); \
372 } while (0)
373
374 TestPArith(xmm0, xmm1);
375 TestPArith(xmm1, xmm2);
376 TestPArith(xmm2, xmm3);
377 TestPArith(xmm3, xmm4);
378 TestPArith(xmm4, xmm5);
379 TestPArith(xmm5, xmm6);
380 TestPArith(xmm6, xmm7);
381 TestPArith(xmm7, xmm0);
382
383 #undef TestPArith
384 #undef TestPArithSize
385 #undef TestPAndnXmmAddr
386 #undef TestPAndnXmmXmm
387 #undef TestPArithXmmImm
388 #undef TestPArithXmmAddr
389 #undef TestPArithXmmXmm
390 }
391
392 TEST_F(AssemblerX8632Test, ArithPS) {
393 #define TestArithPSXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type) \
394 do { \
395 static constexpr char TestString[] = \
396 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
397 ", " #Type ")"; \
398 const uint32_t T0 = allocateDqword(); \
399 const Dqword V0 Value0; \
400 const uint32_t T1 = allocateDqword(); \
401 const Dqword V1 Value1; \
402 \
403 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
404 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
405 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \
406 XmmRegister::Encoded_Reg_##Src); \
407 \
408 AssembledTest test = assemble(); \
409 test.setDqwordTo(T0, V0); \
410 test.setDqwordTo(T1, V1); \
411 test.run(); \
412 \
413 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
414 \
415 reset(); \
416 } while (0)
417
418 #define TestArithPSXmmXmmUntyped(Dst, Value0, Src, Value1, Inst, Op, Type) \
419 do { \
420 static constexpr char TestString[] = \
421 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
422 ", " #Type ")"; \
423 const uint32_t T0 = allocateDqword(); \
424 const Dqword V0 Value0; \
425 const uint32_t T1 = allocateDqword(); \
426 const Dqword V1 Value1; \
427 \
428 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
429 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
430 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \
431 \
432 AssembledTest test = assemble(); \
433 test.setDqwordTo(T0, V0); \
434 test.setDqwordTo(T1, V1); \
435 test.run(); \
436 \
437 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
438 \
439 reset(); \
440 } while (0)
441
442 #define TestArithPSXmmAddrUntyped(Dst, Value0, Value1, Inst, Op, Type) \
443 do { \
444 static constexpr char TestString[] = \
445 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
446 ", " #Type ")"; \
447 const uint32_t T0 = allocateDqword(); \
448 const Dqword V0 Value0; \
449 const uint32_t T1 = allocateDqword(); \
450 const Dqword V1 Value1; \
451 \
452 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
453 __ Inst(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
454 \
455 AssembledTest test = assemble(); \
456 test.setDqwordTo(T0, V0); \
457 test.setDqwordTo(T1, V1); \
458 test.run(); \
459 \
460 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
461 \
462 reset(); \
463 } while (0)
464
465 #define TestMinMaxPS(Dst, Value0, Src, Value1, Inst, Type) \
466 do { \
467 static constexpr char TestString[] = \
468 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Type \
469 ")"; \
470 const uint32_t T0 = allocateDqword(); \
471 const Dqword V0 Value0; \
472 const uint32_t T1 = allocateDqword(); \
473 const Dqword V1 Value1; \
474 \
475 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
476 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
477 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \
478 \
479 AssembledTest test = assemble(); \
480 test.setDqwordTo(T0, V0); \
481 test.setDqwordTo(T1, V1); \
482 test.run(); \
483 \
484 ASSERT_EQ(packedAs<Type>(V0).Inst(V1), test.Dst<Dqword>()) << TestString; \
485 \
486 reset(); \
487 } while (0)
488
489 #define TestArithPSXmmAddr(Dst, Value0, Value1, Inst, Op, Type) \
490 do { \
491 static constexpr char TestString[] = \
492 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
493 ", " #Type ")"; \
494 const uint32_t T0 = allocateDqword(); \
495 const Dqword V0 Value0; \
496 const uint32_t T1 = allocateDqword(); \
497 const Dqword V1 Value1; \
498 \
499 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
500 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
501 \
502 AssembledTest test = assemble(); \
503 test.setDqwordTo(T0, V0); \
504 test.setDqwordTo(T1, V1); \
505 test.run(); \
506 \
507 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
508 \
509 reset(); \
510 } while (0)
511
512 #define TestArithPS(Dst, Src) \
513 do { \
514 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
515 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
516 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
517 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
518 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
519 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
520 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
521 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
522 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
523 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
524 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
525 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
526 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
527 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
528 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
529 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
530 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
531 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
532 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
533 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
534 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), andpd, &, \
535 double); \
536 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), andpd, &, \
537 double); \
538 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
539 (0.55, 0.43, 0.23, 1.21), orps, |, float); \
540 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), orpd, |, \
541 double); \
542 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
543 (0.55, 0.43, 0.23, 1.21), minps, float); \
544 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
545 (0.55, 0.43, 0.23, 1.21), maxps, float); \
546 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), minpd, double); \
547 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxpd, double); \
548 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
549 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
550 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
551 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
552 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorpd, ^, \
553 double); \
554 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), xorpd, ^, \
555 double); \
556 } while (0)
557
558 #if 0
559
560 #endif
561
562 TestArithPS(xmm0, xmm1);
563 TestArithPS(xmm1, xmm2);
564 TestArithPS(xmm2, xmm3);
565 TestArithPS(xmm3, xmm4);
566 TestArithPS(xmm4, xmm5);
567 TestArithPS(xmm5, xmm6);
568 TestArithPS(xmm6, xmm7);
569 TestArithPS(xmm7, xmm0);
570
571 #undef TestArithPs
572 #undef TestMinMaxPS
573 #undef TestArithPSXmmXmmUntyped
574 #undef TestArithPSXmmAddr
575 #undef TestArithPSXmmXmm
576 }
577
578 TEST_F(AssemblerX8632Test, Blending) {
579 using f32 = float;
580 using i8 = uint8_t;
581
582 #define TestBlendingXmmXmm(Dst, Value0, Src, Value1, M /*ask*/, Inst, Type) \
583 do { \
584 static constexpr char TestString[] = \
585 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #M ", " #Inst \
586 ", " #Type ")"; \
587 const uint32_t T0 = allocateDqword(); \
588 const Dqword V0 Value0; \
589 const uint32_t T1 = allocateDqword(); \
590 const Dqword V1 Value1; \
591 const uint32_t Mask = allocateDqword(); \
592 const Dqword MaskValue M; \
593 \
594 __ movups(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \
595 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
596 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
597 __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##Dst, \
598 XmmRegister::Encoded_Reg_##Src); \
599 \
600 AssembledTest test = assemble(); \
601 test.setDqwordTo(T0, V0); \
602 test.setDqwordTo(T1, V1); \
603 test.setDqwordTo(Mask, MaskValue); \
604 test.run(); \
605 \
606 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
607 << TestString; \
608 reset(); \
609 } while (0)
610
611 #define TestBlendingXmmAddr(Dst, Value0, Value1, M /*ask*/, Inst, Type) \
612 do { \
613 static constexpr char TestString[] = \
614 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #M ", " #Inst ", " #Type \
615 ")"; \
616 const uint32_t T0 = allocateDqword(); \
617 const Dqword V0 Value0; \
618 const uint32_t T1 = allocateDqword(); \
619 const Dqword V1 Value1; \
620 const uint32_t Mask = allocateDqword(); \
621 const Dqword MaskValue M; \
622 \
623 __ movups(XmmRegister::Encoded_Reg_xmm0, dwordAddress(Mask)); \
624 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
625 __ Inst(IceType_##Type, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
626 \
627 AssembledTest test = assemble(); \
628 test.setDqwordTo(T0, V0); \
629 test.setDqwordTo(T1, V1); \
630 test.setDqwordTo(Mask, MaskValue); \
631 test.run(); \
632 \
633 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
634 << TestString; \
635 reset(); \
636 } while (0)
637
638 #define TestBlending(Src, Dst) \
639 do { \
640 TestBlendingXmmXmm( \
641 Dst, (1.0, 2.0, 1.0, 2.0), Src, (-1.0, -2.0, -1.0, -2.0), \
642 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
643 blendvps, f32); \
644 TestBlendingXmmAddr( \
645 Dst, (1.0, 2.0, 1.0, 2.0), (-1.0, -2.0, -1.0, -2.0), \
646 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
647 blendvps, f32); \
648 TestBlendingXmmXmm( \
649 Dst, \
650 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
651 Src, \
652 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
653 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
654 pblendvb, i8); \
655 TestBlendingXmmAddr( \
656 Dst, \
657 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
658 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
659 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
660 pblendvb, i8); \
661 } while (0)
662
663 /* xmm0 is taken. It is the implicit mask . */
664 TestBlending(xmm1, xmm2);
665 TestBlending(xmm2, xmm3);
666 TestBlending(xmm3, xmm4);
667 TestBlending(xmm4, xmm5);
668 TestBlending(xmm5, xmm6);
669 TestBlending(xmm6, xmm7);
670 TestBlending(xmm7, xmm1);
671
672 #undef TestBlending
673 #undef TestBlendingXmmAddr
674 #undef TestBlendingXmmXmm
675 }
676
677 TEST_F(AssemblerX8632Test, Cmpps) {
678 #define TestCmppsXmmXmm(Dst, Src, C, Op) \
679 do { \
680 static constexpr char TestString[] = \
681 "(" #Src ", " #Dst ", " #C ", " #Op ")"; \
682 const uint32_t T0 = allocateDqword(); \
683 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
684 const uint32_t T1 = allocateDqword(); \
685 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
686 \
687 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
688 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
689 __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
690 Cond::Cmpps_##C); \
691 \
692 AssembledTest test = assemble(); \
693 test.setDqwordTo(T0, V0); \
694 test.setDqwordTo(T1, V1); \
695 test.run(); \
696 \
697 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
698 ; \
699 reset(); \
700 } while (0)
701
702 #define TestCmppsXmmAddr(Dst, C, Op) \
703 do { \
704 static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \
705 const uint32_t T0 = allocateDqword(); \
706 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
707 const uint32_t T1 = allocateDqword(); \
708 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
709 \
710 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
711 __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \
712 Cond::Cmpps_##C); \
713 \
714 AssembledTest test = assemble(); \
715 test.setDqwordTo(T0, V0); \
716 test.setDqwordTo(T1, V1); \
717 test.run(); \
718 \
719 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
720 ; \
721 reset(); \
722 } while (0)
723
724 #define TestCmppsOrdUnordXmmXmm(Dst, Src, C) \
725 do { \
726 static constexpr char TestString[] = "(" #Src ", " #Dst ", " #C ")"; \
727 const uint32_t T0 = allocateDqword(); \
728 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
729 std::numeric_limits<float>::quiet_NaN()); \
730 const uint32_t T1 = allocateDqword(); \
731 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
732 std::numeric_limits<float>::quiet_NaN()); \
733 \
734 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
735 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
736 __ cmpps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
737 Cond::Cmpps_##C); \
738 \
739 AssembledTest test = assemble(); \
740 test.setDqwordTo(T0, V0); \
741 test.setDqwordTo(T1, V1); \
742 test.run(); \
743 \
744 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
745 ; \
746 reset(); \
747 } while (0)
748
749 #define TestCmppsOrdUnordXmmAddr(Dst, C) \
750 do { \
751 static constexpr char TestString[] = "(" #Dst ", " #C ")"; \
752 const uint32_t T0 = allocateDqword(); \
753 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
754 std::numeric_limits<float>::quiet_NaN()); \
755 const uint32_t T1 = allocateDqword(); \
756 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
757 std::numeric_limits<float>::quiet_NaN()); \
758 \
759 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
760 __ cmpps(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \
761 Cond::Cmpps_##C); \
762 \
763 AssembledTest test = assemble(); \
764 test.setDqwordTo(T0, V0); \
765 test.setDqwordTo(T1, V1); \
766 test.run(); \
767 \
768 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
769 ; \
770 reset(); \
771 } while (0)
772
773 #define TestCmpps(Dst, Src) \
774 do { \
775 TestCmppsXmmXmm(Dst, Src, eq, == ); \
776 TestCmppsXmmAddr(Dst, eq, == ); \
777 TestCmppsXmmXmm(Dst, Src, eq, == ); \
778 TestCmppsXmmAddr(Dst, eq, == ); \
779 TestCmppsXmmXmm(Dst, Src, eq, == ); \
780 TestCmppsXmmAddr(Dst, eq, == ); \
781 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
782 TestCmppsOrdUnordXmmAddr(Dst, unord); \
783 TestCmppsXmmXmm(Dst, Src, eq, == ); \
784 TestCmppsXmmAddr(Dst, eq, == ); \
785 TestCmppsXmmXmm(Dst, Src, eq, == ); \
786 TestCmppsXmmAddr(Dst, eq, == ); \
787 TestCmppsXmmXmm(Dst, Src, eq, == ); \
788 TestCmppsXmmAddr(Dst, eq, == ); \
789 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
790 TestCmppsOrdUnordXmmAddr(Dst, unord); \
791 } while (0)
792
793 TestCmpps(xmm0, xmm1);
794 TestCmpps(xmm1, xmm2);
795 TestCmpps(xmm2, xmm3);
796 TestCmpps(xmm3, xmm4);
797 TestCmpps(xmm4, xmm5);
798 TestCmpps(xmm5, xmm6);
799 TestCmpps(xmm6, xmm7);
800 TestCmpps(xmm7, xmm0);
801
802 #undef TestCmpps
803 #undef TestCmppsOrdUnordXmmAddr
804 #undef TestCmppsOrdUnordXmmXmm
805 #undef TestCmppsXmmAddr
806 #undef TestCmppsXmmXmm
807 }
808
809 TEST_F(AssemblerX8632Test, Sqrtps_Rsqrtps_Reciprocalps_Sqrtpd) {
810 #define TestImplSingle(Dst, Inst, Expect) \
811 do { \
812 static constexpr char TestString[] = "(" #Dst ", " #Inst ")"; \
813 const uint32_t T0 = allocateDqword(); \
814 const Dqword V0(1.0, 4.0, 20.0, 3.14); \
815 \
816 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
817 __ Inst(XmmRegister::Encoded_Reg_##Dst); \
818 \
819 AssembledTest test = assemble(); \
820 test.setDqwordTo(T0, V0); \
821 test.run(); \
822 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
823 reset(); \
824 } while (0)
825
826 #define TestImpl(Dst) \
827 do { \
828 TestImplSingle(Dst, sqrtps, (uint64_t(0x400000003F800000ull), \
829 uint64_t(0x3FE2D10B408F1BBDull))); \
830 TestImplSingle(Dst, rsqrtps, (uint64_t(0x3EFFF0003F7FF000ull), \
831 uint64_t(0x3F1078003E64F000ull))); \
832 TestImplSingle(Dst, reciprocalps, (uint64_t(0x3E7FF0003F7FF000ull), \
833 uint64_t(0x3EA310003D4CC000ull))); \
834 \
835 TestImplSingle(Dst, sqrtpd, (uint64_t(0x4036A09E9365F5F3ull), \
836 uint64_t(0x401C42FAE40282A8ull))); \
837 } while (0)
838
839 TestImpl(xmm0);
840 TestImpl(xmm1);
841 TestImpl(xmm2);
842 TestImpl(xmm3);
843 TestImpl(xmm4);
844 TestImpl(xmm5);
845 TestImpl(xmm6);
846 TestImpl(xmm7);
847
848 #undef TestImpl
849 #undef TestImplSingle
850 }
851
852 TEST_F(AssemblerX8632Test, Unpck) {
853 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),
854 uint64_t(0xCCCCCCCCDDDDDDDDull));
855 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),
856 uint64_t(0x9999999988888888ull));
857
858 const Dqword unpcklpsExpected(uint64_t(0xFFFFFFFFBBBBBBBBull),
859 uint64_t(0xEEEEEEEEAAAAAAAAull));
860 const Dqword unpcklpdExpected(uint64_t(0xAAAAAAAABBBBBBBBull),
861 uint64_t(0xEEEEEEEEFFFFFFFFull));
862 const Dqword unpckhpsExpected(uint64_t(0x88888888DDDDDDDDull),
863 uint64_t(0x99999999CCCCCCCCull));
864 const Dqword unpckhpdExpected(uint64_t(0xCCCCCCCCDDDDDDDDull),
865 uint64_t(0x9999999988888888ull));
866
867 #define TestImplSingle(Dst, Src, Inst) \
868 do { \
869 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
870 const uint32_t T0 = allocateDqword(); \
871 const uint32_t T1 = allocateDqword(); \
872 \
873 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
874 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
875 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \
876 \
877 AssembledTest test = assemble(); \
878 test.setDqwordTo(T0, V0); \
879 test.setDqwordTo(T1, V1); \
880 test.run(); \
881 \
882 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
883 reset(); \
884 } while (0)
885
886 #define TestImpl(Dst, Src) \
887 do { \
888 TestImplSingle(Dst, Src, unpcklps); \
889 TestImplSingle(Dst, Src, unpcklpd); \
890 TestImplSingle(Dst, Src, unpckhps); \
891 TestImplSingle(Dst, Src, unpckhpd); \
892 } while (0)
893
894 TestImpl(xmm0, xmm1);
895 TestImpl(xmm1, xmm2);
896 TestImpl(xmm2, xmm3);
897 TestImpl(xmm3, xmm4);
898 TestImpl(xmm4, xmm5);
899 TestImpl(xmm5, xmm6);
900 TestImpl(xmm6, xmm7);
901 TestImpl(xmm7, xmm0);
902
903 #undef TestImpl
904 #undef TestImplSingle
905 }
906
907 TEST_F(AssemblerX8632Test, Shufp) {
908 const Dqword V0(uint64_t(0x1111111122222222ull),
909 uint64_t(0x5555555577777777ull));
910 const Dqword V1(uint64_t(0xAAAAAAAABBBBBBBBull),
911 uint64_t(0xCCCCCCCCDDDDDDDDull));
912
913 const uint8_t pshufdImm = 0x63;
914 const Dqword pshufdExpected(uint64_t(0xBBBBBBBBCCCCCCCCull),
915 uint64_t(0xAAAAAAAADDDDDDDDull));
916
917 const uint8_t shufpsImm = 0xf9;
918 const Dqword shufpsExpected(uint64_t(0x7777777711111111ull),
919 uint64_t(0xCCCCCCCCCCCCCCCCull));
920
921 #define TestImplSingleXmmXmm(Dst, Src, Inst) \
922 do { \
923 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
924 const uint32_t T0 = allocateDqword(); \
925 const uint32_t T1 = allocateDqword(); \
926 \
927 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
928 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
929 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, \
930 XmmRegister::Encoded_Reg_##Src, Immediate(Inst##Imm)); \
931 \
932 AssembledTest test = assemble(); \
933 test.setDqwordTo(T0, V0); \
934 test.setDqwordTo(T1, V1); \
935 test.run(); \
936 \
937 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
938 reset(); \
939 } while (0)
940
941 #define TestImplSingleXmmAddr(Dst, Inst) \
942 do { \
943 static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \
944 const uint32_t T0 = allocateDqword(); \
945 const uint32_t T1 = allocateDqword(); \
946 \
947 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
948 __ Inst(IceType_f32, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1), \
949 Immediate(Inst##Imm)); \
950 \
951 AssembledTest test = assemble(); \
952 test.setDqwordTo(T0, V0); \
953 test.setDqwordTo(T1, V1); \
954 test.run(); \
955 \
956 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
957 reset(); \
958 } while (0)
959
960 #define TestImplSingleXmmXmmUntyped(Dst, Src, Inst) \
961 do { \
962 static constexpr char TestString[] = \
963 "(" #Dst ", " #Src ", " #Inst ", Untyped)"; \
964 const uint32_t T0 = allocateDqword(); \
965 const uint32_t T1 = allocateDqword(); \
966 \
967 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
968 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
969 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
970 Immediate(Inst##Imm)); \
971 \
972 AssembledTest test = assemble(); \
973 test.setDqwordTo(T0, V0); \
974 test.setDqwordTo(T1, V1); \
975 test.run(); \
976 \
977 ASSERT_EQ(Inst##UntypedExpected, test.Dst<Dqword>()) << TestString; \
978 reset(); \
979 } while (0)
980
981 #define TestImpl(Dst, Src) \
982 do { \
983 TestImplSingleXmmXmm(Dst, Src, pshufd); \
984 TestImplSingleXmmAddr(Dst, pshufd); \
985 TestImplSingleXmmXmm(Dst, Src, shufps); \
986 TestImplSingleXmmAddr(Dst, shufps); \
987 } while (0)
988
989 TestImpl(xmm0, xmm1);
990 TestImpl(xmm1, xmm2);
991 TestImpl(xmm2, xmm3);
992 TestImpl(xmm3, xmm4);
993 TestImpl(xmm4, xmm5);
994 TestImpl(xmm5, xmm6);
995 TestImpl(xmm6, xmm7);
996 TestImpl(xmm7, xmm0);
997
998 #undef TestImpl
999 #undef TestImplSingleXmmXmmUntyped
1000 #undef TestImplSingleXmmAddr
1001 #undef TestImplSingleXmmXmm
1002 }
1003
1004 TEST_F(AssemblerX8632Test, Cvt) {
1005 const Dqword dq2ps32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
1006 const Dqword dq2ps32SrcValue(-5, 3, 100, 200);
1007 const Dqword dq2ps32Expected(-5.0f, 3.0f, 100.0, 200.0);
1008
1009 const Dqword dq2ps64DstValue(0.0f, 0.0f, -1.0f, -1.0f);
1010 const Dqword dq2ps64SrcValue(-5, 3, 100, 200);
1011 const Dqword dq2ps64Expected(-5.0f, 3.0f, 100.0, 200.0);
1012
1013 const Dqword tps2dq32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
1014 const Dqword tps2dq32SrcValue(-5.0f, 3.0f, 100.0, 200.0);
1015 const Dqword tps2dq32Expected(-5, 3, 100, 200);
1016
1017 const Dqword tps2dq64DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
1018 const Dqword tps2dq64SrcValue(-5.0f, 3.0f, 100.0, 200.0);
1019 const Dqword tps2dq64Expected(-5, 3, 100, 200);
1020
1021 const Dqword si2ss32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
1022 const int32_t si2ss32SrcValue = 5;
1023 const Dqword si2ss32Expected(5.0f, -1.0f, -1.0f, -1.0f);
1024
1025 const Dqword si2ss64DstValue(-1.0, -1.0);
1026 const int32_t si2ss64SrcValue = 5;
1027 const Dqword si2ss64Expected(5.0, -1.0);
1028
1029 const int32_t tss2si32DstValue = 0xF00F0FF0;
1030 const Dqword tss2si32SrcValue(-5.0f, -1.0f, -1.0f, -1.0f);
1031 const int32_t tss2si32Expected = -5;
1032
1033 const int32_t tss2si64DstValue = 0xF00F0FF0;
1034 const Dqword tss2si64SrcValue(-5.0, -1.0);
1035 const int32_t tss2si64Expected = -5;
1036
1037 const Dqword float2float32DstValue(-1.0, -1.0);
1038 const Dqword float2float32SrcValue(-5.0, 3, 100, 200);
1039 const Dqword float2float32Expected(-5.0, -1.0);
1040
1041 const Dqword float2float64DstValue(-1.0, -1.0, -1.0, -1.0);
1042 const Dqword float2float64SrcValue(-5.0, 3.0);
1043 const Dqword float2float64Expected(-5.0, -1.0, -1.0, -1.0);
1044
1045 #define TestImplPXmmXmm(Dst, Src, Inst, Size) \
1046 do { \
1047 static constexpr char TestString[] = \
1048 "(" #Dst ", " #Src ", cvt" #Inst ", f" #Size ")"; \
1049 const uint32_t T0 = allocateDqword(); \
1050 const uint32_t T1 = allocateDqword(); \
1051 \
1052 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1053 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
1054 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1055 XmmRegister::Encoded_Reg_##Src); \
1056 \
1057 AssembledTest test = assemble(); \
1058 test.setDqwordTo(T0, Inst##Size##DstValue); \
1059 test.setDqwordTo(T1, Inst##Size##SrcValue); \
1060 test.run(); \
1061 \
1062 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
1063 reset(); \
1064 } while (0)
1065
1066 #define TestImplSXmmReg(Dst, GPR, Inst, Size) \
1067 do { \
1068 static constexpr char TestString[] = \
1069 "(" #Dst ", " #GPR ", cvt" #Inst ", f" #Size ")"; \
1070 const uint32_t T0 = allocateDqword(); \
1071 \
1072 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1073 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
1074 Immediate(Inst##Size##SrcValue)); \
1075 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1076 GPRRegister::Encoded_Reg_##GPR); \
1077 \
1078 AssembledTest test = assemble(); \
1079 test.setDqwordTo(T0, Inst##Size##DstValue); \
1080 test.run(); \
1081 \
1082 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
1083 reset(); \
1084 } while (0)
1085
1086 #define TestImplSRegXmm(GPR, Src, Inst, Size) \
1087 do { \
1088 static constexpr char TestString[] = \
1089 "(" #GPR ", " #Src ", cvt" #Inst ", f" #Size ")"; \
1090 const uint32_t T0 = allocateDqword(); \
1091 \
1092 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
1093 Immediate(Inst##Size##DstValue)); \
1094 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
1095 __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \
1096 XmmRegister::Encoded_Reg_##Src); \
1097 \
1098 AssembledTest test = assemble(); \
1099 test.setDqwordTo(T0, Inst##Size##SrcValue); \
1100 test.run(); \
1101 \
1102 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
1103 << TestString; \
1104 reset(); \
1105 } while (0)
1106
1107 #define TestImplPXmmAddr(Dst, Inst, Size) \
1108 do { \
1109 static constexpr char TestString[] = \
1110 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
1111 const uint32_t T0 = allocateDqword(); \
1112 const uint32_t T1 = allocateDqword(); \
1113 \
1114 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1115 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1116 dwordAddress(T1)); \
1117 \
1118 AssembledTest test = assemble(); \
1119 test.setDqwordTo(T0, Inst##Size##DstValue); \
1120 test.setDqwordTo(T1, Inst##Size##SrcValue); \
1121 test.run(); \
1122 \
1123 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
1124 reset(); \
1125 } while (0)
1126
1127 #define TestImplSXmmAddr(Dst, Inst, Size) \
1128 do { \
1129 static constexpr char TestString[] = \
1130 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
1131 const uint32_t T0 = allocateDqword(); \
1132 const uint32_t T1 = allocateDword(); \
1133 \
1134 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1135 __ cvt##Inst(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1136 dwordAddress(T1)); \
1137 \
1138 AssembledTest test = assemble(); \
1139 test.setDqwordTo(T0, Inst##Size##DstValue); \
1140 test.setDwordTo(T1, Inst##Size##SrcValue); \
1141 test.run(); \
1142 \
1143 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
1144 reset(); \
1145 } while (0)
1146
1147 #define TestImplSRegAddr(GPR, Inst, Size) \
1148 do { \
1149 static constexpr char TestString[] = \
1150 "(" #GPR ", Addr, cvt" #Inst ", f" #Size ")"; \
1151 const uint32_t T0 = allocateDqword(); \
1152 \
1153 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, \
1154 Immediate(Inst##Size##DstValue)); \
1155 __ cvt##Inst(IceType_f##Size, GPRRegister::Encoded_Reg_##GPR, \
1156 dwordAddress(T0)); \
1157 \
1158 AssembledTest test = assemble(); \
1159 test.setDqwordTo(T0, Inst##Size##SrcValue); \
1160 test.run(); \
1161 \
1162 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
1163 << TestString; \
1164 reset(); \
1165 } while (0)
1166
1167 #define TestImplSize(Dst, Src, GPR, Size) \
1168 do { \
1169 TestImplPXmmXmm(Dst, Src, dq2ps, Size); \
1170 TestImplPXmmAddr(Src, dq2ps, Size); \
1171 TestImplPXmmXmm(Dst, Src, tps2dq, Size); \
1172 TestImplPXmmAddr(Src, tps2dq, Size); \
1173 TestImplSXmmReg(Dst, GPR, si2ss, Size); \
1174 TestImplSXmmAddr(Dst, si2ss, Size); \
1175 TestImplSRegXmm(GPR, Src, tss2si, Size); \
1176 TestImplSRegAddr(GPR, tss2si, Size); \
1177 TestImplPXmmXmm(Dst, Src, float2float, Size); \
1178 TestImplPXmmAddr(Src, float2float, Size); \
1179 } while (0)
1180
1181 #define TestImpl(Dst, Src, GPR) \
1182 do { \
1183 TestImplSize(Dst, Src, GPR, 32); \
1184 TestImplSize(Dst, Src, GPR, 64); \
1185 } while (0)
1186
1187 TestImpl(xmm0, xmm1, eax);
1188 TestImpl(xmm1, xmm2, ebx);
1189 TestImpl(xmm2, xmm3, ecx);
1190 TestImpl(xmm3, xmm4, edx);
1191 TestImpl(xmm4, xmm5, esi);
1192 TestImpl(xmm5, xmm6, edi);
1193 TestImpl(xmm6, xmm7, eax);
1194 TestImpl(xmm7, xmm0, ebx);
1195
1196 #undef TestImpl
1197 #undef TestImplSize
1198 #undef TestImplSRegAddr
1199 #undef TestImplSXmmAddr
1200 #undef TestImplPXmmAddr
1201 #undef TestImplSRegXmm
1202 #undef TestImplSXmmReg
1203 #undef TestImplPXmmXmm
1204 }
1205
1206 TEST_F(AssemblerX8632Test, Ucomiss) {
1207 static constexpr float qnan32 = std::numeric_limits<float>::quiet_NaN();
1208 static constexpr double qnan64 = std::numeric_limits<float>::quiet_NaN();
1209
1210 Dqword test32DstValue(0.0, qnan32, qnan32, qnan32);
1211 Dqword test32SrcValue(0.0, qnan32, qnan32, qnan32);
1212
1213 Dqword test64DstValue(0.0, qnan64);
1214 Dqword test64SrcValue(0.0, qnan64);
1215
1216 #define TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, \
1217 BOther) \
1218 do { \
1219 static constexpr char NearBranch = AssemblerX8632::kNearJump; \
1220 static constexpr char TestString[] = \
1221 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #CompType \
1222 ", " #BParity ", " #BOther ")"; \
1223 const uint32_t T0 = allocateDqword(); \
1224 test##Size##DstValue.F##Size[0] = Value0; \
1225 const uint32_t T1 = allocateDqword(); \
1226 test##Size##SrcValue.F##Size[0] = Value1; \
1227 const uint32_t ImmIfTrue = 0xBEEF; \
1228 const uint32_t ImmIfFalse = 0xC0FFE; \
1229 \
1230 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1231 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
1232 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
1233 __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1234 XmmRegister::Encoded_Reg_##Src); \
1235 Label Done; \
1236 __ j(Cond::Br_##BParity, &Done, NearBranch); \
1237 __ j(Cond::Br_##BOther, &Done, NearBranch); \
1238 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
1239 __ bind(&Done); \
1240 \
1241 AssembledTest test = assemble(); \
1242 test.setDqwordTo(T0, test##Size##DstValue); \
1243 test.setDqwordTo(T1, test##Size##SrcValue); \
1244 test.run(); \
1245 \
1246 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
1247 reset(); \
1248 } while (0)
1249
1250 #define TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther) \
1251 do { \
1252 static constexpr char NearBranch = AssemblerX8632::kNearJump; \
1253 static constexpr char TestString[] = \
1254 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #CompType \
1255 ", " #BParity ", " #BOther ")"; \
1256 const uint32_t T0 = allocateDqword(); \
1257 test##Size##DstValue.F##Size[0] = Value0; \
1258 const uint32_t T1 = allocateDqword(); \
1259 test##Size##SrcValue.F##Size[0] = Value1; \
1260 const uint32_t ImmIfTrue = 0xBEEF; \
1261 const uint32_t ImmIfFalse = 0xC0FFE; \
1262 \
1263 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1264 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
1265 __ ucomiss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1266 dwordAddress(T1)); \
1267 Label Done; \
1268 __ j(Cond::Br_##BParity, &Done, NearBranch); \
1269 __ j(Cond::Br_##BOther, &Done, NearBranch); \
1270 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
1271 __ bind(&Done); \
1272 \
1273 AssembledTest test = assemble(); \
1274 test.setDqwordTo(T0, test##Size##DstValue); \
1275 test.setDqwordTo(T1, test##Size##SrcValue); \
1276 test.run(); \
1277 \
1278 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
1279 reset(); \
1280 } while (0)
1281
1282 #define TestImplCond(Dst, Value0, Src, Value1, Size, CompType, BParity, \
1283 BOther) \
1284 do { \
1285 TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, BOther); \
1286 TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther); \
1287 } while (0)
1288
1289 #define TestImplSize(Dst, Src, Size) \
1290 do { \
1291 TestImplCond(Dst, 1.0, Src, 1.0, Size, isEq, p, ne); \
1292 TestImplCond(Dst, 1.0, Src, 2.0, Size, isNe, p, e); \
1293 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLe, p, a); \
1294 TestImplCond(Dst, 1.0, Src, 1.0, Size, isLe, p, a); \
1295 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLt, p, ae); \
1296 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGe, p, b); \
1297 TestImplCond(Dst, 1.0, Src, 1.0, Size, isGe, p, b); \
1298 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGt, p, be); \
1299 TestImplCond(Dst, qnan##Size, Src, 1.0, Size, isUnord, np, o); \
1300 TestImplCond(Dst, 1.0, Src, qnan##Size, Size, isUnord, np, s); \
1301 TestImplCond(Dst, qnan##Size, Src, qnan##Size, Size, isUnord, np, s); \
1302 } while (0)
1303
1304 #define TestImpl(Dst, Src) \
1305 do { \
1306 TestImplSize(Dst, Src, 32); \
1307 TestImplSize(Dst, Src, 64); \
1308 } while (0)
1309
1310 TestImpl(xmm0, xmm1);
1311 TestImpl(xmm1, xmm2);
1312 TestImpl(xmm2, xmm3);
1313 TestImpl(xmm3, xmm4);
1314 TestImpl(xmm4, xmm5);
1315 TestImpl(xmm5, xmm6);
1316 TestImpl(xmm6, xmm7);
1317 TestImpl(xmm7, xmm0);
1318
1319 #undef TestImpl
1320 #undef TestImplSize
1321 #undef TestImplCond
1322 #undef TestImplXmmAddr
1323 #undef TestImplXmmXmm
1324 }
1325
1326 TEST_F(AssemblerX8632Test, Sqrtss) {
1327 Dqword test32SrcValue(-100.0, -100.0, -100.0, -100.0);
1328 Dqword test32DstValue(-1.0, -1.0, -1.0, -1.0);
1329
1330 Dqword test64SrcValue(-100.0, -100.0);
1331 Dqword test64DstValue(-1.0, -1.0);
1332
1333 #define TestSqrtssXmmXmm(Dst, Src, Value1, Result, Size) \
1334 do { \
1335 static constexpr char TestString[] = \
1336 "(" #Dst ", " #Src ", " #Value1 ", " #Result ", " #Size ")"; \
1337 const uint32_t T0 = allocateDqword(); \
1338 test##Size##SrcValue.F##Size[0] = Value1; \
1339 const uint32_t T1 = allocateDqword(); \
1340 \
1341 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
1342 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
1343 __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1344 XmmRegister::Encoded_Reg_##Src); \
1345 \
1346 AssembledTest test = assemble(); \
1347 test.setDqwordTo(T0, test##Size##SrcValue); \
1348 test.setDqwordTo(T1, test##Size##DstValue); \
1349 test.run(); \
1350 \
1351 Dqword Expected = test##Size##DstValue; \
1352 Expected.F##Size[0] = Result; \
1353 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1354 reset(); \
1355 } while (0)
1356
1357 #define TestSqrtssXmmAddr(Dst, Value1, Result, Size) \
1358 do { \
1359 static constexpr char TestString[] = \
1360 "(" #Dst ", Addr, " #Value1 ", " #Result ", " #Size ")"; \
1361 const uint32_t T0 = allocateDqword(); \
1362 test##Size##SrcValue.F##Size[0] = Value1; \
1363 const uint32_t T1 = allocateDqword(); \
1364 \
1365 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \
1366 __ sqrtss(IceType_f##Size, XmmRegister::Encoded_Reg_##Dst, \
1367 dwordAddress(T0)); \
1368 \
1369 AssembledTest test = assemble(); \
1370 test.setDqwordTo(T0, test##Size##SrcValue); \
1371 test.setDqwordTo(T1, test##Size##DstValue); \
1372 test.run(); \
1373 \
1374 Dqword Expected = test##Size##DstValue; \
1375 Expected.F##Size[0] = Result; \
1376 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1377 reset(); \
1378 } while (0)
1379
1380 #define TestSqrtssSize(Dst, Src, Size) \
1381 do { \
1382 TestSqrtssXmmXmm(Dst, Src, 4.0, 2.0, Size); \
1383 TestSqrtssXmmAddr(Dst, 4.0, 2.0, Size); \
1384 TestSqrtssXmmXmm(Dst, Src, 9.0, 3.0, Size); \
1385 TestSqrtssXmmAddr(Dst, 9.0, 3.0, Size); \
1386 TestSqrtssXmmXmm(Dst, Src, 100.0, 10.0, Size); \
1387 TestSqrtssXmmAddr(Dst, 100.0, 10.0, Size); \
1388 } while (0)
1389
1390 #define TestSqrtss(Dst, Src) \
1391 do { \
1392 TestSqrtssSize(Dst, Src, 32); \
1393 TestSqrtssSize(Dst, Src, 64); \
1394 } while (0)
1395
1396 TestSqrtss(xmm0, xmm1);
1397 TestSqrtss(xmm1, xmm2);
1398 TestSqrtss(xmm2, xmm3);
1399 TestSqrtss(xmm3, xmm4);
1400 TestSqrtss(xmm4, xmm5);
1401 TestSqrtss(xmm5, xmm6);
1402 TestSqrtss(xmm6, xmm7);
1403 TestSqrtss(xmm7, xmm0);
1404
1405 #undef TestSqrtss
1406 #undef TestSqrtssSize
1407 #undef TestSqrtssXmmAddr
1408 #undef TestSqrtssXmmXmm
1409 }
1410
1411 TEST_F(AssemblerX8632Test, Insertps) {
1412 #define TestInsertpsXmmXmmImm(Dst, Value0, Src, Value1, Imm, Expected) \
1413 do { \
1414 static constexpr char TestString[] = \
1415 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Imm ", " #Expected \
1416 ")"; \
1417 const uint32_t T0 = allocateDqword(); \
1418 const Dqword V0 Value0; \
1419 const uint32_t T1 = allocateDqword(); \
1420 const Dqword V1 Value1; \
1421 \
1422 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1423 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
1424 __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##Dst, \
1425 XmmRegister::Encoded_Reg_##Src, Immediate(Imm)); \
1426 \
1427 AssembledTest test = assemble(); \
1428 test.setDqwordTo(T0, V0); \
1429 test.setDqwordTo(T1, V1); \
1430 test.run(); \
1431 \
1432 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
1433 reset(); \
1434 } while (0)
1435
1436 #define TestInsertpsXmmAddrImm(Dst, Value0, Value1, Imm, Expected) \
1437 do { \
1438 static constexpr char TestString[] = \
1439 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Expected ")"; \
1440 const uint32_t T0 = allocateDqword(); \
1441 const Dqword V0 Value0; \
1442 const uint32_t T1 = allocateDqword(); \
1443 const Dqword V1 Value1; \
1444 \
1445 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1446 __ insertps(IceType_v4f32, XmmRegister::Encoded_Reg_##Dst, \
1447 dwordAddress(T1), Immediate(Imm)); \
1448 \
1449 AssembledTest test = assemble(); \
1450 test.setDqwordTo(T0, V0); \
1451 test.setDqwordTo(T1, V1); \
1452 test.run(); \
1453 \
1454 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
1455 reset(); \
1456 } while (0)
1457
1458 #define TestInsertps(Dst, Src) \
1459 do { \
1460 TestInsertpsXmmXmmImm( \
1461 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
1462 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
1463 0x99, \
1464 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
1465 TestInsertpsXmmAddrImm( \
1466 Dst, (uint64_t(-1), uint64_t(-1)), \
1467 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
1468 0x99, \
1469 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
1470 TestInsertpsXmmXmmImm( \
1471 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
1472 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
1473 0x9D, \
1474 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x0000000000000000ull))); \
1475 TestInsertpsXmmAddrImm( \
1476 Dst, (uint64_t(-1), uint64_t(-1)), \
1477 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
1478 0x9D, \
1479 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x0000000000000000ull))); \
1480 } while (0)
1481
1482 TestInsertps(xmm0, xmm1);
1483 TestInsertps(xmm1, xmm2);
1484 TestInsertps(xmm2, xmm3);
1485 TestInsertps(xmm3, xmm4);
1486 TestInsertps(xmm4, xmm5);
1487 TestInsertps(xmm5, xmm6);
1488 TestInsertps(xmm6, xmm7);
1489 TestInsertps(xmm7, xmm0);
1490
1491 #undef TestInsertps
1492 #undef TestInsertpsXmmXmmAddr
1493 #undef TestInsertpsXmmXmmImm
1494 }
1495
1496 TEST_F(AssemblerX8632Test, Pinsr) {
1497 static constexpr uint8_t Mask32 = 0x03;
1498 static constexpr uint8_t Mask16 = 0x07;
1499 static constexpr uint8_t Mask8 = 0x0F;
1500
1501 #define TestPinsrXmmGPRImm(Dst, Value0, GPR, Value1, Imm, Size) \
1502 do { \
1503 static constexpr char TestString[] = \
1504 "(" #Dst ", " #Value0 ", " #GPR ", " #Value1 ", " #Imm ", " #Size ")"; \
1505 const uint32_t T0 = allocateDqword(); \
1506 const Dqword V0 Value0; \
1507 \
1508 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1509 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##GPR, Immediate(Value1)); \
1510 __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
1511 GPRRegister::Encoded_Reg_##GPR, Immediate(Imm)); \
1512 \
1513 AssembledTest test = assemble(); \
1514 test.setDqwordTo(T0, V0); \
1515 test.run(); \
1516 \
1517 constexpr uint8_t sel = (Imm)&Mask##Size; \
1518 Dqword Expected = V0; \
1519 Expected.U##Size[sel] = Value1; \
1520 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1521 reset(); \
1522 } while (0)
1523
1524 #define TestPinsrXmmAddrImm(Dst, Value0, Value1, Imm, Size) \
1525 do { \
1526 static constexpr char TestString[] = \
1527 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Size ")"; \
1528 const uint32_t T0 = allocateDqword(); \
1529 const Dqword V0 Value0; \
1530 const uint32_t T1 = allocateDword(); \
1531 const uint32_t V1 = Value1; \
1532 \
1533 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1534 __ pinsr(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
1535 dwordAddress(T1), Immediate(Imm)); \
1536 \
1537 AssembledTest test = assemble(); \
1538 test.setDqwordTo(T0, V0); \
1539 test.setDwordTo(T1, V1); \
1540 test.run(); \
1541 \
1542 constexpr uint8_t sel = (Imm)&Mask##Size; \
1543 Dqword Expected = V0; \
1544 Expected.U##Size[sel] = Value1; \
1545 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1546 reset(); \
1547 } while (0)
1548
1549 #define TestPinsrSize(Dst, GPR, Value1, Imm, Size) \
1550 do { \
1551 TestPinsrXmmGPRImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
1552 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
1553 GPR, Value1, Imm, Size); \
1554 TestPinsrXmmAddrImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
1555 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
1556 Value1, Imm, Size); \
1557 } while (0)
1558
1559 #define TestPinsr(Src, Dst) \
1560 do { \
1561 TestPinsrSize(Src, Dst, 0xEE, 0x03, 8); \
1562 TestPinsrSize(Src, Dst, 0xFFEE, 0x03, 16); \
1563 TestPinsrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
1564 } while (0)
1565
1566 TestPinsr(xmm0, eax);
1567 TestPinsr(xmm1, ebx);
1568 TestPinsr(xmm2, ecx);
1569 TestPinsr(xmm3, edx);
1570 TestPinsr(xmm4, esi);
1571 TestPinsr(xmm5, edi);
1572 TestPinsr(xmm6, eax);
1573 TestPinsr(xmm7, ebx);
1574
1575 #undef TestPinsr
1576 #undef TestPinsrSize
1577 #undef TestPinsrXmmAddrImm
1578 #undef TestPinsrXmmGPRImm
1579 }
1580
1581 TEST_F(AssemblerX8632Test, Pextr) {
1582 static constexpr uint8_t Mask32 = 0x03;
1583 static constexpr uint8_t Mask16 = 0x07;
1584 static constexpr uint8_t Mask8 = 0x0F;
1585
1586 #define TestPextrGPRXmmImm(GPR, Src, Value1, Imm, Size) \
1587 do { \
1588 static constexpr char TestString[] = \
1589 "(" #GPR ", " #Src ", " #Value1 ", " #Imm ", " #Size ")"; \
1590 const uint32_t T0 = allocateDqword(); \
1591 const Dqword V0 Value1; \
1592 \
1593 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \
1594 __ pextr(IceType_i##Size, GPRRegister::Encoded_Reg_##GPR, \
1595 XmmRegister::Encoded_Reg_##Src, Immediate(Imm)); \
1596 \
1597 AssembledTest test = assemble(); \
1598 test.setDqwordTo(T0, V0); \
1599 test.run(); \
1600 \
1601 constexpr uint8_t sel = (Imm)&Mask##Size; \
1602 ASSERT_EQ(V0.U##Size[sel], test.GPR()) << TestString; \
1603 reset(); \
1604 } while (0)
1605
1606 #define TestPextrSize(GPR, Src, Value1, Imm, Size) \
1607 do { \
1608 TestPextrGPRXmmImm(GPR, Src, (uint64_t(0xAAAAAAAABBBBBBBBull), \
1609 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
1610 Imm, Size); \
1611 } while (0)
1612
1613 #define TestPextr(Src, Dst) \
1614 do { \
1615 TestPextrSize(Src, Dst, 0xEE, 0x03, 8); \
1616 TestPextrSize(Src, Dst, 0xFFEE, 0x03, 16); \
1617 TestPextrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
1618 } while (0)
1619
1620 TestPextr(eax, xmm0);
1621 TestPextr(ebx, xmm1);
1622 TestPextr(ecx, xmm2);
1623 TestPextr(edx, xmm3);
1624 TestPextr(esi, xmm4);
1625 TestPextr(edi, xmm5);
1626 TestPextr(eax, xmm6);
1627 TestPextr(ebx, xmm7);
1628
1629 #undef TestPextr
1630 #undef TestPextrSize
1631 #undef TestPextrXmmGPRImm
1632 }
1633
1634 TEST_F(AssemblerX8632Test, Pcmpeq_Pcmpgt) {
1635 #define TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, Inst, Op) \
1636 do { \
1637 static constexpr char TestString[] = \
1638 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #Op ")"; \
1639 const uint32_t T0 = allocateDqword(); \
1640 const Dqword V0 Value0; \
1641 const uint32_t T1 = allocateDqword(); \
1642 const Dqword V1 Value1; \
1643 \
1644 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1645 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
1646 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
1647 XmmRegister::Encoded_Reg_##Src); \
1648 \
1649 AssembledTest test = assemble(); \
1650 test.setDqwordTo(T0, V0); \
1651 test.setDqwordTo(T1, V1); \
1652 test.run(); \
1653 \
1654 Dqword Expected(uint64_t(0), uint64_t(0)); \
1655 static constexpr uint8_t ArraySize = \
1656 sizeof(Dqword) / sizeof(uint##Size##_t); \
1657 for (uint8_t i = 0; i < ArraySize; ++i) { \
1658 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
1659 } \
1660 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1661 reset(); \
1662 } while (0)
1663
1664 #define TestPcmpXmmAddr(Dst, Value0, Value1, Size, Inst, Op) \
1665 do { \
1666 static constexpr char TestString[] = \
1667 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #Op ")"; \
1668 const uint32_t T0 = allocateDqword(); \
1669 const Dqword V0 Value0; \
1670 const uint32_t T1 = allocateDqword(); \
1671 const Dqword V1 Value1; \
1672 \
1673 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1674 __ Inst(IceType_i##Size, XmmRegister::Encoded_Reg_##Dst, \
1675 dwordAddress(T1)); \
1676 \
1677 AssembledTest test = assemble(); \
1678 test.setDqwordTo(T0, V0); \
1679 test.setDqwordTo(T1, V1); \
1680 test.run(); \
1681 \
1682 Dqword Expected(uint64_t(0), uint64_t(0)); \
1683 static constexpr uint8_t ArraySize = \
1684 sizeof(Dqword) / sizeof(uint##Size##_t); \
1685 for (uint8_t i = 0; i < ArraySize; ++i) { \
1686 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
1687 } \
1688 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1689 reset(); \
1690 } while (0)
1691
1692 #define TestPcmpValues(Dst, Value0, Src, Value1, Size) \
1693 do { \
1694 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpeq, == ); \
1695 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpeq, == ); \
1696 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpgt, < ); \
1697 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpgt, < ); \
1698 } while (0)
1699
1700 #define TestPcmpSize(Dst, Src, Size) \
1701 do { \
1702 TestPcmpValues(Dst, (uint64_t(0x8888888888888888ull), \
1703 uint64_t(0x0000000000000000ull)), \
1704 Src, (uint64_t(0x0000008800008800ull), \
1705 uint64_t(0xFFFFFFFFFFFFFFFFull)), \
1706 Size); \
1707 TestPcmpValues(Dst, (uint64_t(0x123567ABAB55DE01ull), \
1708 uint64_t(0x12345abcde12345Aull)), \
1709 Src, (uint64_t(0x0000008800008800ull), \
1710 uint64_t(0xAABBCCDD1234321Aull)), \
1711 Size); \
1712 } while (0)
1713
1714 #define TestPcmp(Dst, Src) \
1715 do { \
1716 TestPcmpSize(xmm0, xmm1, 8); \
1717 TestPcmpSize(xmm0, xmm1, 16); \
1718 TestPcmpSize(xmm0, xmm1, 32); \
1719 } while (0)
1720
1721 TestPcmp(xmm0, xmm1);
1722 TestPcmp(xmm1, xmm2);
1723 TestPcmp(xmm2, xmm3);
1724 TestPcmp(xmm3, xmm4);
1725 TestPcmp(xmm4, xmm5);
1726 TestPcmp(xmm5, xmm6);
1727 TestPcmp(xmm6, xmm7);
1728 TestPcmp(xmm7, xmm0);
1729
1730 #undef TestPcmp
1731 #undef TestPcmpSize
1732 #undef TestPcmpValues
1733 #undef TestPcmpXmmAddr
1734 #undef TestPcmpXmmXmm
1735 }
1736
1737 TEST_F(AssemblerX8632Test, Roundsd) {
1738 #define TestRoundsdXmmXmm(Dst, Src, Mode, Input, RN) \
1739 do { \
1740 static constexpr char TestString[] = \
1741 "(" #Dst ", " #Src ", " #Mode ", " #Input ", " #RN ")"; \
1742 const uint32_t T0 = allocateDqword(); \
1743 const Dqword V0(-3.0, -3.0); \
1744 const uint32_t T1 = allocateDqword(); \
1745 const Dqword V1(double(Input), -123.4); \
1746 \
1747 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \
1748 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \
1749 __ roundsd(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src, \
1750 AssemblerX8632::k##Mode); \
1751 \
1752 AssembledTest test = assemble(); \
1753 test.setDqwordTo(T0, V0); \
1754 test.setDqwordTo(T1, V1); \
1755 test.run(); \
1756 \
1757 const Dqword Expected(double(RN), -3.0); \
1758 EXPECT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
1759 reset(); \
1760 } while (0)
1761
1762 #define TestRoundsd(Dst, Src) \
1763 do { \
1764 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.51, 6); \
1765 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.49, 5); \
1766 TestRoundsdXmmXmm(Dst, Src, RoundDown, 5.51, 5); \
1767 TestRoundsdXmmXmm(Dst, Src, RoundUp, 5.49, 6); \
1768 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.49, 5); \
1769 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.51, 5); \
1770 } while (0)
1771
1772 TestRoundsd(xmm0, xmm1);
1773 TestRoundsd(xmm1, xmm2);
1774 TestRoundsd(xmm2, xmm3);
1775 TestRoundsd(xmm3, xmm4);
1776 TestRoundsd(xmm4, xmm5);
1777 TestRoundsd(xmm5, xmm6);
1778 TestRoundsd(xmm6, xmm7);
1779 TestRoundsd(xmm7, xmm0);
1780
1781 #undef TestRoundsd
1782 #undef TestRoundsdXmmXmm
1783 }
1784
1785 TEST_F(AssemblerX8632Test, Set1ps) {
1786 #define TestImpl(Xmm, Src, Imm) \
1787 do { \
1788 __ set1ps(XmmRegister::Encoded_Reg_##Xmm, GPRRegister::Encoded_Reg_##Src, \
1789 Immediate(Imm)); \
1790 \
1791 AssembledTest test = assemble(); \
1792 test.run(); \
1793 \
1794 const Dqword Expected((uint64_t(Imm) << 32) | uint32_t(Imm), \
1795 (uint64_t(Imm) << 32) | uint32_t(Imm)); \
1796 ASSERT_EQ(Expected, test.Xmm<Dqword>()) \
1797 << "(" #Xmm ", " #Src ", " #Imm ")"; \
1798 reset(); \
1799 } while (0)
1800
1801 TestImpl(xmm0, ebx, 1);
1802 TestImpl(xmm1, ecx, 2);
1803 TestImpl(xmm2, edx, 3);
1804 TestImpl(xmm3, esi, 4);
1805 TestImpl(xmm4, edi, 5);
1806 TestImpl(xmm5, eax, 6);
1807 TestImpl(xmm6, ebx, 7);
1808 TestImpl(xmm7, ecx, 8);
1809
1810 #undef TestImpl
1811 }
1812
1813 } // end of anonymous namespace
1814 } // end of namespace Test
1815 } // end of namespace X8632
1816 } // end of namespace Ice
OLDNEW
« no previous file with comments | « unittest/AssemblerX8632/X87.cpp ('k') | unittest/AssemblerX8664/ControlFlow.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698