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

Side by Side Diff: unittest/IceAssemblerX8664Test.cpp

Issue 1224173006: Adds the x86-64 assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: 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
OLDNEW
(Empty)
1 //===- subzero/unittest/IceAssemblerX8664.cpp - X8664 Assembler tests -----===//
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
10 #include "IceAssemblerX8664.h"
11
12 #include "IceDefs.h"
13
14 #include "gtest/gtest.h"
15
16 #include <algorithm>
17 #include <cstring>
18 #include <errno.h>
19 #include <iostream>
20 #include <limits>
21 #include <memory>
22 #include <sys/mman.h>
23 #include <type_traits>
24
25 namespace Ice {
26 namespace X8664 {
27 namespace {
28 class AssemblerX8664TestBase : public ::testing::Test {
29 protected:
30 using Address = AssemblerX8664::Traits::Address;
31 using ByteRegister = AssemblerX8664::Traits::ByteRegister;
32 using Cond = AssemblerX8664::Traits::Cond;
33 using GPRRegister = AssemblerX8664::Traits::GPRRegister;
34 using Traits = AssemblerX8664::Traits;
35 using XmmRegister = AssemblerX8664::Traits::XmmRegister;
36
37 // The following are "nicknames" for all possible GPRs in x86-64. With those, we
38 // can use, e.g.,
39 //
40 // Encoded_GPR_al()
41 //
42 // instead of GPRRegister::Encoded_Reg_eax for 8 bit operands. They also
43 // introduce "regular" nicknames for legacy x86-32 register (e.g., eax becomes
44 // r1; esp, r0).
45 #define LegacyRegAliases(NewName, Name64, Name32, Name16, Name8) \
46 static constexpr GPRRegister Encoded_GPR_##NewName() { \
47 return GPRRegister::Encoded_Reg_##Name32; \
48 } \
49 static constexpr GPRRegister Encoded_GPR_##NewName##q() { \
50 return GPRRegister::Encoded_Reg_##Name32; \
51 } \
52 static constexpr GPRRegister Encoded_GPR_##NewName##d() { \
53 return GPRRegister::Encoded_Reg_##Name32; \
54 } \
55 static constexpr GPRRegister Encoded_GPR_##NewName##w() { \
56 return GPRRegister::Encoded_Reg_##Name32; \
57 } \
58 static constexpr GPRRegister Encoded_GPR_##NewName##l() { \
59 return GPRRegister::Encoded_Reg_##Name32; \
60 } \
61 static constexpr GPRRegister Encoded_GPR_##Name64() { \
62 return GPRRegister::Encoded_Reg_##Name32; \
63 } \
64 static constexpr GPRRegister Encoded_GPR_##Name32() { \
65 return GPRRegister::Encoded_Reg_##Name32; \
66 } \
67 static constexpr GPRRegister Encoded_GPR_##Name16() { \
68 return GPRRegister::Encoded_Reg_##Name32; \
69 } \
70 static constexpr GPRRegister Encoded_GPR_##Name8() { \
71 return GPRRegister::Encoded_Reg_##Name32; \
72 }
73 #define NewRegAliases(Name) \
74 static constexpr GPRRegister Encoded_GPR_##Name() { \
75 return GPRRegister::Encoded_Reg_##Name##d; \
76 } \
77 static constexpr GPRRegister Encoded_GPR_##Name##q() { \
78 return GPRRegister::Encoded_Reg_##Name##d; \
79 } \
80 static constexpr GPRRegister Encoded_GPR_##Name##d() { \
81 return GPRRegister::Encoded_Reg_##Name##d; \
82 } \
83 static constexpr GPRRegister Encoded_GPR_##Name##w() { \
84 return GPRRegister::Encoded_Reg_##Name##d; \
85 } \
86 static constexpr GPRRegister Encoded_GPR_##Name##l() { \
87 return GPRRegister::Encoded_Reg_##Name##d; \
88 }
89 #define XmmRegAliases(Name) \
90 static constexpr XmmRegister Encoded_Xmm_##Name() { \
91 return XmmRegister::Encoded_Reg_##Name; \
92 }
93 LegacyRegAliases(r0, rsp, esp, sp, spl);
94 LegacyRegAliases(r1, rax, eax, ax, al);
95 LegacyRegAliases(r2, rbx, ebx, bx, bl);
96 LegacyRegAliases(r3, rcx, ecx, cx, cl);
97 LegacyRegAliases(r4, rdx, edx, dx, dl);
98 LegacyRegAliases(r5, rbp, ebp, bp, bpl);
99 LegacyRegAliases(r6, rsi, esi, si, sil);
100 LegacyRegAliases(r7, rdi, edi, di, dil);
101 NewRegAliases(r8);
102 NewRegAliases(r9);
103 NewRegAliases(r10);
104 NewRegAliases(r11);
105 NewRegAliases(r12);
106 NewRegAliases(r13);
107 NewRegAliases(r14);
108 NewRegAliases(r15);
109 XmmRegAliases(xmm0);
110 XmmRegAliases(xmm1);
111 XmmRegAliases(xmm2);
112 XmmRegAliases(xmm3);
113 XmmRegAliases(xmm4);
114 XmmRegAliases(xmm5);
115 XmmRegAliases(xmm6);
116 XmmRegAliases(xmm7);
117 XmmRegAliases(xmm8);
118 XmmRegAliases(xmm9);
119 XmmRegAliases(xmm10);
120 XmmRegAliases(xmm11);
121 XmmRegAliases(xmm12);
122 XmmRegAliases(xmm13);
123 XmmRegAliases(xmm14);
124 XmmRegAliases(xmm15);
125 #undef XmmRegAliases
126 #undef NewRegAliases
127 #undef LegacyRegAliases
128
129 AssemblerX8664TestBase() { reset(); }
130
131 void reset() { Assembler.reset(new AssemblerX8664()); }
132
133 AssemblerX8664 *assembler() const { return Assembler.get(); }
134
135 size_t codeBytesSize() const { return Assembler->getBufferView().size(); }
136
137 const uint8_t *codeBytes() const {
138 return static_cast<const uint8_t *>(
139 static_cast<const void *>(Assembler->getBufferView().data()));
140 }
141
142 private:
143 std::unique_ptr<AssemblerX8664> Assembler;
144 };
145
146 // __ is a helper macro. It allows test cases to emit X8664 assembly
147 // instructions with
148 //
149 // __ mov(GPRRegister::Reg_Eax, 1);
150 // __ ret();
151 //
152 // and so on. The idea of having this was "stolen" from dart's unit tests.
153 #define __ (this->assembler())->
154
155 // AssemblerX8664LowLevelTest verify that the "basic" instructions the tests
156 // rely on are encoded correctly. Therefore, instead of executing the assembled
157 // code, these tests will verify that the assembled bytes are sane.
158 class AssemblerX8664LowLevelTest : public AssemblerX8664TestBase {
159 protected:
160 // verifyBytes is a template helper that takes a Buffer, and a variable number
161 // of bytes. As the name indicates, it is used to verify the bytes for an
162 // instruction encoding.
163 template <int N, int I> static bool verifyBytes(const uint8_t *) {
164 static_assert(I == N, "Invalid template instantiation.");
165 return true;
166 }
167
168 template <int N, int I = 0, typename... Args>
169 static bool verifyBytes(const uint8_t *Buffer, uint8_t Byte,
170 Args... OtherBytes) {
171 static_assert(I < N, "Invalid template instantiation.");
172 EXPECT_EQ(Byte, Buffer[I]) << "Byte " << (I + 1) << " of " << N;
173 return verifyBytes<N, I + 1>(Buffer, OtherBytes...) && Buffer[I] == Byte;
174 }
175 };
176
177 TEST_F(AssemblerX8664LowLevelTest, Ret) {
178 __ ret();
179
180 constexpr size_t ByteCount = 1;
181 ASSERT_EQ(ByteCount, codeBytesSize());
182
183 verifyBytes<ByteCount>(codeBytes(), 0xc3);
184 }
185
186 TEST_F(AssemblerX8664LowLevelTest, RetImm) {
187 __ ret(Immediate(0x20));
188
189 constexpr size_t ByteCount = 3;
190 ASSERT_EQ(ByteCount, codeBytesSize());
191
192 verifyBytes<ByteCount>(codeBytes(), 0xC2, 0x20, 0x00);
193 }
194
195 TEST_F(AssemblerX8664LowLevelTest, CallImm4) {
196 __ call(Immediate(4));
197
198 constexpr size_t ByteCount = 5;
199 ASSERT_EQ(ByteCount, codeBytesSize());
200
201 verifyBytes<ByteCount>(codeBytes(), 0xe8, 0x00, 0x00, 0x00, 0x00);
202 }
203
204 TEST_F(AssemblerX8664LowLevelTest, PopRegs) {
205 __ popl(Encoded_GPR_eax());
206 __ popl(Encoded_GPR_ebx());
207 __ popl(Encoded_GPR_ecx());
208 __ popl(Encoded_GPR_edx());
209 __ popl(Encoded_GPR_edi());
210 __ popl(Encoded_GPR_esi());
211 __ popl(Encoded_GPR_ebp());
212 __ popl(Encoded_GPR_r8());
213 __ popl(Encoded_GPR_r9());
214 __ popl(Encoded_GPR_r10());
215 __ popl(Encoded_GPR_r11());
216 __ popl(Encoded_GPR_r12());
217 __ popl(Encoded_GPR_r13());
218 __ popl(Encoded_GPR_r14());
219 __ popl(Encoded_GPR_r15());
220
221 constexpr size_t ByteCount = 23;
222 ASSERT_EQ(ByteCount, codeBytesSize());
223
224 constexpr uint8_t Rex_B = 0x41;
225 constexpr uint8_t PopOpcode = 0x58;
226 verifyBytes<ByteCount>(
227 codeBytes(), PopOpcode | Encoded_GPR_eax(), PopOpcode | Encoded_GPR_ebx(),
228 PopOpcode | Encoded_GPR_ecx(), PopOpcode | Encoded_GPR_edx(),
229 PopOpcode | Encoded_GPR_edi(), PopOpcode | Encoded_GPR_esi(),
230 PopOpcode | Encoded_GPR_ebp(), Rex_B, PopOpcode | (Encoded_GPR_r8() & 7),
231 Rex_B, PopOpcode | (Encoded_GPR_r9() & 7), Rex_B,
232 PopOpcode | (Encoded_GPR_r10() & 7), Rex_B,
233 PopOpcode | (Encoded_GPR_r11() & 7), Rex_B,
234 PopOpcode | (Encoded_GPR_r12() & 7), Rex_B,
235 PopOpcode | (Encoded_GPR_r13() & 7), Rex_B,
236 PopOpcode | (Encoded_GPR_r14() & 7), Rex_B,
237 PopOpcode | (Encoded_GPR_r15() & 7));
238 }
239
240 TEST_F(AssemblerX8664LowLevelTest, PushRegs) {
241 __ pushl(Encoded_GPR_eax());
242 __ pushl(Encoded_GPR_ebx());
243 __ pushl(Encoded_GPR_ecx());
244 __ pushl(Encoded_GPR_edx());
245 __ pushl(Encoded_GPR_edi());
246 __ pushl(Encoded_GPR_esi());
247 __ pushl(Encoded_GPR_ebp());
248 __ pushl(Encoded_GPR_r8());
249 __ pushl(Encoded_GPR_r9());
250 __ pushl(Encoded_GPR_r10());
251 __ pushl(Encoded_GPR_r11());
252 __ pushl(Encoded_GPR_r12());
253 __ pushl(Encoded_GPR_r13());
254 __ pushl(Encoded_GPR_r14());
255 __ pushl(Encoded_GPR_r15());
256
257 constexpr size_t ByteCount = 23;
258 ASSERT_EQ(ByteCount, codeBytesSize());
259
260 constexpr uint8_t Rex_B = 0x41;
261 constexpr uint8_t PushOpcode = 0x50;
262 verifyBytes<ByteCount>(
263 codeBytes(), PushOpcode | Encoded_GPR_eax(),
264 PushOpcode | Encoded_GPR_ebx(), PushOpcode | Encoded_GPR_ecx(),
265 PushOpcode | Encoded_GPR_edx(), PushOpcode | Encoded_GPR_edi(),
266 PushOpcode | Encoded_GPR_esi(), PushOpcode | Encoded_GPR_ebp(), Rex_B,
267 PushOpcode | (Encoded_GPR_r8() & 7), Rex_B,
268 PushOpcode | (Encoded_GPR_r9() & 7), Rex_B,
269 PushOpcode | (Encoded_GPR_r10() & 7), Rex_B,
270 PushOpcode | (Encoded_GPR_r11() & 7), Rex_B,
271 PushOpcode | (Encoded_GPR_r12() & 7), Rex_B,
272 PushOpcode | (Encoded_GPR_r13() & 7), Rex_B,
273 PushOpcode | (Encoded_GPR_r14() & 7), Rex_B,
274 PushOpcode | (Encoded_GPR_r15() & 7));
275 }
276
277 TEST_F(AssemblerX8664LowLevelTest, MovRegisterZero) {
278 __ mov(IceType_i32, Encoded_GPR_eax(), Immediate(0x00));
279 __ mov(IceType_i32, Encoded_GPR_ebx(), Immediate(0x00));
280 __ mov(IceType_i32, Encoded_GPR_ecx(), Immediate(0x00));
281 __ mov(IceType_i32, Encoded_GPR_edx(), Immediate(0x00));
282 __ mov(IceType_i32, Encoded_GPR_edi(), Immediate(0x00));
283 __ mov(IceType_i32, Encoded_GPR_esi(), Immediate(0x00));
284 __ mov(IceType_i32, Encoded_GPR_ebp(), Immediate(0x00));
285 __ mov(IceType_i32, Encoded_GPR_r8(), Immediate(0x00));
286 __ mov(IceType_i32, Encoded_GPR_r10(), Immediate(0x00));
287 __ mov(IceType_i32, Encoded_GPR_r11(), Immediate(0x00));
288 __ mov(IceType_i32, Encoded_GPR_r12(), Immediate(0x00));
289 __ mov(IceType_i32, Encoded_GPR_r13(), Immediate(0x00));
290 __ mov(IceType_i32, Encoded_GPR_r14(), Immediate(0x00));
291 __ mov(IceType_i32, Encoded_GPR_r15(), Immediate(0x00));
292
293 constexpr uint8_t Rex_B = 0x41;
294 constexpr size_t MovReg32BitImmBytes = 5;
295 constexpr size_t ByteCount = 14 * MovReg32BitImmBytes + 7 /*Rex_B*/;
296
297 ASSERT_EQ(ByteCount, codeBytesSize());
298
299 constexpr uint8_t MovOpcode = 0xb8;
300 verifyBytes<ByteCount>(
301 codeBytes(), MovOpcode | Encoded_GPR_eax(), 0x00, 0x00, 0x00, 0x00,
302 MovOpcode | Encoded_GPR_ebx(), 0x00, 0x00, 0x00, 0x00,
303 MovOpcode | Encoded_GPR_ecx(), 0x00, 0x00, 0x00, 0x00,
304 MovOpcode | Encoded_GPR_edx(), 0x00, 0x00, 0x00, 0x00,
305 MovOpcode | Encoded_GPR_edi(), 0x00, 0x00, 0x00, 0x00,
306 MovOpcode | Encoded_GPR_esi(), 0x00, 0x00, 0x00, 0x00,
307 MovOpcode | Encoded_GPR_ebp(), 0x00, 0x00, 0x00, 0x00, Rex_B,
308 MovOpcode | (Encoded_GPR_r8() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
309 MovOpcode | (Encoded_GPR_r10() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
310 MovOpcode | (Encoded_GPR_r11() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
311 MovOpcode | (Encoded_GPR_r12() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
312 MovOpcode | (Encoded_GPR_r13() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
313 MovOpcode | (Encoded_GPR_r14() & 7), 0x00, 0x00, 0x00, 0x00, Rex_B,
314 MovOpcode | (Encoded_GPR_r15() & 7), 0x00, 0x00, 0x00, 0x00);
315 }
316
317 TEST_F(AssemblerX8664LowLevelTest, Cmp) {
318 #define TestRegReg(Inst, Dst, Src, OpType, ByteCountUntyped, ...) \
319 do { \
320 static constexpr char TestString[] = \
321 "(" #Inst ", " #Dst ", " #Src ", " #OpType ", " #ByteCountUntyped \
322 ", " #__VA_ARGS__ ")"; \
323 static constexpr uint8_t ByteCount = ByteCountUntyped; \
324 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
325 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
326 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
327 << TestString; \
328 reset(); \
329 } while (0)
330
331 #define TestRegImm(Inst, Dst, Imm, OpType, ByteCountUntyped, ...) \
332 do { \
333 static constexpr char TestString[] = \
334 "(" #Inst ", " #Dst ", " #Imm ", " #OpType ", " #ByteCountUntyped \
335 ", " #__VA_ARGS__ ")"; \
336 static constexpr uint8_t ByteCount = ByteCountUntyped; \
337 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), Immediate(Imm)); \
338 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
339 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
340 << TestString; \
341 reset(); \
342 } while (0)
343
344 #define TestRegAbsoluteAddr(Inst, Dst, Disp, OpType, ByteCountUntyped, ...) \
345 do { \
346 static constexpr char TestString[] = \
347 "(" #Inst ", " #Dst ", " #Disp ", " #OpType ", " #ByteCountUntyped \
348 ", " #__VA_ARGS__ ")"; \
349 static constexpr uint8_t ByteCount = ByteCountUntyped; \
350 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
351 Address(Address::ABSOLUTE, Disp)); \
352 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
353 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
354 << TestString; \
355 reset(); \
356 } while (0)
357
358 #define TestRegAddrBase(Inst, Dst, Base, Disp, OpType, ByteCountUntyped, ...) \
359 do { \
360 static constexpr char TestString[] = \
361 "(" #Inst ", " #Dst ", " #Base ", " #Disp ", " #OpType \
362 ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
363 static constexpr uint8_t ByteCount = ByteCountUntyped; \
364 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
365 Address(Encoded_GPR_##Base(), Disp)); \
366 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
367 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
368 << TestString; \
369 reset(); \
370 } while (0)
371
372 #define TestRegAddrScaledIndex(Inst, Dst, Index, Scale, Disp, OpType, \
373 ByteCountUntyped, ...) \
374 do { \
375 static constexpr char TestString[] = \
376 "(" #Inst ", " #Dst ", " #Index ", " #Scale ", " #Disp ", " #OpType \
377 ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
378 static constexpr uint8_t ByteCount = ByteCountUntyped; \
379 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
380 Address(Encoded_GPR_##Index(), Traits::TIMES_##Scale, Disp)); \
381 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
382 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
383 << TestString; \
384 reset(); \
385 } while (0)
386
387 #define TestRegAddrBaseScaledIndex(Inst, Dst, Base, Index, Scale, Disp, \
388 OpType, ByteCountUntyped, ...) \
389 do { \
390 static constexpr char TestString[] = \
391 "(" #Inst ", " #Dst ", " #Base ", " #Index ", " #Scale ", " #Disp \
392 ", " #OpType ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
393 static constexpr uint8_t ByteCount = ByteCountUntyped; \
394 __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
395 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
396 Traits::TIMES_##Scale, Disp)); \
397 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
398 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
399 << TestString; \
400 reset(); \
401 } while (0)
402
403 #define TestAddrBaseScaledIndexImm(Inst, Base, Index, Scale, Disp, Imm, \
404 OpType, ByteCountUntyped, ...) \
405 do { \
406 static constexpr char TestString[] = \
407 "(" #Inst ", " #Base ", " #Index ", " #Scale ", " #Disp ", " #Imm \
408 ", " #OpType ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
409 static constexpr uint8_t ByteCount = ByteCountUntyped; \
410 __ Inst(IceType_##OpType, \
411 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
412 Traits::TIMES_##Scale, Disp), \
413 Immediate(Imm)); \
414 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
415 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
416 << TestString; \
417 reset(); \
418 } while (0)
419
420 #define TestAddrBaseScaledIndexReg(Inst, Base, Index, Scale, Disp, Src, \
421 OpType, ByteCountUntyped, ...) \
422 do { \
423 static constexpr char TestString[] = \
424 "(" #Inst ", " #Base ", " #Index ", " #Scale ", " #Disp ", " #Src \
425 ", " #OpType ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
426 static constexpr uint8_t ByteCount = ByteCountUntyped; \
427 __ Inst(IceType_##OpType, \
428 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
429 Traits::TIMES_##Scale, Disp), \
430 Encoded_GPR_##Src()); \
431 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
432 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
433 << TestString; \
434 reset(); \
435 } while (0)
436
437 /* cmp GPR, GPR */
438 TestRegReg(cmp, eax, ecx, i32, 2, 0x3B, 0xC1);
439 TestRegReg(cmp, ecx, edx, i32, 2, 0x3B, 0xCA);
440 TestRegReg(cmp, edx, ebx, i32, 2, 0x3B, 0xD3);
441 TestRegReg(cmp, ebx, esp, i32, 2, 0x3B, 0xDC);
442 TestRegReg(cmp, esp, ebp, i32, 2, 0x3B, 0xE5);
443 TestRegReg(cmp, ebp, esi, i32, 2, 0x3B, 0xEE);
444 TestRegReg(cmp, esi, edi, i32, 2, 0x3B, 0xF7);
445 TestRegReg(cmp, edi, r8, i32, 3, 0x41, 0x3B, 0xF8);
446 TestRegReg(cmp, r8, r9, i32, 3, 0x45, 0x3B, 0xC1);
447 TestRegReg(cmp, r9, r10, i32, 3, 0x45, 0x3B, 0xCA);
448 TestRegReg(cmp, r10, r11, i32, 3, 0x45, 0x3B, 0xD3);
449 TestRegReg(cmp, r11, r12, i32, 3, 0x45, 0x3B, 0xDC);
450 TestRegReg(cmp, r12, r13, i32, 3, 0x45, 0x3B, 0xE5);
451 TestRegReg(cmp, r13, r14, i32, 3, 0x45, 0x3B, 0xEE);
452 TestRegReg(cmp, r14, r15, i32, 3, 0x45, 0x3B, 0xF7);
453 TestRegReg(cmp, r15, eax, i32, 3, 0x44, 0x3B, 0xF8);
454
455 TestRegReg(cmp, eax, ecx, i16, 3, 0x66, 0x3B, 0xC1);
456 TestRegReg(cmp, ecx, edx, i16, 3, 0x66, 0x3B, 0xCA);
457 TestRegReg(cmp, edx, ebx, i16, 3, 0x66, 0x3B, 0xD3);
458 TestRegReg(cmp, ebx, esp, i16, 3, 0x66, 0x3B, 0xDC);
459 TestRegReg(cmp, esp, ebp, i16, 3, 0x66, 0x3B, 0xE5);
460 TestRegReg(cmp, ebp, esi, i16, 3, 0x66, 0x3B, 0xEE);
461 TestRegReg(cmp, esi, edi, i16, 3, 0x66, 0x3B, 0xF7);
462 TestRegReg(cmp, edi, r8, i16, 4, 0x66, 0x41, 0x3B, 0xF8);
463 TestRegReg(cmp, r8, r9, i16, 4, 0x66, 0x45, 0x3B, 0xC1);
464 TestRegReg(cmp, r9, r10, i16, 4, 0x66, 0x45, 0x3B, 0xCA);
465 TestRegReg(cmp, r10, r11, i16, 4, 0x66, 0x45, 0x3B, 0xD3);
466 TestRegReg(cmp, r11, r12, i16, 4, 0x66, 0x45, 0x3B, 0xDC);
467 TestRegReg(cmp, r12, r13, i16, 4, 0x66, 0x45, 0x3B, 0xE5);
468 TestRegReg(cmp, r13, r14, i16, 4, 0x66, 0x45, 0x3B, 0xEE);
469 TestRegReg(cmp, r14, r15, i16, 4, 0x66, 0x45, 0x3B, 0xF7);
470 TestRegReg(cmp, r15, eax, i16, 4, 0x66, 0x44, 0x3B, 0xF8);
471
472 TestRegReg(cmp, eax, ecx, i8, 2, 0x3A, 0xC1);
473 TestRegReg(cmp, ecx, edx, i8, 2, 0x3A, 0xCA);
474 TestRegReg(cmp, edx, ebx, i8, 2, 0x3A, 0xD3);
475 TestRegReg(cmp, ebx, esp, i8, 3, 0x40, 0x3A, 0xDC);
476 TestRegReg(cmp, esp, ebp, i8, 3, 0x40, 0x3A, 0xE5);
477 TestRegReg(cmp, ebp, esi, i8, 3, 0x40, 0x3A, 0xEE);
478 TestRegReg(cmp, esi, edi, i8, 3, 0x40, 0x3A, 0xF7);
479 TestRegReg(cmp, edi, r8, i8, 3, 0x41, 0x3A, 0xF8);
480 TestRegReg(cmp, r8, r9, i8, 3, 0x45, 0x3A, 0xC1);
481 TestRegReg(cmp, r9, r10, i8, 3, 0x45, 0x3A, 0xCA);
482 TestRegReg(cmp, r10, r11, i8, 3, 0x45, 0x3A, 0xD3);
483 TestRegReg(cmp, r11, r12, i8, 3, 0x45, 0x3A, 0xDC);
484 TestRegReg(cmp, r12, r13, i8, 3, 0x45, 0x3A, 0xE5);
485 TestRegReg(cmp, r13, r14, i8, 3, 0x45, 0x3A, 0xEE);
486 TestRegReg(cmp, r14, r15, i8, 3, 0x45, 0x3A, 0xF7);
487 TestRegReg(cmp, r15, eax, i8, 3, 0x44, 0x3A, 0xF8);
488
489 /* cmp GPR, Imm8 */
490 TestRegImm(cmp, eax, 5, i32, 3, 0x83, 0xF8, 0x05);
491 TestRegImm(cmp, ecx, 5, i32, 3, 0x83, 0xF9, 0x05);
492 TestRegImm(cmp, edx, 5, i32, 3, 0x83, 0xFA, 0x05);
493 TestRegImm(cmp, ebx, 5, i32, 3, 0x83, 0xFB, 0x05);
494 TestRegImm(cmp, esp, 5, i32, 3, 0x83, 0xFC, 0x05);
495 TestRegImm(cmp, ebp, 5, i32, 3, 0x83, 0xFD, 0x05);
496 TestRegImm(cmp, esi, 5, i32, 3, 0x83, 0xFE, 0x05);
497 TestRegImm(cmp, edi, 5, i32, 3, 0x83, 0xFF, 0x05);
498 TestRegImm(cmp, r8, 5, i32, 4, 0x41, 0x83, 0xF8, 0x05);
499 TestRegImm(cmp, r9, 5, i32, 4, 0x41, 0x83, 0xF9, 0x05);
500 TestRegImm(cmp, r10, 5, i32, 4, 0x41, 0x83, 0xFA, 0x05);
501 TestRegImm(cmp, r11, 5, i32, 4, 0x41, 0x83, 0xFB, 0x05);
502 TestRegImm(cmp, r12, 5, i32, 4, 0x41, 0x83, 0xFC, 0x05);
503 TestRegImm(cmp, r13, 5, i32, 4, 0x41, 0x83, 0xFD, 0x05);
504 TestRegImm(cmp, r14, 5, i32, 4, 0x41, 0x83, 0xFE, 0x05);
505 TestRegImm(cmp, r15, 5, i32, 4, 0x41, 0x83, 0xFF, 0x05);
506
507 TestRegImm(cmp, eax, 5, i16, 4, 0x66, 0x83, 0xF8, 0x05);
508 TestRegImm(cmp, ecx, 5, i16, 4, 0x66, 0x83, 0xF9, 0x05);
509 TestRegImm(cmp, edx, 5, i16, 4, 0x66, 0x83, 0xFA, 0x05);
510 TestRegImm(cmp, ebx, 5, i16, 4, 0x66, 0x83, 0xFB, 0x05);
511 TestRegImm(cmp, esp, 5, i16, 4, 0x66, 0x83, 0xFC, 0x05);
512 TestRegImm(cmp, ebp, 5, i16, 4, 0x66, 0x83, 0xFD, 0x05);
513 TestRegImm(cmp, esi, 5, i16, 4, 0x66, 0x83, 0xFE, 0x05);
514 TestRegImm(cmp, edi, 5, i16, 4, 0x66, 0x83, 0xFF, 0x05);
515 TestRegImm(cmp, r8, 5, i16, 5, 0x66, 0x41, 0x83, 0xF8, 0x05);
516 TestRegImm(cmp, r9, 5, i16, 5, 0x66, 0x41, 0x83, 0xF9, 0x05);
517 TestRegImm(cmp, r10, 5, i16, 5, 0x66, 0x41, 0x83, 0xFA, 0x05);
518 TestRegImm(cmp, r11, 5, i16, 5, 0x66, 0x41, 0x83, 0xFB, 0x05);
519 TestRegImm(cmp, r12, 5, i16, 5, 0x66, 0x41, 0x83, 0xFC, 0x05);
520 TestRegImm(cmp, r13, 5, i16, 5, 0x66, 0x41, 0x83, 0xFD, 0x05);
521 TestRegImm(cmp, r14, 5, i16, 5, 0x66, 0x41, 0x83, 0xFE, 0x05);
522 TestRegImm(cmp, r15, 5, i16, 5, 0x66, 0x41, 0x83, 0xFF, 0x05);
523
524 TestRegImm(cmp, eax, 5, i8, 2, 0x3C, 0x05);
525 TestRegImm(cmp, ecx, 5, i8, 3, 0x80, 0xF9, 0x05);
526 TestRegImm(cmp, edx, 5, i8, 3, 0x80, 0xFA, 0x05);
527 TestRegImm(cmp, ebx, 5, i8, 3, 0x80, 0xFB, 0x05);
528 TestRegImm(cmp, esp, 5, i8, 4, 0x40, 0x80, 0xFC, 0x05);
529 TestRegImm(cmp, ebp, 5, i8, 4, 0x40, 0x80, 0xFD, 0x05);
530 TestRegImm(cmp, esi, 5, i8, 4, 0x40, 0x80, 0xFE, 0x05);
531 TestRegImm(cmp, edi, 5, i8, 4, 0x40, 0x80, 0xFF, 0x05);
532 TestRegImm(cmp, r8, 5, i8, 4, 0x41, 0x80, 0xF8, 0x05);
533 TestRegImm(cmp, r9, 5, i8, 4, 0x41, 0x80, 0xF9, 0x05);
534 TestRegImm(cmp, r10, 5, i8, 4, 0x41, 0x80, 0xFA, 0x05);
535 TestRegImm(cmp, r11, 5, i8, 4, 0x41, 0x80, 0xFB, 0x05);
536 TestRegImm(cmp, r12, 5, i8, 4, 0x41, 0x80, 0xFC, 0x05);
537 TestRegImm(cmp, r13, 5, i8, 4, 0x41, 0x80, 0xFD, 0x05);
538 TestRegImm(cmp, r14, 5, i8, 4, 0x41, 0x80, 0xFE, 0x05);
539 TestRegImm(cmp, r15, 5, i8, 4, 0x41, 0x80, 0xFF, 0x05);
540
541 /* cmp GPR, Imm16 */
542 TestRegImm(cmp, eax, 0x100, i32, 5, 0x3D, 0x00, 0x01, 0x00, 0x00);
543 TestRegImm(cmp, ecx, 0x100, i32, 6, 0x81, 0xF9, 0x00, 0x01, 0x00, 0x00);
544 TestRegImm(cmp, edx, 0x100, i32, 6, 0x81, 0xFA, 0x00, 0x01, 0x00, 0x00);
545 TestRegImm(cmp, ebx, 0x100, i32, 6, 0x81, 0xFB, 0x00, 0x01, 0x00, 0x00);
546 TestRegImm(cmp, esp, 0x100, i32, 6, 0x81, 0xFC, 0x00, 0x01, 0x00, 0x00);
547 TestRegImm(cmp, ebp, 0x100, i32, 6, 0x81, 0xFD, 0x00, 0x01, 0x00, 0x00);
548 TestRegImm(cmp, esi, 0x100, i32, 6, 0x81, 0xFE, 0x00, 0x01, 0x00, 0x00);
549 TestRegImm(cmp, edi, 0x100, i32, 6, 0x81, 0xFF, 0x00, 0x01, 0x00, 0x00);
550 TestRegImm(cmp, r8, 0x100, i32, 7, 0x41, 0x81, 0xF8, 0x00, 0x01, 0x00, 0x00);
551 TestRegImm(cmp, r9, 0x100, i32, 7, 0x41, 0x81, 0xF9, 0x00, 0x01, 0x00, 0x00);
552 TestRegImm(cmp, r10, 0x100, i32, 7, 0x41, 0x81, 0xFA, 0x00, 0x01, 0x00, 0x00);
553 TestRegImm(cmp, r11, 0x100, i32, 7, 0x41, 0x81, 0xFB, 0x00, 0x01, 0x00, 0x00);
554 TestRegImm(cmp, r12, 0x100, i32, 7, 0x41, 0x81, 0xFC, 0x00, 0x01, 0x00, 0x00);
555 TestRegImm(cmp, r13, 0x100, i32, 7, 0x41, 0x81, 0xFD, 0x00, 0x01, 0x00, 0x00);
556 TestRegImm(cmp, r14, 0x100, i32, 7, 0x41, 0x81, 0xFE, 0x00, 0x01, 0x00, 0x00);
557 TestRegImm(cmp, r15, 0x100, i32, 7, 0x41, 0x81, 0xFF, 0x00, 0x01, 0x00, 0x00);
558
559 TestRegImm(cmp, eax, 0x100, i16, 4, 0x66, 0x3D, 0x00, 0x01);
560 TestRegImm(cmp, ecx, 0x100, i16, 5, 0x66, 0x81, 0xF9, 0x00, 0x01);
561 TestRegImm(cmp, edx, 0x100, i16, 5, 0x66, 0x81, 0xFA, 0x00, 0x01);
562 TestRegImm(cmp, ebx, 0x100, i16, 5, 0x66, 0x81, 0xFB, 0x00, 0x01);
563 TestRegImm(cmp, esp, 0x100, i16, 5, 0x66, 0x81, 0xFC, 0x00, 0x01);
564 TestRegImm(cmp, ebp, 0x100, i16, 5, 0x66, 0x81, 0xFD, 0x00, 0x01);
565 TestRegImm(cmp, esi, 0x100, i16, 5, 0x66, 0x81, 0xFE, 0x00, 0x01);
566 TestRegImm(cmp, edi, 0x100, i16, 5, 0x66, 0x81, 0xFF, 0x00, 0x01);
567 TestRegImm(cmp, r8, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xF8, 0x00, 0x01);
568 TestRegImm(cmp, r9, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xF9, 0x00, 0x01);
569 TestRegImm(cmp, r10, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFA, 0x00, 0x01);
570 TestRegImm(cmp, r11, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFB, 0x00, 0x01);
571 TestRegImm(cmp, r12, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFC, 0x00, 0x01);
572 TestRegImm(cmp, r13, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFD, 0x00, 0x01);
573 TestRegImm(cmp, r14, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFE, 0x00, 0x01);
574 TestRegImm(cmp, r15, 0x100, i16, 6, 0x66, 0x41, 0x81, 0xFF, 0x00, 0x01);
575
576 /* cmp GPR, Absolute */
577 TestRegAbsoluteAddr(cmp, eax, 0xF00FBEEF, i32, 6, 0x3B, 0x05, 0xEF, 0xBE,
578 0x0F, 0xF0);
579 TestRegAbsoluteAddr(cmp, eax, 0xF00FBEEF, i16, 7, 0x66, 0x3B, 0x05, 0xEF,
580 0xBE, 0x0F, 0xF0);
581 TestRegAbsoluteAddr(cmp, eax, 0xF00FBEEF, i8, 6, 0x3A, 0x05, 0xEF, 0xBE, 0x0F,
582 0xF0);
583 TestRegAbsoluteAddr(cmp, r8, 0xF00FBEEF, i32, 7, 0x44, 0x3B, 0x05, 0xEF, 0xBE,
584 0x0F, 0xF0);
585 TestRegAbsoluteAddr(cmp, r8, 0xF00FBEEF, i16, 8, 0x66, 0x44, 0x3B, 0x05, 0xEF,
586 0xBE, 0x0F, 0xF0);
587 TestRegAbsoluteAddr(cmp, r8, 0xF00FBEEF, i8, 7, 0x44, 0x3A, 0x05, 0xEF, 0xBE,
588 0x0F, 0xF0);
589
590 /* cmp GPR, 0(Base) */
591 TestRegAddrBase(cmp, eax, ecx, 0, i32, 2, 0x3B, 0x01);
592 TestRegAddrBase(cmp, ecx, edx, 0, i32, 2, 0x3B, 0x0A);
593 TestRegAddrBase(cmp, edx, ebx, 0, i32, 2, 0x3B, 0x13);
594 TestRegAddrBase(cmp, ebx, esp, 0, i32, 3, 0x3B, 0x1C, 0x24);
595 TestRegAddrBase(cmp, esp, ebp, 0, i32, 3, 0x3B, 0x65, 0x00);
596 TestRegAddrBase(cmp, ebp, esi, 0, i32, 2, 0x3B, 0x2E);
597 TestRegAddrBase(cmp, esi, edi, 0, i32, 2, 0x3B, 0x37);
598 TestRegAddrBase(cmp, edi, r8, 0, i32, 3, 0x41, 0x3B, 0x38);
599 TestRegAddrBase(cmp, r8, r9, 0, i32, 3, 0x45, 0x3B, 0x01);
600 TestRegAddrBase(cmp, r9, r10, 0, i32, 3, 0x45, 0x3B, 0x0A);
601 TestRegAddrBase(cmp, r10, r11, 0, i32, 3, 0x45, 0x3B, 0x13);
602 TestRegAddrBase(cmp, r11, r12, 0, i32, 4, 0x45, 0x3B, 0x1C, 0x24);
603 TestRegAddrBase(cmp, r12, r13, 0, i32, 4, 0x45, 0x3B, 0x65, 0x00);
604 TestRegAddrBase(cmp, r13, r14, 0, i32, 3, 0x45, 0x3B, 0x2E);
605 TestRegAddrBase(cmp, r14, r15, 0, i32, 3, 0x45, 0x3B, 0x37);
606 TestRegAddrBase(cmp, r15, eax, 0, i32, 3, 0x44, 0x3B, 0x38);
607
608 TestRegAddrBase(cmp, eax, ecx, 0, i16, 3, 0x66, 0x3B, 0x01);
609 TestRegAddrBase(cmp, ecx, edx, 0, i16, 3, 0x66, 0x3B, 0x0A);
610 TestRegAddrBase(cmp, edx, ebx, 0, i16, 3, 0x66, 0x3B, 0x13);
611 TestRegAddrBase(cmp, ebx, esp, 0, i16, 4, 0x66, 0x3B, 0x1C, 0x24);
612 TestRegAddrBase(cmp, esp, ebp, 0, i16, 4, 0x66, 0x3B, 0x65, 0x00);
613 TestRegAddrBase(cmp, ebp, esi, 0, i16, 3, 0x66, 0x3B, 0x2E);
614 TestRegAddrBase(cmp, esi, edi, 0, i16, 3, 0x66, 0x3B, 0x37);
615 TestRegAddrBase(cmp, edi, r8, 0, i16, 4, 0x66, 0x41, 0x3B, 0x38);
616 TestRegAddrBase(cmp, r8, r9, 0, i16, 4, 0x66, 0x45, 0x3B, 0x01);
617 TestRegAddrBase(cmp, r9, r10, 0, i16, 4, 0x66, 0x45, 0x3B, 0x0A);
618 TestRegAddrBase(cmp, r10, r11, 0, i16, 4, 0x66, 0x45, 0x3B, 0x13);
619 TestRegAddrBase(cmp, r11, r12, 0, i16, 5, 0x66, 0x45, 0x3B, 0x1C, 0x24);
620 TestRegAddrBase(cmp, r12, r13, 0, i16, 5, 0x66, 0x45, 0x3B, 0x65, 0x00);
621 TestRegAddrBase(cmp, r13, r14, 0, i16, 4, 0x66, 0x45, 0x3B, 0x2E);
622 TestRegAddrBase(cmp, r14, r15, 0, i16, 4, 0x66, 0x45, 0x3B, 0x37);
623 TestRegAddrBase(cmp, r15, eax, 0, i16, 4, 0x66, 0x44, 0x3B, 0x38);
624
625 TestRegAddrBase(cmp, eax, ecx, 0, i8, 2, 0x3A, 0x01);
626 TestRegAddrBase(cmp, ecx, edx, 0, i8, 2, 0x3A, 0x0A);
627 TestRegAddrBase(cmp, edx, ebx, 0, i8, 2, 0x3A, 0x13);
628 TestRegAddrBase(cmp, ebx, esp, 0, i8, 3, 0x3A, 0x1C, 0x24);
629 TestRegAddrBase(cmp, esp, ebp, 0, i8, 4, 0x40, 0x3A, 0x65, 0x00);
630 TestRegAddrBase(cmp, ebp, esi, 0, i8, 3, 0x40, 0x3A, 0x2E);
631 TestRegAddrBase(cmp, esi, edi, 0, i8, 3, 0x40, 0x3A, 0x37);
632 TestRegAddrBase(cmp, edi, r8, 0, i8, 3, 0x41, 0x3A, 0x38);
633 TestRegAddrBase(cmp, r8, r9, 0, i8, 3, 0x45, 0x3A, 0x01);
634 TestRegAddrBase(cmp, r9, r10, 0, i8, 3, 0x45, 0x3A, 0x0A);
635 TestRegAddrBase(cmp, r10, r11, 0, i8, 3, 0x45, 0x3A, 0x13);
636 TestRegAddrBase(cmp, r11, r12, 0, i8, 4, 0x45, 0x3A, 0x1C, 0x24);
637 TestRegAddrBase(cmp, r12, r13, 0, i8, 4, 0x45, 0x3A, 0x65, 0x00);
638 TestRegAddrBase(cmp, r13, r14, 0, i8, 3, 0x45, 0x3A, 0x2E);
639 TestRegAddrBase(cmp, r14, r15, 0, i8, 3, 0x45, 0x3A, 0x37);
640 TestRegAddrBase(cmp, r15, eax, 0, i8, 3, 0x44, 0x3A, 0x38);
641
642 /* cmp GPR, Imm8(Base) */
643 TestRegAddrBase(cmp, eax, ecx, 0x40, i32, 3, 0x3B, 0x41, 0x40);
644 TestRegAddrBase(cmp, ecx, edx, 0x40, i32, 3, 0x3B, 0x4A, 0x40);
645 TestRegAddrBase(cmp, edx, ebx, 0x40, i32, 3, 0x3B, 0x53, 0x40);
646 TestRegAddrBase(cmp, ebx, esp, 0x40, i32, 4, 0x3B, 0x5C, 0x24, 0x40);
647 TestRegAddrBase(cmp, esp, ebp, 0x40, i32, 3, 0x3B, 0x65, 0x40);
648 TestRegAddrBase(cmp, ebp, esi, 0x40, i32, 3, 0x3B, 0x6E, 0x40);
649 TestRegAddrBase(cmp, esi, edi, 0x40, i32, 3, 0x3B, 0x77, 0x40);
650 TestRegAddrBase(cmp, edi, r8, 0x40, i32, 4, 0x41, 0x3B, 0x78, 0x40);
651 TestRegAddrBase(cmp, r8, r9, 0x40, i32, 4, 0x45, 0x3B, 0x41, 0x40);
652 TestRegAddrBase(cmp, r9, r10, 0x40, i32, 4, 0x45, 0x3B, 0x4A, 0x40);
653 TestRegAddrBase(cmp, r10, r11, 0x40, i32, 4, 0x45, 0x3B, 0x53, 0x40);
654 TestRegAddrBase(cmp, r11, r12, 0x40, i32, 5, 0x45, 0x3B, 0x5C, 0x24, 0x40);
655 TestRegAddrBase(cmp, r12, r13, 0x40, i32, 4, 0x45, 0x3B, 0x65, 0x40);
656 TestRegAddrBase(cmp, r13, r14, 0x40, i32, 4, 0x45, 0x3B, 0x6E, 0x40);
657 TestRegAddrBase(cmp, r14, r15, 0x40, i32, 4, 0x45, 0x3B, 0x77, 0x40);
658 TestRegAddrBase(cmp, r15, eax, 0x40, i32, 4, 0x44, 0x3B, 0x78, 0x40);
659
660 TestRegAddrBase(cmp, eax, ecx, 0x40, i16, 4, 0x66, 0x3B, 0x41, 0x40);
661 TestRegAddrBase(cmp, ecx, edx, 0x40, i16, 4, 0x66, 0x3B, 0x4A, 0x40);
662 TestRegAddrBase(cmp, edx, ebx, 0x40, i16, 4, 0x66, 0x3B, 0x53, 0x40);
663 TestRegAddrBase(cmp, ebx, esp, 0x40, i16, 5, 0x66, 0x3B, 0x5C, 0x24, 0x40);
664 TestRegAddrBase(cmp, esp, ebp, 0x40, i16, 4, 0x66, 0x3B, 0x65, 0x40);
665 TestRegAddrBase(cmp, ebp, esi, 0x40, i16, 4, 0x66, 0x3B, 0x6E, 0x40);
666 TestRegAddrBase(cmp, esi, edi, 0x40, i16, 4, 0x66, 0x3B, 0x77, 0x40);
667 TestRegAddrBase(cmp, edi, r8, 0x40, i16, 5, 0x66, 0x41, 0x3B, 0x78, 0x40);
668 TestRegAddrBase(cmp, r8, r9, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x41, 0x40);
669 TestRegAddrBase(cmp, r9, r10, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x4A, 0x40);
670 TestRegAddrBase(cmp, r10, r11, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x53, 0x40);
671 TestRegAddrBase(cmp, r11, r12, 0x40, i16, 6, 0x66, 0x45, 0x3B, 0x5C, 0x24,
672 0x40);
673 TestRegAddrBase(cmp, r12, r13, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x65, 0x40);
674 TestRegAddrBase(cmp, r13, r14, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x6E, 0x40);
675 TestRegAddrBase(cmp, r14, r15, 0x40, i16, 5, 0x66, 0x45, 0x3B, 0x77, 0x40);
676 TestRegAddrBase(cmp, r15, eax, 0x40, i16, 5, 0x66, 0x44, 0x3B, 0x78, 0x40);
677
678 TestRegAddrBase(cmp, eax, ecx, 0x40, i8, 3, 0x3A, 0x41, 0x40);
679 TestRegAddrBase(cmp, ecx, edx, 0x40, i8, 3, 0x3A, 0x4A, 0x40);
680 TestRegAddrBase(cmp, edx, ebx, 0x40, i8, 3, 0x3A, 0x53, 0x40);
681 TestRegAddrBase(cmp, ebx, esp, 0x40, i8, 4, 0x3A, 0x5C, 0x24, 0x40);
682 TestRegAddrBase(cmp, esp, ebp, 0x40, i8, 4, 0x40, 0x3A, 0x65, 0x40);
683 TestRegAddrBase(cmp, ebp, esi, 0x40, i8, 4, 0x40, 0x3A, 0x6E, 0x40);
684 TestRegAddrBase(cmp, esi, edi, 0x40, i8, 4, 0x40, 0x3A, 0x77, 0x40);
685 TestRegAddrBase(cmp, edi, r8, 0x40, i8, 4, 0x41, 0x3A, 0x78, 0x40);
686 TestRegAddrBase(cmp, r8, r9, 0x40, i8, 4, 0x45, 0x3A, 0x41, 0x40);
687 TestRegAddrBase(cmp, r9, r10, 0x40, i8, 4, 0x45, 0x3A, 0x4A, 0x40);
688 TestRegAddrBase(cmp, r10, r11, 0x40, i8, 4, 0x45, 0x3A, 0x53, 0x40);
689 TestRegAddrBase(cmp, r11, r12, 0x40, i8, 5, 0x45, 0x3A, 0x5C, 0x24, 0x40);
690 TestRegAddrBase(cmp, r12, r13, 0x40, i8, 4, 0x45, 0x3A, 0x65, 0x40);
691 TestRegAddrBase(cmp, r13, r14, 0x40, i8, 4, 0x45, 0x3A, 0x6E, 0x40);
692 TestRegAddrBase(cmp, r14, r15, 0x40, i8, 4, 0x45, 0x3A, 0x77, 0x40);
693 TestRegAddrBase(cmp, r15, eax, 0x40, i8, 4, 0x44, 0x3A, 0x78, 0x40);
694
695 /* cmp GPR, Imm32(Base) */
696 TestRegAddrBase(cmp, eax, ecx, 0xF0, i32, 6, 0x3B, 0x81, 0xF0, 0x00, 0x00,
697 0x00);
698 TestRegAddrBase(cmp, ecx, edx, 0xF0, i32, 6, 0x3B, 0x8A, 0xF0, 0x00, 0x00,
699 0x00);
700 TestRegAddrBase(cmp, edx, ebx, 0xF0, i32, 6, 0x3B, 0x93, 0xF0, 0x00, 0x00,
701 0x00);
702 TestRegAddrBase(cmp, ebx, esp, 0xF0, i32, 7, 0x3B, 0x9C, 0x24, 0xF0, 0x00,
703 0x00, 0x00);
704 TestRegAddrBase(cmp, esp, ebp, 0xF0, i32, 6, 0x3B, 0xA5, 0xF0, 0x00, 0x00,
705 0x00);
706 TestRegAddrBase(cmp, ebp, esi, 0xF0, i32, 6, 0x3B, 0xAE, 0xF0, 0x00, 0x00,
707 0x00);
708 TestRegAddrBase(cmp, esi, edi, 0xF0, i32, 6, 0x3B, 0xB7, 0xF0, 0x00, 0x00,
709 0x00);
710 TestRegAddrBase(cmp, edi, r8, 0xF0, i32, 7, 0x41, 0x3B, 0xB8, 0xF0, 0x00,
711 0x00, 0x00);
712 TestRegAddrBase(cmp, r8, r9, 0xF0, i32, 7, 0x45, 0x3B, 0x81, 0xF0, 0x00, 0x00,
713 0x00);
714 TestRegAddrBase(cmp, r9, r10, 0xF0, i32, 7, 0x45, 0x3B, 0x8A, 0xF0, 0x00,
715 0x00, 0x00);
716 TestRegAddrBase(cmp, r10, r11, 0xF0, i32, 7, 0x45, 0x3B, 0x93, 0xF0, 0x00,
717 0x00, 0x00);
718 TestRegAddrBase(cmp, r11, r12, 0xF0, i32, 8, 0x45, 0x3B, 0x9C, 0x24, 0xF0,
719 0x00, 0x00, 0x00);
720 TestRegAddrBase(cmp, r12, r13, 0xF0, i32, 7, 0x45, 0x3B, 0xA5, 0xF0, 0x00,
721 0x00, 0x00);
722 TestRegAddrBase(cmp, r13, r14, 0xF0, i32, 7, 0x45, 0x3B, 0xAE, 0xF0, 0x00,
723 0x00, 0x00);
724 TestRegAddrBase(cmp, r14, r15, 0xF0, i32, 7, 0x45, 0x3B, 0xB7, 0xF0, 0x00,
725 0x00, 0x00);
726 TestRegAddrBase(cmp, r15, eax, 0xF0, i32, 7, 0x44, 0x3B, 0xB8, 0xF0, 0x00,
727 0x00, 0x00);
728
729 TestRegAddrBase(cmp, eax, ecx, 0xF0, i16, 7, 0x66, 0x3B, 0x81, 0xF0, 0x00,
730 0x00, 0x00);
731 TestRegAddrBase(cmp, ecx, edx, 0xF0, i16, 7, 0x66, 0x3B, 0x8A, 0xF0, 0x00,
732 0x00, 0x00);
733 TestRegAddrBase(cmp, edx, ebx, 0xF0, i16, 7, 0x66, 0x3B, 0x93, 0xF0, 0x00,
734 0x00, 0x00);
735 TestRegAddrBase(cmp, ebx, esp, 0xF0, i16, 8, 0x66, 0x3B, 0x9C, 0x24, 0xF0,
736 0x00, 0x00, 0x00);
737 TestRegAddrBase(cmp, esp, ebp, 0xF0, i16, 7, 0x66, 0x3B, 0xa5, 0xF0, 0x00,
738 0x00, 0x00);
739 TestRegAddrBase(cmp, ebp, esi, 0xF0, i16, 7, 0x66, 0x3B, 0xaE, 0xF0, 0x00,
740 0x00, 0x00);
741 TestRegAddrBase(cmp, esi, edi, 0xF0, i16, 7, 0x66, 0x3B, 0xb7, 0xF0, 0x00,
742 0x00, 0x00);
743 TestRegAddrBase(cmp, edi, r8, 0xF0, i16, 8, 0x66, 0x41, 0x3B, 0xb8, 0xF0,
744 0x00, 0x00, 0x00);
745 TestRegAddrBase(cmp, r8, r9, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0x81, 0xF0, 0x00,
746 0x00, 0x00);
747 TestRegAddrBase(cmp, r9, r10, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0x8A, 0xF0,
748 0x00, 0x00, 0x00);
749 TestRegAddrBase(cmp, r10, r11, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0x93, 0xF0,
750 0x00, 0x00, 0x00);
751 TestRegAddrBase(cmp, r11, r12, 0xF0, i16, 9, 0x66, 0x45, 0x3B, 0x9C, 0x24,
752 0xF0, 0x00, 0x00, 0x00);
753 TestRegAddrBase(cmp, r12, r13, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0xa5, 0xF0,
754 0x00, 0x00, 0x00);
755 TestRegAddrBase(cmp, r13, r14, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0xaE, 0xF0,
756 0x00, 0x00, 0x00);
757 TestRegAddrBase(cmp, r14, r15, 0xF0, i16, 8, 0x66, 0x45, 0x3B, 0xb7, 0xF0,
758 0x00, 0x00, 0x00);
759 TestRegAddrBase(cmp, r15, eax, 0xF0, i16, 8, 0x66, 0x44, 0x3B, 0xb8, 0xF0,
760 0x00, 0x00, 0x00);
761
762 TestRegAddrBase(cmp, eax, ecx, 0xF0, i8, 6, 0x3A, 0x81, 0xF0, 0x00, 0x00,
763 0x00);
764 TestRegAddrBase(cmp, ecx, edx, 0xF0, i8, 6, 0x3A, 0x8A, 0xF0, 0x00, 0x00,
765 0x00);
766 TestRegAddrBase(cmp, edx, ebx, 0xF0, i8, 6, 0x3A, 0x93, 0xF0, 0x00, 0x00,
767 0x00);
768 TestRegAddrBase(cmp, ebx, esp, 0xF0, i8, 7, 0x3A, 0x9C, 0x24, 0xF0, 0x00,
769 0x00, 0x00);
770 TestRegAddrBase(cmp, esp, ebp, 0xF0, i8, 7, 0x40, 0x3A, 0xA5, 0xF0, 0x00,
771 0x00, 0x00);
772 TestRegAddrBase(cmp, ebp, esi, 0xF0, i8, 7, 0x40, 0x3A, 0xAE, 0xF0, 0x00,
773 0x00, 0x00);
774 TestRegAddrBase(cmp, esi, edi, 0xF0, i8, 7, 0x40, 0x3A, 0xB7, 0xF0, 0x00,
775 0x00, 0x00);
776 TestRegAddrBase(cmp, edi, r8, 0xF0, i8, 7, 0x41, 0x3A, 0xB8, 0xF0, 0x00, 0x00,
777 0x00);
778 TestRegAddrBase(cmp, r8, r9, 0xF0, i8, 7, 0x45, 0x3A, 0x81, 0xF0, 0x00, 0x00,
779 0x00);
780 TestRegAddrBase(cmp, r9, r10, 0xF0, i8, 7, 0x45, 0x3A, 0x8A, 0xF0, 0x00, 0x00,
781 0x00);
782 TestRegAddrBase(cmp, r10, r11, 0xF0, i8, 7, 0x45, 0x3A, 0x93, 0xF0, 0x00,
783 0x00, 0x00);
784 TestRegAddrBase(cmp, r11, r12, 0xF0, i8, 8, 0x45, 0x3A, 0x9C, 0x24, 0xF0,
785 0x00, 0x00, 0x00);
786 TestRegAddrBase(cmp, r12, r13, 0xF0, i8, 7, 0x45, 0x3A, 0xA5, 0xF0, 0x00,
787 0x00, 0x00);
788 TestRegAddrBase(cmp, r13, r14, 0xF0, i8, 7, 0x45, 0x3A, 0xAE, 0xF0, 0x00,
789 0x00, 0x00);
790 TestRegAddrBase(cmp, r14, r15, 0xF0, i8, 7, 0x45, 0x3A, 0xB7, 0xF0, 0x00,
791 0x00, 0x00);
792 TestRegAddrBase(cmp, r15, eax, 0xF0, i8, 7, 0x44, 0x3A, 0xB8, 0xF0, 0x00,
793 0x00, 0x00);
794
795 /* cmp GPR, Imm(,Index,Scale) */
796 TestRegAddrScaledIndex(cmp, eax, ecx, 1, 0, i32, 7, 0x3B, 0x04, 0x0D, 0x00,
797 0x00, 0x00, 0x00);
798 TestRegAddrScaledIndex(cmp, ecx, edx, 2, 0, i32, 7, 0x3B, 0x0C, 0x55, 0x00,
799 0x00, 0x00, 0x00);
800 TestRegAddrScaledIndex(cmp, edx, ebx, 4, 0, i32, 7, 0x3B, 0x14, 0x9D, 0x00,
801 0x00, 0x00, 0x00);
802 TestRegAddrScaledIndex(cmp, r8, r9, 1, 0, i32, 8, 0x46, 0x3B, 0x04, 0x0D,
803 0x00, 0x00, 0x00, 0x00);
804 TestRegAddrScaledIndex(cmp, r9, r10, 2, 0, i32, 8, 0x46, 0x3B, 0x0C, 0x55,
805 0x00, 0x00, 0x00, 0x00);
806 TestRegAddrScaledIndex(cmp, r10, r11, 4, 0, i32, 8, 0x46, 0x3B, 0x14, 0x9D,
807 0x00, 0x00, 0x00, 0x00);
808 // esp cannot be an scaled index.
809 TestRegAddrScaledIndex(cmp, esp, ebp, 8, 0, i32, 7, 0x3B, 0x24, 0xED, 0x00,
810 0x00, 0x00, 0x00);
811 TestRegAddrScaledIndex(cmp, ebp, esi, 1, 0, i32, 7, 0x3B, 0x2C, 0x35, 0x00,
812 0x00, 0x00, 0x00);
813 TestRegAddrScaledIndex(cmp, esi, edi, 2, 0, i32, 7, 0x3B, 0x34, 0x7D, 0x00,
814 0x00, 0x00, 0x00);
815 TestRegAddrScaledIndex(cmp, edi, eax, 4, 0, i32, 7, 0x3B, 0x3C, 0x85, 0x00,
816 0x00, 0x00, 0x00);
817 TestRegAddrScaledIndex(cmp, ebx, ecx, 8, 0, i32, 7, 0x3B, 0x1C, 0xCD, 0x00,
818 0x00, 0x00, 0x00);
819 TestRegAddrScaledIndex(cmp, r12, r13, 8, 0, i32, 8, 0x46, 0x3B, 0x24, 0xED,
820 0x00, 0x00, 0x00, 0x00);
821 TestRegAddrScaledIndex(cmp, r13, r14, 1, 0, i32, 8, 0x46, 0x3B, 0x2C, 0x35,
822 0x00, 0x00, 0x00, 0x00);
823 TestRegAddrScaledIndex(cmp, r14, r15, 2, 0, i32, 8, 0x46, 0x3B, 0x34, 0x7D,
824 0x00, 0x00, 0x00, 0x00);
825 TestRegAddrScaledIndex(cmp, r15, r8, 4, 0, i32, 8, 0x46, 0x3B, 0x3C, 0x85,
826 0x00, 0x00, 0x00, 0x00);
827 TestRegAddrScaledIndex(cmp, r11, r9, 8, 0, i32, 8, 0x46, 0x3B, 0x1C, 0xCD,
828 0x00, 0x00, 0x00, 0x00);
829
830 TestRegAddrScaledIndex(cmp, eax, ecx, 8, 0, i16, 8, 0x66, 0x3B, 0x04, 0xCD,
831 0x00, 0x00, 0x00, 0x00);
832 TestRegAddrScaledIndex(cmp, ecx, edx, 1, 0, i16, 8, 0x66, 0x3B, 0x0C, 0x15,
833 0x00, 0x00, 0x00, 0x00);
834 TestRegAddrScaledIndex(cmp, edx, ebx, 2, 0, i16, 8, 0x66, 0x3B, 0x14, 0x5D,
835 0x00, 0x00, 0x00, 0x00);
836 TestRegAddrScaledIndex(cmp, r8, r9, 8, 0, i16, 9, 0x66, 0x46, 0x3B, 0x04,
837 0xCD, 0x00, 0x00, 0x00, 0x00);
838 TestRegAddrScaledIndex(cmp, r9, r10, 1, 0, i16, 9, 0x66, 0x46, 0x3B, 0x0C,
839 0x15, 0x00, 0x00, 0x00, 0x00);
840 TestRegAddrScaledIndex(cmp, r10, r11, 2, 0, i16, 9, 0x66, 0x46, 0x3B, 0x14,
841 0x5D, 0x00, 0x00, 0x00, 0x00);
842 // esp cannot be an scaled index.
843 TestRegAddrScaledIndex(cmp, esp, ebp, 4, 0, i16, 8, 0x66, 0x3B, 0x24, 0xAD,
844 0x00, 0x00, 0x00, 0x00);
845 TestRegAddrScaledIndex(cmp, ebp, esi, 8, 0, i16, 8, 0x66, 0x3B, 0x2C, 0xF5,
846 0x00, 0x00, 0x00, 0x00);
847 TestRegAddrScaledIndex(cmp, esi, edi, 1, 0, i16, 8, 0x66, 0x3B, 0x34, 0x3D,
848 0x00, 0x00, 0x00, 0x00);
849 TestRegAddrScaledIndex(cmp, edi, eax, 2, 0, i16, 8, 0x66, 0x3B, 0x3C, 0x45,
850 0x00, 0x00, 0x00, 0x00);
851 TestRegAddrScaledIndex(cmp, ebx, ecx, 8, 0, i16, 8, 0x66, 0x3B, 0x1C, 0xCD,
852 0x00, 0x00, 0x00, 0x00);
853
854 TestRegAddrScaledIndex(cmp, eax, ecx, 4, 0, i8, 7, 0x3A, 0x04, 0x8D, 0x00,
855 0x00, 0x00, 0x00);
856 TestRegAddrScaledIndex(cmp, ecx, edx, 8, 0, i8, 7, 0x3A, 0x0C, 0xD5, 0x00,
857 0x00, 0x00, 0x00);
858 TestRegAddrScaledIndex(cmp, edx, ebx, 1, 0, i8, 7, 0x3A, 0x14, 0x1D, 0x00,
859 0x00, 0x00, 0x00);
860 TestRegAddrScaledIndex(cmp, r8, r9, 4, 0, i8, 8, 0x46, 0x3A, 0x04, 0x8D, 0x00,
861 0x00, 0x00, 0x00);
862 TestRegAddrScaledIndex(cmp, r9, r10, 8, 0, i8, 8, 0x46, 0x3A, 0x0C, 0xD5,
863 0x00, 0x00, 0x00, 0x00);
864 TestRegAddrScaledIndex(cmp, r10, r11, 1, 0, i8, 8, 0x46, 0x3A, 0x14, 0x1D,
865 0x00, 0x00, 0x00, 0x00);
866 // esp cannot be an scaled index.
867 TestRegAddrScaledIndex(cmp, esp, ebp, 2, 0, i8, 8, 0x40, 0x3A, 0x24, 0x6D,
868 0x00, 0x00, 0x00, 0x00);
869 TestRegAddrScaledIndex(cmp, ebp, esi, 4, 0, i8, 8, 0x40, 0x3A, 0x2C, 0xB5,
870 0x00, 0x00, 0x00, 0x00);
871 TestRegAddrScaledIndex(cmp, esi, edi, 8, 0, i8, 8, 0x40, 0x3A, 0x34, 0xFD,
872 0x00, 0x00, 0x00, 0x00);
873 TestRegAddrScaledIndex(cmp, edi, eax, 1, 0, i8, 8, 0x40, 0x3A, 0x3C, 0x05,
874 0x00, 0x00, 0x00, 0x00);
875 TestRegAddrScaledIndex(cmp, ebx, ecx, 8, 0, i8, 7, 0x3a, 0x1C, 0xCD, 0x00,
876 0x00, 0x00, 0x00);
877 TestRegAddrScaledIndex(cmp, r12, r13, 2, 0, i8, 8, 0x46, 0x3A, 0x24, 0x6D,
878 0x00, 0x00, 0x00, 0x00);
879 TestRegAddrScaledIndex(cmp, r13, r14, 4, 0, i8, 8, 0x46, 0x3A, 0x2C, 0xB5,
880 0x00, 0x00, 0x00, 0x00);
881 TestRegAddrScaledIndex(cmp, r14, r15, 8, 0, i8, 8, 0x46, 0x3A, 0x34, 0xFD,
882 0x00, 0x00, 0x00, 0x00);
883 TestRegAddrScaledIndex(cmp, r15, r8, 1, 0, i8, 8, 0x46, 0x3A, 0x3C, 0x05,
884 0x00, 0x00, 0x00, 0x00);
885 TestRegAddrScaledIndex(cmp, r11, r9, 8, 0, i8, 8, 0x46, 0x3a, 0x1C, 0xCD,
886 0x00, 0x00, 0x00, 0x00);
887
888 /* cmp GPR, 0(Base,Index,Scale) */
889 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0, i32, 3, 0x3B, 0x04,
890 0x11);
891 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0, i32, 3, 0x3B, 0x0C,
892 0x5A);
893 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0, i32, 4, 0x47, 0x3B, 0x04,
894 0x11);
895 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0, i32, 4, 0x47, 0x3B, 0x0C,
896 0x5A);
897 // esp cannot be an scaled index.
898 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0, i32, 3, 0x3B, 0x1C,
899 0xAC);
900 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0, i32, 4, 0x3B, 0x64, 0xF5,
901 0x00);
902 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0, i32, 3, 0x3B, 0x2C,
903 0x3E);
904 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0, i32, 3, 0x3B, 0x34,
905 0x47);
906 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0, i32, 3, 0x3B, 0x3C,
907 0x98);
908 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0, i32, 3, 0x3B, 0x1C,
909 0xD1);
910 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0, i32, 4, 0x47, 0x3B, 0x1C,
911 0xAC);
912 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0, i32, 5, 0x47, 0x3B, 0x64,
913 0xF5, 0x00);
914 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0, i32, 4, 0x47, 0x3B, 0x2C,
915 0x3E);
916 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0, i32, 4, 0x47, 0x3B, 0x34,
917 0x47);
918 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0, i32, 4, 0x47, 0x3B, 0x3C,
919 0x98);
920 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0, i32, 4, 0x47, 0x3B, 0x1C,
921 0xD1);
922
923 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0, i16, 4, 0x66, 0x3B, 0x04,
924 0x11);
925 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0, i16, 4, 0x66, 0x3B, 0x0C,
926 0x5A);
927 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0, i16, 5, 0x66, 0x47, 0x3B,
928 0x04, 0x11);
929 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0, i16, 5, 0x66, 0x47, 0x3B,
930 0x0C, 0x5A);
931 // esp cannot be an scaled index.
932 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0, i16, 4, 0x66, 0x3B, 0x1C,
933 0xAC);
934 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0, i16, 5, 0x66, 0x3B, 0x64,
935 0xF5, 0x00);
936 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0, i16, 4, 0x66, 0x3B, 0x2C,
937 0x3E);
938 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0, i16, 4, 0x66, 0x3B, 0x34,
939 0x47);
940 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0, i16, 4, 0x66, 0x3B, 0x3C,
941 0x98);
942 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0, i16, 4, 0x66, 0x3B, 0x1C,
943 0xD1);
944 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0, i16, 5, 0x66, 0x47, 0x3B,
945 0x1C, 0xAC);
946 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0, i16, 6, 0x66, 0x47, 0x3B,
947 0x64, 0xF5, 0x00);
948 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0, i16, 5, 0x66, 0x47, 0x3B,
949 0x2C, 0x3E);
950 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0, i16, 5, 0x66, 0x47, 0x3B,
951 0x34, 0x47);
952 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0, i16, 5, 0x66, 0x47, 0x3B,
953 0x3C, 0x98);
954 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0, i16, 5, 0x66, 0x47, 0x3B,
955 0x1C, 0xD1);
956
957 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0, i8, 3, 0x3A, 0x04, 0x11);
958 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0, i8, 3, 0x3A, 0x0C, 0x5A);
959 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0, i8, 4, 0x47, 0x3A, 0x04,
960 0x11);
961 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0, i8, 4, 0x47, 0x3A, 0x0C,
962 0x5A);
963 // esp cannot be an scaled index.
964 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0, i8, 3, 0x3A, 0x1C, 0xAC);
965 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0, i8, 5, 0x40, 0x3A, 0x64,
966 0xF5, 0x00);
967 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0, i8, 4, 0x40, 0x3A, 0x2C,
968 0x3E);
969 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0, i8, 4, 0x40, 0x3A, 0x34,
970 0x47);
971 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0, i8, 4, 0x40, 0x3A, 0x3C,
972 0x98);
973 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0, i8, 3, 0x3A, 0x1C, 0xD1);
974 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0, i8, 4, 0x47, 0x3A, 0x1C,
975 0xAC);
976 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0, i8, 5, 0x47, 0x3A, 0x64,
977 0xF5, 0x00);
978 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0, i8, 4, 0x47, 0x3A, 0x2C,
979 0x3E);
980 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0, i8, 4, 0x47, 0x3A, 0x34,
981 0x47);
982 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0, i8, 4, 0x47, 0x3A, 0x3C,
983 0x98);
984 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0, i8, 4, 0x47, 0x3A, 0x1C,
985 0xD1);
986
987 /* cmp GPR, Imm8(Base,Index,Scale) */
988 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0x40, i32, 4, 0x3B, 0x44,
989 0x11, 0x40);
990 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0x40, i32, 4, 0x3B, 0x4C,
991 0x5A, 0x40);
992 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0x40, i32, 5, 0x47, 0x3B,
993 0x44, 0x11, 0x40);
994 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0x40, i32, 5, 0x47, 0x3B,
995 0x4C, 0x5A, 0x40);
996 // esp cannot be an scaled index.
997 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0x40, i32, 4, 0x3B, 0x5C,
998 0xAC, 0x40);
999 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0x40, i32, 4, 0x3B, 0x64,
1000 0xF5, 0x40);
1001 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0x40, i32, 4, 0x3B, 0x6C,
1002 0x3E, 0x40);
1003 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0x40, i32, 4, 0x3B, 0x74,
1004 0x47, 0x40);
1005 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0x40, i32, 4, 0x3B, 0x7C,
1006 0x98, 0x40);
1007 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0x40, i32, 4, 0x3B, 0x5C,
1008 0xD1, 0x40);
1009 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0x40, i32, 5, 0x47, 0x3B,
1010 0x5C, 0xAC, 0x40);
1011 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0x40, i32, 5, 0x47, 0x3B,
1012 0x64, 0xF5, 0x40);
1013 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0x40, i32, 5, 0x47, 0x3B,
1014 0x6C, 0x3E, 0x40);
1015 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0x40, i32, 5, 0x47, 0x3B,
1016 0x74, 0x47, 0x40);
1017 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0x40, i32, 5, 0x47, 0x3B,
1018 0x7C, 0x98, 0x40);
1019 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0x40, i32, 5, 0x47, 0x3B,
1020 0x5C, 0xD1, 0x40);
1021
1022 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0x40, i16, 5, 0x66, 0x3B,
1023 0x44, 0x11, 0x40);
1024 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0x40, i16, 5, 0x66, 0x3B,
1025 0x4C, 0x5A, 0x40);
1026 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0x40, i16, 6, 0x66, 0x47,
1027 0x3B, 0x44, 0x11, 0x40);
1028 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0x40, i16, 6, 0x66, 0x47,
1029 0x3B, 0x4C, 0x5A, 0x40);
1030 // esp cannot be an scaled index.
1031 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0x40, i16, 5, 0x66, 0x3B,
1032 0x5C, 0xAC, 0x40);
1033 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0x40, i16, 5, 0x66, 0x3B,
1034 0x64, 0xF5, 0x40);
1035 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0x40, i16, 5, 0x66, 0x3B,
1036 0x6C, 0x3E, 0x40);
1037 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0x40, i16, 5, 0x66, 0x3B,
1038 0x74, 0x47, 0x40);
1039 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0x40, i16, 5, 0x66, 0x3B,
1040 0x7C, 0x98, 0x40);
1041 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0x40, i16, 5, 0x66, 0x3B,
1042 0x5C, 0xD1, 0x40);
1043 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0x40, i16, 6, 0x66, 0x47,
1044 0x3B, 0x5C, 0xAC, 0x40);
1045 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0x40, i16, 6, 0x66, 0x47,
1046 0x3B, 0x64, 0xF5, 0x40);
1047 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0x40, i16, 6, 0x66, 0x47,
1048 0x3B, 0x6C, 0x3E, 0x40);
1049 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0x40, i16, 6, 0x66, 0x47,
1050 0x3B, 0x74, 0x47, 0x40);
1051 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0x40, i16, 6, 0x66, 0x47,
1052 0x3B, 0x7C, 0x98, 0x40);
1053 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0x40, i16, 6, 0x66, 0x47,
1054 0x3B, 0x5C, 0xD1, 0x40);
1055
1056 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0x40, i8, 4, 0x3A, 0x44,
1057 0x11, 0x40);
1058 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0x40, i8, 4, 0x3A, 0x4C,
1059 0x5A, 0x40);
1060 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0x40, i8, 5, 0x47, 0x3A, 0x44,
1061 0x11, 0x40);
1062 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0x40, i8, 5, 0x47, 0x3A,
1063 0x4C, 0x5A, 0x40);
1064 // esp cannot be an scaled index.
1065 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0x40, i8, 4, 0x3A, 0x5C,
1066 0xAC, 0x40);
1067 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0x40, i8, 5, 0x40, 0x3A,
1068 0x64, 0xF5, 0x40);
1069 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0x40, i8, 5, 0x40, 0x3A,
1070 0x6C, 0x3E, 0x40);
1071 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0x40, i8, 5, 0x40, 0x3A,
1072 0x74, 0x47, 0x40);
1073 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0x40, i8, 5, 0x40, 0x3A,
1074 0x7C, 0x98, 0x40);
1075 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0x40, i8, 4, 0x3A, 0x5C,
1076 0xD1, 0x40);
1077 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0x40, i8, 5, 0x47, 0x3A,
1078 0x5C, 0xAC, 0x40);
1079 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0x40, i8, 5, 0x47, 0x3A,
1080 0x64, 0xF5, 0x40);
1081 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0x40, i8, 5, 0x47, 0x3A,
1082 0x6C, 0x3E, 0x40);
1083 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0x40, i8, 5, 0x47, 0x3A,
1084 0x74, 0x47, 0x40);
1085 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0x40, i8, 5, 0x47, 0x3A,
1086 0x7C, 0x98, 0x40);
1087 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0x40, i8, 5, 0x47, 0x3A,
1088 0x5C, 0xD1, 0x40);
1089
1090 /* cmp GPR, Imm32(Base,Index,Scale) */
1091 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0xF0, i32, 7, 0x3B, 0x84,
1092 0x11, 0xF0, 0x00, 0x00, 0x00);
1093 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0xF0, i32, 7, 0x3B, 0x8C,
1094 0x5A, 0xF0, 0x00, 0x00, 0x00);
1095 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0xF0, i32, 8, 0x47, 0x3B,
1096 0x84, 0x11, 0xF0, 0x00, 0x00, 0x00);
1097 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0xF0, i32, 8, 0x47, 0x3B,
1098 0x8C, 0x5A, 0xF0, 0x00, 0x00, 0x00);
1099 // esp cannot be an scaled index.
1100 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0xF0, i32, 7, 0x3B, 0x9C,
1101 0xAC, 0xF0, 0x00, 0x00, 0x00);
1102 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0xF0, i32, 7, 0x3B, 0xA4,
1103 0xF5, 0xF0, 0x00, 0x00, 0x00);
1104 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0xF0, i32, 7, 0x3B, 0xAC,
1105 0x3E, 0xF0, 0x00, 0x00, 0x00);
1106 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0xF0, i32, 7, 0x3B, 0xB4,
1107 0x47, 0xF0, 0x00, 0x00, 0x00);
1108 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0xF0, i32, 7, 0x3B, 0xBC,
1109 0x98, 0xF0, 0x00, 0x00, 0x00);
1110 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0xF0, i32, 7, 0x3B, 0x9C,
1111 0xD1, 0xF0, 0x00, 0x00, 0x00);
1112 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0xF0, i32, 8, 0x47, 0x3B,
1113 0x9C, 0xAC, 0xF0, 0x00, 0x00, 0x00);
1114 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0xF0, i32, 8, 0x47, 0x3B,
1115 0xA4, 0xF5, 0xF0, 0x00, 0x00, 0x00);
1116 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0xF0, i32, 8, 0x47, 0x3B,
1117 0xAC, 0x3E, 0xF0, 0x00, 0x00, 0x00);
1118 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0xF0, i32, 8, 0x47, 0x3B,
1119 0xB4, 0x47, 0xF0, 0x00, 0x00, 0x00);
1120 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0xF0, i32, 8, 0x47, 0x3B,
1121 0xBC, 0x98, 0xF0, 0x00, 0x00, 0x00);
1122 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0xF0, i32, 8, 0x47, 0x3B,
1123 0x9C, 0xD1, 0xF0, 0x00, 0x00, 0x00);
1124
1125 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0xF0, i16, 8, 0x66, 0x3B,
1126 0x84, 0x11, 0xF0, 0x00, 0x00, 0x00);
1127 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0xF0, i16, 8, 0x66, 0x3B,
1128 0x8C, 0x5A, 0xF0, 0x00, 0x00, 0x00);
1129 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0xF0, i16, 9, 0x66, 0x47,
1130 0x3B, 0x84, 0x11, 0xF0, 0x00, 0x00, 0x00);
1131 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0xF0, i16, 9, 0x66, 0x47,
1132 0x3B, 0x8C, 0x5A, 0xF0, 0x00, 0x00, 0x00);
1133 // esp cannot be an scaled index.
1134 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0xF0, i16, 8, 0x66, 0x3B,
1135 0x9C, 0xAC, 0xF0, 0x00, 0x00, 0x00);
1136 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0xF0, i16, 8, 0x66, 0x3B,
1137 0xA4, 0xF5, 0xF0, 0x00, 0x00, 0x00);
1138 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0xF0, i16, 8, 0x66, 0x3B,
1139 0xAC, 0x3E, 0xF0, 0x00, 0x00, 0x00);
1140 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0xF0, i16, 8, 0x66, 0x3B,
1141 0xB4, 0x47, 0xF0, 0x00, 0x00, 0x00);
1142 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0xF0, i16, 8, 0x66, 0x3B,
1143 0xBC, 0x98, 0xF0, 0x00, 0x00, 0x00);
1144 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0xF0, i16, 8, 0x66, 0x3B,
1145 0x9C, 0xD1, 0xF0, 0x00, 0x00, 0x00);
1146 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0xF0, i16, 9, 0x66, 0x47,
1147 0x3B, 0x9C, 0xAC, 0xF0, 0x00, 0x00, 0x00);
1148 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0xF0, i16, 9, 0x66, 0x47,
1149 0x3B, 0xA4, 0xF5, 0xF0, 0x00, 0x00, 0x00);
1150 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0xF0, i16, 9, 0x66, 0x47,
1151 0x3B, 0xAC, 0x3E, 0xF0, 0x00, 0x00, 0x00);
1152 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0xF0, i16, 9, 0x66, 0x47,
1153 0x3B, 0xB4, 0x47, 0xF0, 0x00, 0x00, 0x00);
1154 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0xF0, i16, 9, 0x66, 0x47,
1155 0x3B, 0xBC, 0x98, 0xF0, 0x00, 0x00, 0x00);
1156 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0xF0, i16, 9, 0x66, 0x47,
1157 0x3B, 0x9C, 0xD1, 0xF0, 0x00, 0x00, 0x00);
1158
1159 TestRegAddrBaseScaledIndex(cmp, eax, ecx, edx, 1, 0xF0, i8, 7, 0x3A, 0x84,
1160 0x11, 0xF0, 0x00, 0x00, 0x00);
1161 TestRegAddrBaseScaledIndex(cmp, ecx, edx, ebx, 2, 0xF0, i8, 7, 0x3A, 0x8C,
1162 0x5A, 0xF0, 0x00, 0x00, 0x00);
1163 TestRegAddrBaseScaledIndex(cmp, r8, r9, r10, 1, 0xF0, i8, 8, 0x47, 0x3A, 0x84,
1164 0x11, 0xF0, 0x00, 0x00, 0x00);
1165 TestRegAddrBaseScaledIndex(cmp, r9, r10, r11, 2, 0xF0, i8, 8, 0x47, 0x3A,
1166 0x8C, 0x5A, 0xF0, 0x00, 0x00, 0x00);
1167 // esp cannot be an scaled index.
1168 TestRegAddrBaseScaledIndex(cmp, ebx, esp, ebp, 4, 0xF0, i8, 7, 0x3A, 0x9C,
1169 0xAC, 0xF0, 0x00, 0x00, 0x00);
1170 TestRegAddrBaseScaledIndex(cmp, esp, ebp, esi, 8, 0xF0, i8, 8, 0x40, 0x3A,
1171 0xA4, 0xF5, 0xF0, 0x00, 0x00, 0x00);
1172 TestRegAddrBaseScaledIndex(cmp, ebp, esi, edi, 1, 0xF0, i8, 8, 0x40, 0x3A,
1173 0xAC, 0x3E, 0xF0, 0x00, 0x00, 0x00);
1174 TestRegAddrBaseScaledIndex(cmp, esi, edi, eax, 2, 0xF0, i8, 8, 0x40, 0x3A,
1175 0xB4, 0x47, 0xF0, 0x00, 0x00, 0x00);
1176 TestRegAddrBaseScaledIndex(cmp, edi, eax, ebx, 4, 0xF0, i8, 8, 0x40, 0x3A,
1177 0xBC, 0x98, 0xF0, 0x00, 0x00, 0x00);
1178 TestRegAddrBaseScaledIndex(cmp, ebx, ecx, edx, 8, 0xF0, i8, 7, 0x3A, 0x9C,
1179 0xD1, 0xF0, 0x00, 0x00, 0x00);
1180 TestRegAddrBaseScaledIndex(cmp, r11, r12, r13, 4, 0xF0, i8, 8, 0x47, 0x3A,
1181 0x9C, 0xAC, 0xF0, 0x00, 0x00, 0x00);
1182 TestRegAddrBaseScaledIndex(cmp, r12, r13, r14, 8, 0xF0, i8, 8, 0x47, 0x3A,
1183 0xA4, 0xF5, 0xF0, 0x00, 0x00, 0x00);
1184 TestRegAddrBaseScaledIndex(cmp, r13, r14, r15, 1, 0xF0, i8, 8, 0x47, 0x3A,
1185 0xAC, 0x3E, 0xF0, 0x00, 0x00, 0x00);
1186 TestRegAddrBaseScaledIndex(cmp, r14, r15, r8, 2, 0xF0, i8, 8, 0x47, 0x3A,
1187 0xB4, 0x47, 0xF0, 0x00, 0x00, 0x00);
1188 TestRegAddrBaseScaledIndex(cmp, r15, r8, r11, 4, 0xF0, i8, 8, 0x47, 0x3A,
1189 0xBC, 0x98, 0xF0, 0x00, 0x00, 0x00);
1190 TestRegAddrBaseScaledIndex(cmp, r11, r9, r10, 8, 0xF0, i8, 8, 0x47, 0x3A,
1191 0x9C, 0xD1, 0xF0, 0x00, 0x00, 0x00);
1192
1193 /* cmp Addr, Imm */
1194 // Note: at this point we trust the assembler knows how to encode addresses,
1195 // so no more exhaustive addressing mode testing.
1196 TestAddrBaseScaledIndexImm(cmp, eax, ecx, 1, 0xF0, 0x12, i32, 8, 0x83, 0xBC,
1197 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1198 TestAddrBaseScaledIndexImm(cmp, ecx, edx, 1, 0xF0, 0xF0, i32, 11, 0x81, 0xBC,
1199 0x11, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
1200 0x00);
1201 TestAddrBaseScaledIndexImm(cmp, r8, r9, 1, 0xF0, 0x12, i32, 9, 0x43, 0x83,
1202 0xBC, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1203 TestAddrBaseScaledIndexImm(cmp, r9, r10, 1, 0xF0, 0xF0, i32, 12, 0x43, 0x81,
1204 0xBC, 0x11, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00,
1205 0x00, 0x00);
1206
1207 TestAddrBaseScaledIndexImm(cmp, eax, ecx, 1, 0xF0, 0x12, i16, 9, 0x66, 0x83,
1208 0xBC, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1209 TestAddrBaseScaledIndexImm(cmp, ecx, edx, 1, 0xF0, 0xF0, i16, 10, 0x66, 0x81,
1210 0xBC, 0x11, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00);
1211 TestAddrBaseScaledIndexImm(cmp, r8, r9, 1, 0xF0, 0x12, i16, 10, 0x66, 0x43,
1212 0x83, 0xBC, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1213 TestAddrBaseScaledIndexImm(cmp, r9, r10, 1, 0xF0, 0xF0, i16, 11, 0x66, 0x43,
1214 0x81, 0xBC, 0x11, 0xF0, 0x00, 0x00, 0x00, 0xF0,
1215 0x00);
1216
1217 TestAddrBaseScaledIndexImm(cmp, eax, ecx, 1, 0xF0, 0x12, i8, 8, 0x80, 0xBC,
1218 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1219 TestAddrBaseScaledIndexImm(cmp, r8, r9, 1, 0xF0, 0x12, i8, 9, 0x43, 0x80,
1220 0xBC, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x12);
1221
1222 /* cmp Addr, GPR */
1223 TestAddrBaseScaledIndexReg(cmp, eax, ecx, 1, 0xF0, edx, i32, 7, 0x39, 0x94,
1224 0x08, 0xF0, 0x00, 0x00, 0x00);
1225 TestAddrBaseScaledIndexReg(cmp, r8, r9, 1, 0xF0, r10, i32, 8, 0x47, 0x39,
1226 0x94, 0x08, 0xF0, 0x00, 0x00, 0x00);
1227
1228 TestAddrBaseScaledIndexReg(cmp, eax, ecx, 1, 0xF0, edx, i16, 8, 0x66, 0x39,
1229 0x94, 0x08, 0xF0, 0x00, 0x00, 0x00);
1230 TestAddrBaseScaledIndexReg(cmp, r8, r9, 1, 0xF0, r10, i16, 9, 0x66, 0x47,
1231 0x39, 0x94, 0x08, 0xF0, 0x00, 0x00, 0x00);
1232
1233 TestAddrBaseScaledIndexReg(cmp, eax, ecx, 1, 0xF0, edx, i8, 7, 0x38, 0x94,
1234 0x08, 0xF0, 0x00, 0x00, 0x00);
1235 TestAddrBaseScaledIndexReg(cmp, r8, r9, 1, 0xF0, r10, i8, 8, 0x47, 0x38, 0x94,
1236 0x08, 0xF0, 0x00, 0x00, 0x00);
1237
1238 #undef TestAddrBaseScaledIndexReg
1239 #undef TestAddrBaseScaledIndexImm
1240 #undef TestRegAddrBaseScaledIndex
1241 #undef TestRegAddrScaledIndex
1242 #undef TestRegAddrBase
1243 #undef TestRegAbsoluteAddr
1244 #undef TestRegImm
1245 #undef TestRegReg
1246 }
1247
1248 // After these tests we should have a sane environment; we know the following
1249 // work:
1250 //
1251 // (*) zeroing eax, ebx, ecx, edx, edi, and esi;
1252 // (*) call $4 instruction (used for ip materialization);
1253 // (*) register push and pop;
1254 // (*) cmp reg, reg; and
1255 // (*) returning from functions.
1256 //
1257 // We can now dive into testing each emitting method in AssemblerX8664. Each
1258 // test will emit some instructions for performing the test. The assembled
1259 // instructions will operate in a "safe" environment. All x86-64 registers are
1260 // spilled to the program stack, and the registers are then zeroed out, with the
1261 // exception of %esp and %r9.
1262 //
1263 // The jitted code and the unittest code will share the same stack. Therefore,
1264 // test harnesses need to ensure it does not leave anything it pushed on the
1265 // stack.
1266 //
1267 // %r9 is initialized with a pointer for rIP-based addressing. This pointer is
1268 // used for position-independent access to a scratchpad area for use in tests.
1269 // In theory we could use rip-based addressing, but in practice that would
1270 // require creating fixups, which would, in turn, require creating a global
1271 // context. We therefore rely on the same technique used for pic code in x86-32
1272 // (i.e., IP materialization). Upon a test start up, a call(NextInstruction) is
1273 // executed. We then pop the return address from the stack, and use it for pic
1274 // addressing.
1275 //
1276 // The jitted code will look like the following:
1277 //
1278 // test:
1279 // push %r9
1280 // call test$materialize_ip
1281 // test$materialize_ip: <<------- %r9 will point here
1282 // pop %r9
1283 // push %rax
1284 // push %rbx
1285 // push %rcx
1286 // push %rdx
1287 // push %rbp
1288 // push %rdi
1289 // push %rsi
1290 // push %r8
1291 // push %r10
1292 // push %r11
1293 // push %r12
1294 // push %r13
1295 // push %r14
1296 // push %r15
1297 // mov $0, %rax
1298 // mov $0, %rbx
1299 // mov $0, %rcx
1300 // mov $0, %rdx
1301 // mov $0, %rbp
1302 // mov $0, %rdi
1303 // mov $0, %rsi
1304 // mov $0, %r8
1305 // mov $0, %r10
1306 // mov $0, %r11
1307 // mov $0, %r12
1308 // mov $0, %r13
1309 // mov $0, %r14
1310 // mov $0, %r15
1311 //
1312 // << test code goes here >>
1313 //
1314 // mov %rax, { 0 + $ScratchpadOffset}(%rbp)
1315 // mov %rbx, { 8 + $ScratchpadOffset}(%rbp)
1316 // mov %rcx, { 16 + $ScratchpadOffset}(%rbp)
1317 // mov %rdx, { 24 + $ScratchpadOffset}(%rbp)
1318 // mov %rdi, { 32 + $ScratchpadOffset}(%rbp)
1319 // mov %rsi, { 40 + $ScratchpadOffset}(%rbp)
1320 // mov %rbp, { 48 + $ScratchpadOffset}(%rbp)
1321 // mov %rsp, { 56 + $ScratchpadOffset}(%rbp)
1322 // mov %r8, { 64 + $ScratchpadOffset}(%rbp)
1323 // mov %r9, { 72 + $ScratchpadOffset}(%rbp)
1324 // mov %r10, { 80 + $ScratchpadOffset}(%rbp)
1325 // mov %r11, { 88 + $ScratchpadOffset}(%rbp)
1326 // mov %r12, { 96 + $ScratchpadOffset}(%rbp)
1327 // mov %r13, {104 + $ScratchpadOffset}(%rbp)
1328 // mov %r14, {112 + $ScratchpadOffset}(%rbp)
1329 // mov %r15, {120 + $ScratchpadOffset}(%rbp)
1330 // movups %xmm0, {128 + $ScratchpadOffset}(%rbp)
1331 // movups %xmm1, {136 + $ScratchpadOffset}(%rbp)
1332 // movups %xmm2, {144 + $ScratchpadOffset}(%rbp)
1333 // movusp %xmm3, {152 + $ScratchpadOffset}(%rbp)
Jim Stichnoth 2015/07/26 15:31:11 movups not movusp, right?
John 2015/07/27 20:35:58 Done.
1334 // movusp %xmm4, {160 + $ScratchpadOffset}(%rbp)
1335 // movusp %xmm5, {168 + $ScratchpadOffset}(%rbp)
1336 // movusp %xmm6, {176 + $ScratchpadOffset}(%rbp)
1337 // movusp %xmm7, {184 + $ScratchpadOffset}(%rbp)
1338 // movusp %xmm8, {192 + $ScratchpadOffset}(%rbp)
1339 // movusp %xmm9, {200 + $ScratchpadOffset}(%rbp)
1340 // movusp %xmm10, {208 + $ScratchpadOffset}(%rbp)
1341 // movusp %xmm11, {216 + $ScratchpadOffset}(%rbp)
1342 // movusp %xmm12, {224 + $ScratchpadOffset}(%rbp)
1343 // movusp %xmm13, {232 + $ScratchpadOffset}(%rbp)
1344 // movusp %xmm14, {240 + $ScratchpadOffset}(%rbp)
1345 // movusp %xmm15, {248 + $ScratchpadOffset}(%rbp)
1346 //
1347 // pop %r15
1348 // pop %r14
1349 // pop %r13
1350 // pop %r12
1351 // pop %r11
1352 // pop %r10
1353 // pop %r8
1354 // pop %rsi
1355 // pop %rdi
1356 // pop %rbp
1357 // pop %rdx
1358 // pop %rcx
1359 // pop %rbx
1360 // pop %rax
1361 // pop %r9
1362 // ret
1363 //
1364 // << ... >>
1365 //
1366 // scratchpad: <<------- accessed via $Offset(%ebp)
1367 //
1368 // << test scratch area >>
1369 //
1370 // TODO(jpp): test the
1371 //
1372 // mov %reg, $Offset(%ebp)
1373 // movups %xmm, $Offset(%ebp)
1374 //
1375 // encodings using the low level assembler test ensuring that the register
1376 // values can be written to the scratchpad area.
1377 //
1378 // r9 was deliberately choosen so that every instruction accessing memory would
1379 // fail if the rex prefix was not emitted for it.
1380 class AssemblerX8664Test : public AssemblerX8664TestBase {
1381 protected:
1382 // Dqword is used to represent 128-bit data types. The Dqword's contents are
1383 // the same as the contents read from memory. Tests can then use the union
1384 // members to verify the tests' outputs.
1385 //
1386 // NOTE: We want sizeof(Dqword) == sizeof(uint64_t) * 2. In other words, we
1387 // want Dqword's contents to be **exactly** what the memory contents were so
1388 // that we can do, e.g.,
1389 //
1390 // ...
1391 // float Ret[4];
1392 // // populate Ret
1393 // return *reinterpret_cast<Dqword *>(&Ret);
1394 //
1395 // While being an ugly hack, this kind of return statements are used
1396 // extensively in the PackedArith (see below) class.
1397 union Dqword {
1398 template <typename T0, typename T1, typename T2, typename T3,
1399 typename = typename std::enable_if<
1400 std::is_floating_point<T0>::value>::type>
1401 Dqword(T0 F0, T1 F1, T2 F2, T3 F3) {
1402 F32[0] = F0;
1403 F32[1] = F1;
1404 F32[2] = F2;
1405 F32[3] = F3;
1406 }
1407
1408 template <typename T>
1409 Dqword(typename std::enable_if<std::is_same<T, int32_t>::value, T>::type I0,
1410 T I1, T I2, T I3) {
1411 I32[0] = I0;
1412 I32[1] = I1;
1413 I32[2] = I2;
1414 I32[3] = I3;
1415 }
1416
1417 template <typename T>
1418 Dqword(typename std::enable_if<std::is_same<T, uint64_t>::value, T>::type
1419 U64_0,
1420 T U64_1) {
1421 U64[0] = U64_0;
1422 U64[1] = U64_1;
1423 }
1424
1425 template <typename T>
1426 Dqword(typename std::enable_if<std::is_same<T, double>::value, T>::type D0,
1427 T D1) {
1428 F64[0] = D0;
1429 F64[1] = D1;
1430 }
1431
1432 bool operator==(const Dqword &Rhs) const {
1433 return std::memcmp(this, &Rhs, sizeof(*this)) == 0;
1434 }
1435
1436 double F64[2];
1437 uint64_t U64[2];
1438 int64_t I64[2];
1439
1440 float F32[4];
1441 uint32_t U32[4];
1442 int32_t I32[4];
1443
1444 uint16_t U16[8];
1445 int16_t I16[8];
1446
1447 uint8_t U8[16];
1448 int8_t I8[16];
1449
1450 private:
1451 Dqword() = delete;
1452 };
1453
1454 // As stated, we want this condition to hold, so we assert.
1455 static_assert(sizeof(Dqword) == 2 * sizeof(uint64_t),
1456 "Dqword has the wrong size.");
1457
1458 // PackedArith is an interface provider for Dqwords. PackedArith's C argument
1459 // is the undelying Dqword's type, which is then used so that we can define
1460 // operators in terms of C++ operators on the underlying elements' type.
1461 template <typename C> class PackedArith {
1462 public:
1463 static constexpr uint32_t N = sizeof(Dqword) / sizeof(C);
1464 static_assert(N * sizeof(C) == sizeof(Dqword),
1465 "Invalid template paramenter.");
1466 static_assert((N & 1) == 0, "N should be divisible by 2");
1467
1468 #define DefinePackedComparisonOperator(Op) \
1469 template <typename Container = C, int Size = N> \
1470 typename std::enable_if<std::is_floating_point<Container>::value, \
1471 Dqword>::type \
1472 operator Op(const Dqword &Rhs) const { \
1473 using ElemType = \
1474 typename std::conditional<std::is_same<float, Container>::value, \
1475 int32_t, int64_t>::type; \
1476 static_assert(sizeof(ElemType) == sizeof(Container), \
1477 "Check ElemType definition."); \
1478 const ElemType *const RhsPtr = \
1479 reinterpret_cast<const ElemType *const>(&Rhs); \
1480 const ElemType *const LhsPtr = \
1481 reinterpret_cast<const ElemType *const>(&Lhs); \
1482 ElemType Ret[N]; \
1483 for (uint32_t i = 0; i < N; ++i) { \
1484 Ret[i] = (LhsPtr[i] Op RhsPtr[i]) ? -1 : 0; \
1485 } \
1486 return *reinterpret_cast<Dqword *>(&Ret); \
1487 }
1488
1489 DefinePackedComparisonOperator(< );
1490 DefinePackedComparisonOperator(<= );
1491 DefinePackedComparisonOperator(> );
1492 DefinePackedComparisonOperator(>= );
1493 DefinePackedComparisonOperator(== );
1494 DefinePackedComparisonOperator(!= );
1495
1496 #undef DefinePackedComparisonOperator
1497
1498 #define DefinePackedOrdUnordComparisonOperator(Op, Ordered) \
1499 template <typename Container = C, int Size = N> \
1500 typename std::enable_if<std::is_floating_point<Container>::value, \
1501 Dqword>::type \
1502 Op(const Dqword &Rhs) const { \
1503 using ElemType = \
1504 typename std::conditional<std::is_same<float, Container>::value, \
1505 int32_t, int64_t>::type; \
1506 static_assert(sizeof(ElemType) == sizeof(Container), \
1507 "Check ElemType definition."); \
1508 const Container *const RhsPtr = \
1509 reinterpret_cast<const Container *const>(&Rhs); \
1510 const Container *const LhsPtr = \
1511 reinterpret_cast<const Container *const>(&Lhs); \
1512 ElemType Ret[N]; \
1513 for (uint32_t i = 0; i < N; ++i) { \
1514 Ret[i] = (!(LhsPtr[i] == LhsPtr[i]) || !(RhsPtr[i] == RhsPtr[i])) != \
1515 (Ordered) \
1516 ? -1 \
1517 : 0; \
1518 } \
1519 return *reinterpret_cast<Dqword *>(&Ret); \
1520 }
1521
1522 DefinePackedOrdUnordComparisonOperator(ord, true);
1523 DefinePackedOrdUnordComparisonOperator(unord, false);
1524 #undef DefinePackedOrdUnordComparisonOperator
1525
1526 #define DefinePackedArithOperator(Op, RhsIndexChanges, NeedsInt) \
1527 template <typename Container = C, int Size = N> \
1528 Dqword operator Op(const Dqword &Rhs) const { \
1529 using ElemTypeForFp = typename std::conditional< \
1530 !(NeedsInt), Container, \
1531 typename std::conditional< \
1532 std::is_same<Container, float>::value, uint32_t, \
1533 typename std::conditional<std::is_same<Container, double>::value, \
1534 uint64_t, void>::type>::type>::type; \
1535 using ElemType = \
1536 typename std::conditional<std::is_integral<Container>::value, \
1537 Container, ElemTypeForFp>::type; \
1538 static_assert(!std::is_same<void, ElemType>::value, \
1539 "Check ElemType definition."); \
1540 const ElemType *const RhsPtr = \
1541 reinterpret_cast<const ElemType *const>(&Rhs); \
1542 const ElemType *const LhsPtr = \
1543 reinterpret_cast<const ElemType *const>(&Lhs); \
1544 ElemType Ret[N]; \
1545 for (uint32_t i = 0; i < N; ++i) { \
1546 Ret[i] = LhsPtr[i] Op RhsPtr[(RhsIndexChanges) ? i : 0]; \
1547 } \
1548 return *reinterpret_cast<Dqword *>(&Ret); \
1549 }
1550
1551 DefinePackedArithOperator(>>, false, true);
1552 DefinePackedArithOperator(<<, false, true);
1553 DefinePackedArithOperator(+, true, false);
1554 DefinePackedArithOperator(-, true, false);
1555 DefinePackedArithOperator(/, true, false);
1556 DefinePackedArithOperator(&, true, true);
1557 DefinePackedArithOperator(|, true, true);
1558 DefinePackedArithOperator (^, true, true);
1559
1560 #undef DefinePackedArithOperator
1561
1562 #define DefinePackedArithShiftImm(Op) \
1563 template <typename Container = C, int Size = N> \
1564 Dqword operator Op(uint8_t imm) const { \
1565 const Container *const LhsPtr = \
1566 reinterpret_cast<const Container *const>(&Lhs); \
1567 Container Ret[N]; \
1568 for (uint32_t i = 0; i < N; ++i) { \
1569 Ret[i] = LhsPtr[i] Op imm; \
1570 } \
1571 return *reinterpret_cast<Dqword *>(&Ret); \
1572 }
1573
1574 DefinePackedArithShiftImm(>> );
1575 DefinePackedArithShiftImm(<< );
1576
1577 #undef DefinePackedArithShiftImm
1578
1579 template <typename Container = C, int Size = N>
1580 typename std::enable_if<std::is_signed<Container>::value ||
1581 std::is_floating_point<Container>::value,
1582 Dqword>::type
1583 operator*(const Dqword &Rhs) const {
1584 static_assert((std::is_integral<Container>::value &&
1585 sizeof(Container) < sizeof(uint64_t)) ||
1586 std::is_floating_point<Container>::value,
1587 "* is only defined for i(8|16|32), and fp types.");
1588
1589 const Container *const RhsPtr =
1590 reinterpret_cast<const Container *const>(&Rhs);
1591 const Container *const LhsPtr =
1592 reinterpret_cast<const Container *const>(&Lhs);
1593 Container Ret[Size];
1594 for (uint32_t i = 0; i < Size; ++i) {
1595 Ret[i] = LhsPtr[i] * RhsPtr[i];
1596 }
1597 return *reinterpret_cast<Dqword *>(&Ret);
1598 }
1599
1600 template <typename Container = C, int Size = N,
1601 typename = typename std::enable_if<
1602 !std::is_signed<Container>::value>::type>
1603 Dqword operator*(const Dqword &Rhs) const {
1604 static_assert(std::is_integral<Container>::value &&
1605 sizeof(Container) < sizeof(uint64_t),
1606 "* is only defined for ui(8|16|32)");
1607 using NextType = typename std::conditional<
1608 sizeof(Container) == 1, uint16_t,
1609 typename std::conditional<sizeof(Container) == 2, uint32_t,
1610 uint64_t>::type>::type;
1611 static_assert(sizeof(Container) * 2 == sizeof(NextType),
1612 "Unexpected size");
1613
1614 const Container *const RhsPtr =
1615 reinterpret_cast<const Container *const>(&Rhs);
1616 const Container *const LhsPtr =
1617 reinterpret_cast<const Container *const>(&Lhs);
1618 NextType Ret[Size / 2];
1619 for (uint32_t i = 0; i < Size; i += 2) {
1620 Ret[i / 2] =
1621 static_cast<NextType>(LhsPtr[i]) * static_cast<NextType>(RhsPtr[i]);
1622 }
1623 return *reinterpret_cast<Dqword *>(&Ret);
1624 }
1625
1626 template <typename Container = C, int Size = N>
1627 PackedArith<Container> operator~() const {
1628 const Container *const LhsPtr =
1629 reinterpret_cast<const Container *const>(&Lhs);
1630 Container Ret[Size];
1631 for (uint32_t i = 0; i < Size; ++i) {
1632 Ret[i] = ~LhsPtr[i];
1633 }
1634 return PackedArith<Container>(*reinterpret_cast<Dqword *>(&Ret));
1635 }
1636
1637 #define MinMaxOperations(Name, Suffix) \
1638 template <typename Container = C, int Size = N> \
1639 Dqword Name##Suffix(const Dqword &Rhs) const { \
1640 static_assert(std::is_floating_point<Container>::value, \
1641 #Name #Suffix "ps is only available for fp."); \
1642 const Container *const RhsPtr = \
1643 reinterpret_cast<const Container *const>(&Rhs); \
1644 const Container *const LhsPtr = \
1645 reinterpret_cast<const Container *const>(&Lhs); \
1646 Container Ret[Size]; \
1647 for (uint32_t i = 0; i < Size; ++i) { \
1648 Ret[i] = std::Name(LhsPtr[i], RhsPtr[i]); \
1649 } \
1650 return *reinterpret_cast<Dqword *>(&Ret); \
1651 }
1652
1653 MinMaxOperations(max, ps);
1654 MinMaxOperations(max, pd);
1655 MinMaxOperations(min, ps);
1656 MinMaxOperations(min, pd);
1657 #undef MinMaxOperations
1658
1659 template <typename Container = C, int Size = N>
1660 Dqword blendWith(const Dqword &Rhs, const Dqword &Mask) const {
1661 using MaskType = typename std::conditional<
1662 sizeof(Container) == 1, int8_t,
1663 typename std::conditional<sizeof(Container) == 2, int16_t,
1664 int32_t>::type>::type;
1665 static_assert(sizeof(MaskType) == sizeof(Container),
1666 "MaskType has the wrong size.");
1667 const Container *const RhsPtr =
1668 reinterpret_cast<const Container *const>(&Rhs);
1669 const Container *const LhsPtr =
1670 reinterpret_cast<const Container *const>(&Lhs);
1671 const MaskType *const MaskPtr =
1672 reinterpret_cast<const MaskType *const>(&Mask);
1673 Container Ret[Size];
1674 for (int i = 0; i < Size; ++i) {
1675 Ret[i] = ((MaskPtr[i] < 0) ? RhsPtr : LhsPtr)[i];
1676 }
1677 return *reinterpret_cast<Dqword *>(&Ret);
1678 }
1679
1680 private:
1681 // The AssemblerX8664Test class needs to be a friend so that it can create
1682 // PackedArith objects (see below.)
1683 friend class AssemblerX8664Test;
1684
1685 explicit PackedArith(const Dqword &MyLhs) : Lhs(MyLhs) {}
1686
1687 // Lhs can't be a & because operator~ returns a temporary object that needs
1688 // access to its own Dqword.
1689 const Dqword Lhs;
1690 };
1691
1692 // Named constructor for PackedArith objects.
1693 template <typename C> static PackedArith<C> packedAs(const Dqword &D) {
1694 return PackedArith<C>(D);
1695 }
1696
1697 AssemblerX8664Test() { reset(); }
1698
1699 void reset() {
1700 AssemblerX8664TestBase::reset();
1701
1702 NeedsEpilogue = true;
1703 // These dwords are allocated for saving the GPR state after the jitted code
1704 // runs.
1705 NumAllocatedDwords = AssembledTest::ScratchpadSlots;
1706 addPrologue();
1707 }
1708
1709 // AssembledTest is a wrapper around a PROT_EXEC mmap'ed buffer. This buffer
1710 // contains both the test code as well as prologue/epilogue, and the
1711 // scratchpad area that tests may use -- all tests use this scratchpad area
1712 // for storing the processor's registers after the tests executed. This class
1713 // also exposes helper methods for reading the register state after test
1714 // execution, as well as for reading the scratchpad area.
1715 class AssembledTest {
1716 AssembledTest() = delete;
1717 AssembledTest(const AssembledTest &) = delete;
1718 AssembledTest &operator=(const AssembledTest &) = delete;
1719
1720 public:
1721 static constexpr uint32_t MaximumCodeSize = 1 << 20;
1722 static constexpr uint32_t raxSlot() { return 0; }
1723 static constexpr uint32_t rbxSlot() { return 2; }
1724 static constexpr uint32_t rcxSlot() { return 4; }
1725 static constexpr uint32_t rdxSlot() { return 6; }
1726 static constexpr uint32_t rdiSlot() { return 8; }
1727 static constexpr uint32_t rsiSlot() { return 10; }
1728 static constexpr uint32_t rbpSlot() { return 12; }
1729 static constexpr uint32_t rspSlot() { return 14; }
1730 static constexpr uint32_t r8Slot() { return 16; }
1731 static constexpr uint32_t r9Slot() { return 18; }
1732 static constexpr uint32_t r10Slot() { return 20; }
1733 static constexpr uint32_t r11Slot() { return 22; }
1734 static constexpr uint32_t r12Slot() { return 24; }
1735 static constexpr uint32_t r13Slot() { return 26; }
1736 static constexpr uint32_t r14Slot() { return 28; }
1737 static constexpr uint32_t r15Slot() { return 30; }
1738
1739 // save 4 dwords for each xmm registers.
1740 static constexpr uint32_t xmm0Slot() { return 32; }
1741 static constexpr uint32_t xmm1Slot() { return 36; }
1742 static constexpr uint32_t xmm2Slot() { return 40; }
1743 static constexpr uint32_t xmm3Slot() { return 44; }
1744 static constexpr uint32_t xmm4Slot() { return 48; }
1745 static constexpr uint32_t xmm5Slot() { return 52; }
1746 static constexpr uint32_t xmm6Slot() { return 56; }
1747 static constexpr uint32_t xmm7Slot() { return 60; }
1748 static constexpr uint32_t xmm8Slot() { return 64; }
1749 static constexpr uint32_t xmm9Slot() { return 68; }
1750 static constexpr uint32_t xmm10Slot() { return 72; }
1751 static constexpr uint32_t xmm11Slot() { return 76; }
1752 static constexpr uint32_t xmm12Slot() { return 80; }
1753 static constexpr uint32_t xmm13Slot() { return 84; }
1754 static constexpr uint32_t xmm14Slot() { return 88; }
1755 static constexpr uint32_t xmm15Slot() { return 92; }
1756
1757 static constexpr uint32_t ScratchpadSlots = 96;
1758
1759 AssembledTest(const uint8_t *Data, const size_t MySize,
1760 const size_t ExtraStorageDwords)
1761 : Size(MaximumCodeSize + 4 * ExtraStorageDwords) {
1762 // MaxCodeSize is needed because EXPECT_LT needs a symbol with a name --
1763 // probably a compiler bug?
1764 uint32_t MaxCodeSize = MaximumCodeSize;
1765 EXPECT_LT(MySize, MaxCodeSize);
1766 assert(MySize < MaximumCodeSize);
1767 ExecutableData = mmap(nullptr, Size, PROT_WRITE | PROT_READ | PROT_EXEC,
1768 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1769 EXPECT_NE(MAP_FAILED, ExecutableData) << strerror(errno);
1770 assert(MAP_FAILED != ExecutableData);
1771 std::memcpy(ExecutableData, Data, MySize);
1772 }
1773
1774 // We allow AssembledTest to be moved so that we can return objects of
1775 // this type.
1776 AssembledTest(AssembledTest &&Buffer)
1777 : ExecutableData(Buffer.ExecutableData), Size(Buffer.Size) {
1778 Buffer.ExecutableData = nullptr;
1779 Buffer.Size = 0;
1780 }
1781
1782 AssembledTest &operator=(AssembledTest &&Buffer) {
1783 ExecutableData = Buffer.ExecutableData;
1784 Buffer.ExecutableData = nullptr;
1785 Size = Buffer.Size;
1786 Buffer.Size = 0;
1787 return *this;
1788 }
1789
1790 ~AssembledTest() {
1791 if (ExecutableData != nullptr) {
1792 munmap(ExecutableData, Size);
1793 ExecutableData = nullptr;
1794 }
1795 }
1796
1797 void run() const { reinterpret_cast<void (*)()>(ExecutableData)(); }
1798
1799 #define LegacyRegAccessors(NewName, Name64, Name32, Name16, Name8) \
1800 static_assert(Encoded_GPR_##NewName() == Encoded_GPR_##Name64(), \
1801 "Invalid aliasing."); \
1802 uint64_t NewName() const { \
1803 return contentsOfQword(AssembledTest::Name64##Slot()); \
1804 } \
1805 static_assert(Encoded_GPR_##NewName##q() == Encoded_GPR_##Name64(), \
1806 "Invalid aliasing."); \
1807 uint64_t NewName##q() const { \
1808 return contentsOfQword(AssembledTest::Name64##Slot()); \
1809 } \
1810 static_assert(Encoded_GPR_##NewName##d() == Encoded_GPR_##Name64(), \
1811 "Invalid aliasing."); \
1812 uint32_t NewName##d() const { \
1813 return contentsOfQword(AssembledTest::Name64##Slot()); \
1814 } \
1815 static_assert(Encoded_GPR_##NewName##w() == Encoded_GPR_##Name64(), \
1816 "Invalid aliasing."); \
1817 uint16_t NewName##w() const { \
1818 return contentsOfQword(AssembledTest::Name64##Slot()); \
1819 } \
1820 static_assert(Encoded_GPR_##NewName##l() == Encoded_GPR_##Name64(), \
1821 "Invalid aliasing."); \
1822 uint8_t NewName##l() const { \
1823 return contentsOfQword(AssembledTest::Name64##Slot()); \
1824 } \
1825 static_assert(Encoded_GPR_##Name64() == Encoded_GPR_##Name64(), \
1826 "Invalid aliasing."); \
1827 uint64_t Name64() const { \
1828 return contentsOfQword(AssembledTest::Name64##Slot()); \
1829 } \
1830 static_assert(Encoded_GPR_##Name32() == Encoded_GPR_##Name64(), \
1831 "Invalid aliasing."); \
1832 uint32_t Name32() const { \
1833 return contentsOfQword(AssembledTest::Name64##Slot()); \
1834 } \
1835 static_assert(Encoded_GPR_##Name16() == Encoded_GPR_##Name64(), \
1836 "Invalid aliasing."); \
1837 uint16_t Name16() const { \
1838 return contentsOfQword(AssembledTest::Name64##Slot()); \
1839 } \
1840 static_assert(Encoded_GPR_##Name8() == Encoded_GPR_##Name64(), \
1841 "Invalid aliasing."); \
1842 uint8_t Name8() const { \
1843 return contentsOfQword(AssembledTest::Name64##Slot()); \
1844 }
1845 #define NewRegAccessors(NewName) \
1846 uint64_t NewName() const { \
1847 return contentsOfQword(AssembledTest::NewName##Slot()); \
1848 } \
1849 uint64_t NewName##q() const { \
1850 return contentsOfQword(AssembledTest::NewName##Slot()); \
1851 } \
1852 uint32_t NewName##d() const { \
1853 return contentsOfQword(AssembledTest::NewName##Slot()); \
1854 } \
1855 uint16_t NewName##w() const { \
1856 return contentsOfQword(AssembledTest::NewName##Slot()); \
1857 } \
1858 uint8_t NewName##l() const { \
1859 return contentsOfQword(AssembledTest::NewName##Slot()); \
1860 }
1861 #define XmmRegAccessor(Name) \
1862 template <typename T> T Name() const { \
1863 return xmm<T>(AssembledTest::Name##Slot()); \
1864 }
1865 LegacyRegAccessors(r0, rsp, esp, sp, spl);
1866 LegacyRegAccessors(r1, rax, eax, ax, al);
1867 LegacyRegAccessors(r2, rbx, ebx, bx, bl);
1868 LegacyRegAccessors(r3, rcx, ecx, cx, cl);
1869 LegacyRegAccessors(r4, rdx, edx, dx, dl);
1870 LegacyRegAccessors(r5, rbp, ebp, bp, bpl);
1871 LegacyRegAccessors(r6, rsi, esi, si, sil);
1872 LegacyRegAccessors(r7, rdi, edi, di, dil);
1873 NewRegAccessors(r8);
1874 NewRegAccessors(r9);
1875 NewRegAccessors(r10);
1876 NewRegAccessors(r11);
1877 NewRegAccessors(r12);
1878 NewRegAccessors(r13);
1879 NewRegAccessors(r14);
1880 NewRegAccessors(r15);
1881 XmmRegAccessor(xmm0);
1882 XmmRegAccessor(xmm1);
1883 XmmRegAccessor(xmm2);
1884 XmmRegAccessor(xmm3);
1885 XmmRegAccessor(xmm4);
1886 XmmRegAccessor(xmm5);
1887 XmmRegAccessor(xmm6);
1888 XmmRegAccessor(xmm7);
1889 XmmRegAccessor(xmm8);
1890 XmmRegAccessor(xmm9);
1891 XmmRegAccessor(xmm10);
1892 XmmRegAccessor(xmm11);
1893 XmmRegAccessor(xmm12);
1894 XmmRegAccessor(xmm13);
1895 XmmRegAccessor(xmm14);
1896 XmmRegAccessor(xmm15);
1897 #undef XmmRegAccessor
1898 #undef NewRegAccessors
1899 #undef LegacyRegAccessors
1900
1901 // contentsOfDword is used for reading the values in the scratchpad area.
1902 // Valid arguments are the dword ids returned by
1903 // AssemblerX8664Test::allocateDword() -- other inputs are considered
1904 // invalid, and are not guaranteed to work if the implementation changes.
1905 template <typename T = uint32_t, typename = typename std::enable_if<
1906 sizeof(T) == sizeof(uint32_t)>::type>
1907 T contentsOfDword(uint32_t Dword) const {
1908 return *reinterpret_cast<T *>(static_cast<uint8_t *>(ExecutableData) +
1909 dwordOffset(Dword));
1910 }
1911
1912 template <typename T = uint64_t, typename = typename std::enable_if<
1913 sizeof(T) == sizeof(uint64_t)>::type>
1914 T contentsOfQword(uint32_t InitialDword) const {
1915 return *reinterpret_cast<T *>(static_cast<uint8_t *>(ExecutableData) +
1916 dwordOffset(InitialDword));
1917 }
1918
1919 Dqword contentsOfDqword(uint32_t InitialDword) const {
1920 return *reinterpret_cast<Dqword *>(
1921 static_cast<uint8_t *>(ExecutableData) +
1922 dwordOffset(InitialDword));
1923 }
1924
1925 template <typename T = uint32_t, typename = typename std::enable_if<
1926 sizeof(T) == sizeof(uint32_t)>::type>
1927 void setDwordTo(uint32_t Dword, T value) {
1928 *reinterpret_cast<uint32_t *>(static_cast<uint8_t *>(ExecutableData) +
1929 dwordOffset(Dword)) =
1930 *reinterpret_cast<uint32_t *>(&value);
1931 }
1932
1933 template <typename T = uint64_t, typename = typename std::enable_if<
1934 sizeof(T) == sizeof(uint64_t)>::type>
1935 void setQwordTo(uint32_t InitialDword, T value) {
1936 *reinterpret_cast<uint64_t *>(static_cast<uint8_t *>(ExecutableData) +
1937 dwordOffset(InitialDword)) =
1938 *reinterpret_cast<uint64_t *>(&value);
1939 }
1940
1941 void setDqwordTo(uint32_t InitialDword, const Dqword &qdword) {
1942 setQwordTo(InitialDword, qdword.U64[0]);
1943 setQwordTo(InitialDword + 2, qdword.U64[1]);
1944 }
1945
1946 private:
1947 template <typename T>
1948 typename std::enable_if<std::is_same<T, Dqword>::value, Dqword>::type
1949 xmm(uint8_t Slot) const {
1950 return contentsOfDqword(Slot);
1951 }
1952
1953 template <typename T>
1954 typename std::enable_if<!std::is_same<T, Dqword>::value, T>::type
1955 xmm(uint8_t Slot) const {
1956 constexpr bool TIs64Bit = sizeof(T) == sizeof(uint64_t);
1957 using _64BitType = typename std::conditional<TIs64Bit, T, uint64_t>::type;
1958 using _32BitType = typename std::conditional<TIs64Bit, uint32_t, T>::type;
1959 if (TIs64Bit) {
1960 return contentsOfQword<_64BitType>(Slot);
1961 }
1962 return contentsOfDword<_32BitType>(Slot);
1963 }
1964
1965 static uint32_t dwordOffset(uint32_t Index) {
1966 return MaximumCodeSize + (Index * 4);
1967 }
1968
1969 void *ExecutableData = nullptr;
1970 size_t Size;
1971 };
1972
1973 // assemble created an AssembledTest with the jitted code. The first time
1974 // assemble is executed it will add the epilogue to the jitted code (which is
1975 // the reason why this method is not const qualified.
1976 AssembledTest assemble() {
1977 if (NeedsEpilogue) {
1978 addEpilogue();
1979 }
1980
1981 NeedsEpilogue = false;
1982 return AssembledTest(codeBytes(), codeBytesSize(), NumAllocatedDwords);
1983 }
1984
1985 // Allocates a new dword slot in the test's scratchpad area.
1986 uint32_t allocateDword() { return NumAllocatedDwords++; }
1987
1988 // Allocates a new qword slot in the test's scratchpad area.
1989 uint32_t allocateQword() {
1990 uint32_t InitialDword = allocateDword();
1991 allocateDword();
1992 return InitialDword;
1993 }
1994
1995 // Allocates a new dqword slot in the test's scratchpad area.
1996 uint32_t allocateDqword() {
1997 uint32_t InitialDword = allocateQword();
1998 allocateQword();
1999 return InitialDword;
2000 }
2001
2002 Address dwordAddress(uint32_t Dword) {
2003 return Address(Encoded_GPR_r9(), dwordDisp(Dword));
2004 }
2005
2006 private:
2007 // e??SlotAddress returns an AssemblerX8664::Traits::Address that can be used
2008 // by the test cases to encode an address operand for accessing the slot for
2009 // the specified register. These are all private for, when jitting the test
2010 // code, tests should not tamper with these values. Besides, during the test
2011 // execution these slots' contents are undefined and should not be accessed.
2012 Address raxSlotAddress() { return dwordAddress(AssembledTest::raxSlot()); }
2013 Address rbxSlotAddress() { return dwordAddress(AssembledTest::rbxSlot()); }
2014 Address rcxSlotAddress() { return dwordAddress(AssembledTest::rcxSlot()); }
2015 Address rdxSlotAddress() { return dwordAddress(AssembledTest::rdxSlot()); }
2016 Address rdiSlotAddress() { return dwordAddress(AssembledTest::rdiSlot()); }
2017 Address rsiSlotAddress() { return dwordAddress(AssembledTest::rsiSlot()); }
2018 Address rbpSlotAddress() { return dwordAddress(AssembledTest::rbpSlot()); }
2019 Address rspSlotAddress() { return dwordAddress(AssembledTest::rspSlot()); }
2020 Address r8SlotAddress() { return dwordAddress(AssembledTest::r8Slot()); }
2021 Address r9SlotAddress() { return dwordAddress(AssembledTest::r9Slot()); }
2022 Address r10SlotAddress() { return dwordAddress(AssembledTest::r10Slot()); }
2023 Address r11SlotAddress() { return dwordAddress(AssembledTest::r11Slot()); }
2024 Address r12SlotAddress() { return dwordAddress(AssembledTest::r12Slot()); }
2025 Address r13SlotAddress() { return dwordAddress(AssembledTest::r13Slot()); }
2026 Address r14SlotAddress() { return dwordAddress(AssembledTest::r14Slot()); }
2027 Address r15SlotAddress() { return dwordAddress(AssembledTest::r15Slot()); }
2028 Address xmm0SlotAddress() { return dwordAddress(AssembledTest::xmm0Slot()); }
2029 Address xmm1SlotAddress() { return dwordAddress(AssembledTest::xmm1Slot()); }
2030 Address xmm2SlotAddress() { return dwordAddress(AssembledTest::xmm2Slot()); }
2031 Address xmm3SlotAddress() { return dwordAddress(AssembledTest::xmm3Slot()); }
2032 Address xmm4SlotAddress() { return dwordAddress(AssembledTest::xmm4Slot()); }
2033 Address xmm5SlotAddress() { return dwordAddress(AssembledTest::xmm5Slot()); }
2034 Address xmm6SlotAddress() { return dwordAddress(AssembledTest::xmm6Slot()); }
2035 Address xmm7SlotAddress() { return dwordAddress(AssembledTest::xmm7Slot()); }
2036 Address xmm8SlotAddress() { return dwordAddress(AssembledTest::xmm8Slot()); }
2037 Address xmm9SlotAddress() { return dwordAddress(AssembledTest::xmm9Slot()); }
2038 Address xmm10SlotAddress() {
2039 return dwordAddress(AssembledTest::xmm10Slot());
2040 }
2041 Address xmm11SlotAddress() {
2042 return dwordAddress(AssembledTest::xmm11Slot());
2043 }
2044 Address xmm12SlotAddress() {
2045 return dwordAddress(AssembledTest::xmm12Slot());
2046 }
2047 Address xmm13SlotAddress() {
2048 return dwordAddress(AssembledTest::xmm13Slot());
2049 }
2050 Address xmm14SlotAddress() {
2051 return dwordAddress(AssembledTest::xmm14Slot());
2052 }
2053 Address xmm15SlotAddress() {
2054 return dwordAddress(AssembledTest::xmm15Slot());
2055 }
2056
2057 // Returns the displacement that should be used when accessing the specified
2058 // Dword in the scratchpad area. It needs to adjust for the initial
2059 // instructions that are emitted before the call that materializes the IP
2060 // register.
2061 uint32_t dwordDisp(uint32_t Dword) const {
2062 EXPECT_LT(Dword, NumAllocatedDwords);
2063 assert(Dword < NumAllocatedDwords);
2064 static constexpr uint8_t PushR9Bytes = 2;
2065 static constexpr uint8_t CallImmBytes = 5;
2066 return AssembledTest::MaximumCodeSize + (Dword * 4) -
2067 (PushR9Bytes + CallImmBytes);
2068 }
2069
2070 void addPrologue() {
2071 __ pushl(Encoded_GPR_r9());
2072 __ call(Immediate(4));
2073 __ popl(Encoded_GPR_r9());
2074
2075 __ pushl(Encoded_GPR_rax());
2076 __ pushl(Encoded_GPR_rbx());
2077 __ pushl(Encoded_GPR_rcx());
2078 __ pushl(Encoded_GPR_rdx());
2079 __ pushl(Encoded_GPR_rbp());
2080 __ pushl(Encoded_GPR_rdi());
2081 __ pushl(Encoded_GPR_rsi());
2082 __ pushl(Encoded_GPR_r8());
2083 __ pushl(Encoded_GPR_r10());
2084 __ pushl(Encoded_GPR_r11());
2085 __ pushl(Encoded_GPR_r12());
2086 __ pushl(Encoded_GPR_r13());
2087 __ pushl(Encoded_GPR_r14());
2088 __ pushl(Encoded_GPR_r15());
2089
2090 __ mov(IceType_i32, Encoded_GPR_rax(), Immediate(0x00));
2091 __ mov(IceType_i32, Encoded_GPR_rbx(), Immediate(0x00));
2092 __ mov(IceType_i32, Encoded_GPR_rcx(), Immediate(0x00));
2093 __ mov(IceType_i32, Encoded_GPR_rdx(), Immediate(0x00));
2094 __ mov(IceType_i32, Encoded_GPR_rbp(), Immediate(0x00));
2095 __ mov(IceType_i32, Encoded_GPR_rdi(), Immediate(0x00));
2096 __ mov(IceType_i32, Encoded_GPR_rsi(), Immediate(0x00));
2097 __ mov(IceType_i32, Encoded_GPR_r8(), Immediate(0x00));
2098 __ mov(IceType_i32, Encoded_GPR_r10(), Immediate(0x00));
2099 __ mov(IceType_i32, Encoded_GPR_r11(), Immediate(0x00));
2100 __ mov(IceType_i32, Encoded_GPR_r12(), Immediate(0x00));
2101 __ mov(IceType_i32, Encoded_GPR_r13(), Immediate(0x00));
2102 __ mov(IceType_i32, Encoded_GPR_r14(), Immediate(0x00));
2103 __ mov(IceType_i32, Encoded_GPR_r15(), Immediate(0x00));
2104 }
2105
2106 void addEpilogue() {
2107 __ mov(IceType_i64, raxSlotAddress(), Encoded_GPR_rax());
2108 __ mov(IceType_i64, rbxSlotAddress(), Encoded_GPR_rbx());
2109 __ mov(IceType_i64, rcxSlotAddress(), Encoded_GPR_rcx());
2110 __ mov(IceType_i64, rdxSlotAddress(), Encoded_GPR_rdx());
2111 __ mov(IceType_i64, rdiSlotAddress(), Encoded_GPR_rdi());
2112 __ mov(IceType_i64, rsiSlotAddress(), Encoded_GPR_rsi());
2113 __ mov(IceType_i64, rbpSlotAddress(), Encoded_GPR_rbp());
2114 __ mov(IceType_i64, rspSlotAddress(), Encoded_GPR_rsp());
2115 __ mov(IceType_i64, r8SlotAddress(), Encoded_GPR_r8());
2116 __ mov(IceType_i64, r9SlotAddress(), Encoded_GPR_r9());
2117 __ mov(IceType_i64, r10SlotAddress(), Encoded_GPR_r10());
2118 __ mov(IceType_i64, r11SlotAddress(), Encoded_GPR_r11());
2119 __ mov(IceType_i64, r12SlotAddress(), Encoded_GPR_r12());
2120 __ mov(IceType_i64, r13SlotAddress(), Encoded_GPR_r13());
2121 __ mov(IceType_i64, r14SlotAddress(), Encoded_GPR_r14());
2122 __ mov(IceType_i64, r15SlotAddress(), Encoded_GPR_r15());
2123 __ movups(xmm0SlotAddress(), Encoded_Xmm_xmm0());
2124 __ movups(xmm1SlotAddress(), Encoded_Xmm_xmm1());
2125 __ movups(xmm2SlotAddress(), Encoded_Xmm_xmm2());
2126 __ movups(xmm3SlotAddress(), Encoded_Xmm_xmm3());
2127 __ movups(xmm4SlotAddress(), Encoded_Xmm_xmm4());
2128 __ movups(xmm5SlotAddress(), Encoded_Xmm_xmm5());
2129 __ movups(xmm6SlotAddress(), Encoded_Xmm_xmm6());
2130 __ movups(xmm7SlotAddress(), Encoded_Xmm_xmm7());
2131 __ movups(xmm8SlotAddress(), Encoded_Xmm_xmm8());
2132 __ movups(xmm9SlotAddress(), Encoded_Xmm_xmm9());
2133 __ movups(xmm10SlotAddress(), Encoded_Xmm_xmm10());
2134 __ movups(xmm11SlotAddress(), Encoded_Xmm_xmm11());
2135 __ movups(xmm12SlotAddress(), Encoded_Xmm_xmm12());
2136 __ movups(xmm13SlotAddress(), Encoded_Xmm_xmm13());
2137 __ movups(xmm14SlotAddress(), Encoded_Xmm_xmm14());
2138 __ movups(xmm15SlotAddress(), Encoded_Xmm_xmm15());
2139
2140 __ popl(Encoded_GPR_r15());
2141 __ popl(Encoded_GPR_r14());
2142 __ popl(Encoded_GPR_r13());
2143 __ popl(Encoded_GPR_r12());
2144 __ popl(Encoded_GPR_r11());
2145 __ popl(Encoded_GPR_r10());
2146 __ popl(Encoded_GPR_r8());
2147 __ popl(Encoded_GPR_rsi());
2148 __ popl(Encoded_GPR_rdi());
2149 __ popl(Encoded_GPR_rbp());
2150 __ popl(Encoded_GPR_rdx());
2151 __ popl(Encoded_GPR_rcx());
2152 __ popl(Encoded_GPR_rbx());
2153 __ popl(Encoded_GPR_rax());
2154 __ popl(Encoded_GPR_r9());
2155
2156 __ ret();
2157 }
2158
2159 bool NeedsEpilogue;
2160 uint32_t NumAllocatedDwords;
2161 };
2162
2163 TEST_F(AssemblerX8664Test, ScratchpadGettersAndSetters) {
2164 const uint32_t S0 = allocateDword();
2165 const uint32_t S1 = allocateDword();
2166 const uint32_t S2 = allocateDword();
2167 const uint32_t S3 = allocateDword();
2168 AssembledTest test = assemble();
2169 test.setDwordTo(S0, 0xBEEF0000u);
2170 test.setDwordTo(S1, 0xDEADu);
2171 test.setDwordTo(S2, 0x20406080u);
2172 ASSERT_EQ(0xBEEF0000u, test.contentsOfDword(S0));
2173 ASSERT_EQ(0xDEADu, test.contentsOfDword(S1));
2174 ASSERT_EQ(0x20406080u, test.contentsOfDword(S2));
2175 ASSERT_EQ(0xDEADBEEF0000ull, test.contentsOfQword(S0));
2176 ASSERT_EQ(0x204060800000DEADull, test.contentsOfQword(S1));
2177
2178 test.setQwordTo(S1, 0x1234567890ABCDEFull);
2179 ASSERT_EQ(0x1234567890ABCDEFull, test.contentsOfQword(S1));
2180 test.setDwordTo(S0, 0xBEEF0000u);
2181 ASSERT_EQ(0x90ABCDEFull, test.contentsOfDword(S1));
2182 ASSERT_EQ(0x12345678ull, test.contentsOfDword(S2));
2183
2184 test.setDwordTo(S0, 1.0f);
2185 ASSERT_FLOAT_EQ(1.0f, test.contentsOfDword<float>(S0));
2186 test.setQwordTo(S0, 3.14);
2187 ASSERT_DOUBLE_EQ(3.14, test.contentsOfQword<double>(S0));
2188
2189 test.setDqwordTo(S0, Dqword(1.0f, 2.0f, 3.0f, 4.0f));
2190 ASSERT_EQ(Dqword(1.0f, 2.0f, 3.0f, 4.0f), test.contentsOfDqword(S0));
2191 EXPECT_FLOAT_EQ(1.0f, test.contentsOfDword<float>(S0));
2192 EXPECT_FLOAT_EQ(2.0f, test.contentsOfDword<float>(S1));
2193 EXPECT_FLOAT_EQ(3.0f, test.contentsOfDword<float>(S2));
2194 EXPECT_FLOAT_EQ(4.0f, test.contentsOfDword<float>(S3));
2195 }
2196
2197 TEST_F(AssemblerX8664Test, MovRegImm) {
2198 static constexpr uint32_t Mask8 = 0x000000FF;
2199 static constexpr uint32_t Mask16 = 0x0000FFFF;
2200 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
2201
2202 #define MovRegImm(Reg, Suffix, Size) \
2203 do { \
2204 static constexpr char TestString[] = "(" #Reg ", " #Size ")"; \
2205 static constexpr uint32_t Value = (0xABCD7645) & Mask##Size; \
2206 static constexpr uint32_t Marker = 0xBEEFFEEB; \
2207 __ mov(IceType_i32, Encoded_GPR_##Reg##q(), Immediate(Marker)); \
2208 __ mov(IceType_i##Size, Encoded_GPR_##Reg##Suffix(), Immediate(Value)); \
2209 \
2210 AssembledTest test = assemble(); \
2211 test.run(); \
2212 \
2213 ASSERT_EQ(Value, test.Reg##Suffix()) << TestString; \
2214 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.Reg##d()) << TestString; \
2215 reset(); \
2216 } while (0)
2217
2218 #define TestImpl(Reg) \
2219 do { \
2220 MovRegImm(Reg, l, 8); \
2221 MovRegImm(Reg, w, 16); \
2222 MovRegImm(Reg, d, 32); \
2223 /* MovRegImm64 not implemented */ \
2224 } while (0)
2225
2226 TestImpl(r1);
2227 TestImpl(r2);
2228 TestImpl(r3);
2229 TestImpl(r4);
2230 TestImpl(r5);
2231 TestImpl(r6);
2232 TestImpl(r7);
2233 TestImpl(r8);
2234 TestImpl(r10);
2235 TestImpl(r11);
2236 TestImpl(r12);
2237 TestImpl(r13);
2238 TestImpl(r14);
2239 TestImpl(r15);
2240
2241 #undef TestImpl
2242 #undef MovRegImm
2243 }
2244
2245 TEST_F(AssemblerX8664Test, MovMemImm) {
2246 const uint32_t T0 = allocateDword();
2247 constexpr uint32_t ExpectedT0 = 0x00111100ul;
2248 const uint32_t T1 = allocateDword();
2249 constexpr uint32_t ExpectedT1 = 0x00222200ul;
2250 const uint32_t T2 = allocateDword();
2251 constexpr uint32_t ExpectedT2 = 0x03333000ul;
2252 const uint32_t T3 = allocateDword();
2253 constexpr uint32_t ExpectedT3 = 0x00444400ul;
2254
2255 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
2256 __ mov(IceType_i16, dwordAddress(T1), Immediate(ExpectedT1));
2257 __ mov(IceType_i8, dwordAddress(T2), Immediate(ExpectedT2));
2258 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
2259
2260 AssembledTest test = assemble();
2261 test.run();
2262 EXPECT_EQ(0ul, test.eax());
2263 EXPECT_EQ(0ul, test.ebx());
2264 EXPECT_EQ(0ul, test.ecx());
2265 EXPECT_EQ(0ul, test.edx());
2266 EXPECT_EQ(0ul, test.edi());
2267 EXPECT_EQ(0ul, test.esi());
2268 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
2269 EXPECT_EQ(ExpectedT1 & 0xFFFF, test.contentsOfDword(T1));
2270 EXPECT_EQ(ExpectedT2 & 0xFF, test.contentsOfDword(T2));
2271 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
2272 }
2273
2274 TEST_F(AssemblerX8664Test, MovMemReg) {
2275 static constexpr uint64_t Mask8 = 0x00000000000000FF;
2276 static constexpr uint64_t Mask16 = 0x000000000000FFFF;
2277 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFF;
2278 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFF;
2279
2280 #define TestMemReg(Src, Size) \
2281 do { \
2282 static constexpr char TestString[] = "(" #Src ", " #Size ")"; \
2283 static constexpr uint32_t Value = 0x1a4d567e & Mask##Size; \
2284 static constexpr uint64_t Marker = 0xD0DA33EEBEEFFEEB; \
2285 const uint32_t T0 = allocateQword(); \
2286 \
2287 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \
2288 __ mov(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
2289 \
2290 AssembledTest test = assemble(); \
2291 test.setQwordTo(T0, Marker); \
2292 test.run(); \
2293 \
2294 ASSERT_EQ((Marker & ~Mask##Size) | Value, test.contentsOfQword(T0)) \
2295 << TestString; \
2296 reset(); \
2297 } while (0)
2298
2299 #define TestImpl(Src) \
2300 do { \
2301 TestMemReg(Src, 8); \
2302 TestMemReg(Src, 16); \
2303 TestMemReg(Src, 32); \
2304 TestMemReg(Src, 64); \
2305 } while (0)
2306
2307 TestImpl(r1);
2308 TestImpl(r2);
2309 TestImpl(r3);
2310 TestImpl(r4);
2311 TestImpl(r5);
2312 TestImpl(r6);
2313 TestImpl(r7);
2314 TestImpl(r8);
2315 TestImpl(r10);
2316 TestImpl(r11);
2317 TestImpl(r12);
2318 TestImpl(r13);
2319 TestImpl(r14);
2320 TestImpl(r15);
2321
2322 #undef TestImpl
2323 #undef TestMemReg
2324 }
2325
2326 TEST_F(AssemblerX8664Test, MovRegReg) {
2327 static constexpr uint64_t Mask8 = 0x00000000000000FFull;
2328 static constexpr uint64_t Mask16 = 0x000000000000FFFFull;
2329 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull;
2330 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull;
2331
2332 static constexpr uint64_t MaskResult8 = 0x00000000000000FFull;
2333 static constexpr uint64_t MaskResult16 = 0x000000000000FFFFull;
2334 static constexpr uint64_t MaskResult32 = 0xFFFFFFFFFFFFFFFFull;
2335 static constexpr uint64_t MaskResult64 = 0xFFFFFFFFFFFFFFFFull;
2336
2337 #define TestRegReg(Dst, Src, Suffix, Size) \
2338 do { \
2339 static constexpr char TestString[] = \
2340 "(" #Dst ", " #Src ", " #Suffix ", " #Size ")"; \
2341 const uint8_t T0 = allocateQword(); \
2342 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \
2343 const uint8_t T1 = allocateQword(); \
2344 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \
2345 \
2346 __ mov(IceType_i64, Encoded_GPR_##Src(), dwordAddress(T0)); \
2347 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \
2348 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
2349 \
2350 AssembledTest test = assemble(); \
2351 test.setQwordTo(T0, Value); \
2352 test.setQwordTo(T1, Marker); \
2353 test.run(); \
2354 \
2355 ASSERT_EQ((Marker & ~MaskResult##Size) | Value, test.Dst()) << TestString; \
2356 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \
2357 reset(); \
2358 } while (0)
2359
2360 #define TestImpl(Dst, Src) \
2361 do { \
2362 TestRegReg(Dst, Src, l, 8); \
2363 TestRegReg(Dst, Src, w, 16); \
2364 TestRegReg(Dst, Src, d, 32); \
2365 TestRegReg(Dst, Src, q, 64); \
2366 } while (0)
2367
2368 TestImpl(r1, r2);
2369 TestImpl(r2, r3);
2370 TestImpl(r3, r4);
2371 TestImpl(r4, r5);
2372 TestImpl(r5, r6);
2373 TestImpl(r6, r7);
2374 TestImpl(r7, r8);
2375 TestImpl(r8, r10);
2376 TestImpl(r10, r11);
2377 TestImpl(r11, r12);
2378 TestImpl(r12, r13);
2379 TestImpl(r13, r14);
2380 TestImpl(r14, r15);
2381 TestImpl(r15, r1);
2382
2383 #undef TestImpl
2384 #undef TestRegReg
2385 }
2386
2387 TEST_F(AssemblerX8664Test, MovRegMem) {
2388 static constexpr uint64_t Mask8 = 0x00000000000000FFull;
2389 static constexpr uint64_t Mask16 = 0x000000000000FFFFull;
2390 static constexpr uint64_t Mask32 = 0x00000000FFFFFFFFull;
2391 static constexpr uint64_t Mask64 = 0xFFFFFFFFFFFFFFFFull;
2392
2393 static constexpr uint64_t MaskResult8 = ~0x00000000000000FFull;
2394 static constexpr uint64_t MaskResult16 = ~0x000000000000FFFFull;
2395 static constexpr uint64_t MaskResult32 = ~0xFFFFFFFFFFFFFFFFull;
2396 static constexpr uint64_t MaskResult64 = ~0xFFFFFFFFFFFFFFFFull;
2397
2398 #define TestRegAddr(Dst, Suffix, Size) \
2399 do { \
2400 static constexpr char TestString[] = \
2401 "(" #Dst ", Addr, " #Suffix ", " #Size ")"; \
2402 const uint8_t T0 = allocateQword(); \
2403 static constexpr uint64_t Value = 0xA4DD30Af86CCE321ull & Mask##Size; \
2404 const uint8_t T1 = allocateQword(); \
2405 static constexpr uint64_t Marker = 0xC0FFEEA0BEEFFEEFull; \
2406 \
2407 __ mov(IceType_i64, Encoded_GPR_##Dst(), dwordAddress(T1)); \
2408 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
2409 \
2410 AssembledTest test = assemble(); \
2411 test.setQwordTo(T0, Value); \
2412 test.setQwordTo(T1, Marker); \
2413 test.run(); \
2414 \
2415 ASSERT_EQ((Marker & MaskResult##Size) | Value, test.Dst()) << TestString; \
2416 ASSERT_EQ(Value, test.Dst##Suffix()) << TestString; \
2417 reset(); \
2418 } while (0)
2419
2420 #define TestImpl(Dst) \
2421 do { \
2422 TestRegAddr(Dst, l, 8); \
2423 TestRegAddr(Dst, w, 16); \
2424 TestRegAddr(Dst, d, 32); \
2425 TestRegAddr(Dst, q, 64); \
2426 } while (0)
2427
2428 TestImpl(r1);
2429 TestImpl(r2);
2430 TestImpl(r3);
2431 TestImpl(r4);
2432 TestImpl(r5);
2433 TestImpl(r6);
2434 TestImpl(r7);
2435 TestImpl(r8);
2436 TestImpl(r10);
2437 TestImpl(r11);
2438 TestImpl(r12);
2439 TestImpl(r13);
2440 TestImpl(r14);
2441 TestImpl(r15);
2442
2443 #undef TestImpl
2444 #undef TestRegAddr
2445 }
2446
2447 TEST_F(AssemblerX8664Test, J) {
2448 #define TestJ(C, Near, Dest, Src0, Value0, Src1, Value1) \
2449 do { \
2450 static constexpr char TestString[] = \
2451 "(" #C ", " #Near ", " #Dest ", " #Src0 ", " #Value0 ", " #Src1 \
2452 ", " #Value1 ")"; \
2453 const bool NearJmp = AssemblerX8664::k##Near##Jump; \
2454 Label ShouldBeTaken; \
2455 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
2456 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
2457 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xBEEF)); \
2458 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
2459 __ j(Cond::Br_##C, &ShouldBeTaken, NearJmp); \
2460 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xC0FFEE)); \
2461 __ bind(&ShouldBeTaken); \
2462 AssembledTest test = assemble(); \
2463 test.run(); \
2464 ASSERT_EQ(Value0, test.Src0()) << TestString; \
2465 ASSERT_EQ(Value1, test.Src1()) << TestString; \
2466 ASSERT_EQ(0xBEEFul, test.Dest()) << TestString; \
2467 reset(); \
2468 } while (0)
2469
2470 #define TestImpl(Dst, Src0, Src1) \
2471 do { \
2472 TestJ(o, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2473 TestJ(o, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2474 TestJ(no, Near, Dst, Src0, 0x1ul, Src1, 0x1ul); \
2475 TestJ(no, Far, Dst, Src0, 0x1ul, Src1, 0x1ul); \
2476 TestJ(b, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2477 TestJ(b, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2478 TestJ(ae, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2479 TestJ(ae, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2480 TestJ(e, Near, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul); \
2481 TestJ(e, Far, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul); \
2482 TestJ(ne, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2483 TestJ(ne, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2484 TestJ(be, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2485 TestJ(be, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2486 TestJ(a, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2487 TestJ(a, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2488 TestJ(s, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2489 TestJ(s, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2490 TestJ(ns, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2491 TestJ(ns, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2492 TestJ(p, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2493 TestJ(p, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2494 TestJ(np, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2495 TestJ(np, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2496 TestJ(l, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2497 TestJ(l, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2498 TestJ(ge, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2499 TestJ(ge, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2500 TestJ(le, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2501 TestJ(le, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \
2502 TestJ(g, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2503 TestJ(g, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \
2504 } while (0)
2505
2506 TestImpl(r1, r2, r3);
2507 TestImpl(r2, r3, r4);
2508 TestImpl(r3, r4, r5);
2509 TestImpl(r4, r5, r6);
2510 TestImpl(r5, r6, r7);
2511 TestImpl(r6, r7, r8);
2512 TestImpl(r7, r8, r10);
2513 TestImpl(r8, r10, r11);
2514 TestImpl(r10, r11, r12);
2515 TestImpl(r11, r12, r13);
2516 TestImpl(r12, r13, r14);
2517 TestImpl(r13, r14, r15);
2518 TestImpl(r14, r15, r1);
2519 TestImpl(r15, r1, r2);
2520
2521 #undef TestImpl
2522 #undef TestJ
2523 }
2524
2525 TEST_F(AssemblerX8664Test, PopAddr) {
2526 const uint32_t T0 = allocateQword();
2527 constexpr uint64_t V0 = 0x3AABBEFABBBAA3ull;
2528
2529 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xC0FFEE));
2530 __ pushl(GPRRegister::Encoded_Reg_eax);
2531 __ popl(dwordAddress(T0));
2532
2533 AssembledTest test = assemble();
2534 test.setQwordTo(T0, V0);
2535
2536 test.run();
2537
2538 ASSERT_EQ(0xC0FFEEul, test.contentsOfQword(T0));
2539 }
2540
2541 TEST_F(AssemblerX8664Test, SetCC) {
2542 #define TestSetCC(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
2543 do { \
2544 static constexpr char TestString[] = \
2545 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \
2546 ", " #Value1 ")"; \
2547 const uint32_t T0 = allocateDword(); \
2548 constexpr uint32_t V0 = 0xF00F00; \
2549 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
2550 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
2551 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
2552 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0)); \
2553 __ setcc(Cond::Br_##C, RegX8664::getEncodedByteReg(Encoded_GPR_##Dest())); \
2554 __ setcc(Cond::Br_##C, dwordAddress(T0)); \
2555 \
2556 AssembledTest test = assemble(); \
2557 test.setDwordTo(T0, V0); \
2558 \
2559 test.run(); \
2560 \
2561 ASSERT_EQ(IsTrue, test.Dest()) << TestString; \
2562 ASSERT_EQ((0xF00F00 | IsTrue), test.contentsOfDword(T0)) << TestString; \
2563 reset(); \
2564 } while (0)
2565
2566 #define TestImpl(Dest, Src0, Src1) \
2567 do { \
2568 TestSetCC(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2569 TestSetCC(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \
2570 TestSetCC(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \
2571 TestSetCC(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2572 TestSetCC(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \
2573 TestSetCC(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2574 TestSetCC(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2575 TestSetCC(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2576 TestSetCC(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \
2577 TestSetCC(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \
2578 TestSetCC(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2579 TestSetCC(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \
2580 TestSetCC(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
2581 TestSetCC(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2582 TestSetCC(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2583 TestSetCC(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2584 TestSetCC(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
2585 TestSetCC(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2586 TestSetCC(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2587 TestSetCC(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2588 TestSetCC(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2589 TestSetCC(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2590 TestSetCC(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
2591 TestSetCC(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2592 TestSetCC(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2593 TestSetCC(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2594 TestSetCC(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
2595 TestSetCC(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
2596 TestSetCC(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
2597 TestSetCC(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
2598 } while (0)
2599
2600 TestImpl(r1, r2, r3);
2601 TestImpl(r2, r3, r4);
2602 TestImpl(r3, r4, r5);
2603 TestImpl(r4, r5, r6);
2604 TestImpl(r5, r6, r7);
2605 TestImpl(r6, r7, r8);
2606 TestImpl(r7, r8, r10);
2607 TestImpl(r8, r10, r11);
2608 TestImpl(r10, r11, r12);
2609 TestImpl(r11, r12, r13);
2610 TestImpl(r12, r13, r14);
2611 TestImpl(r13, r14, r15);
2612 TestImpl(r14, r15, r1);
2613 TestImpl(r15, r1, r2);
2614
2615 #undef TestImpl
2616 #undef TestSetCC
2617 }
2618
2619 TEST_F(AssemblerX8664Test, CallImm) {
2620 __ call(Immediate(16));
2621 __ hlt();
2622 __ hlt();
2623 __ hlt();
2624 __ hlt();
2625 __ hlt();
2626 __ hlt();
2627 __ hlt();
2628 __ hlt();
2629 __ hlt();
2630 __ hlt();
2631 __ hlt();
2632 __ hlt();
2633 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf00f));
2634 __ popl(GPRRegister::Encoded_Reg_ebx);
2635
2636 AssembledTest test = assemble();
2637
2638 test.run();
2639
2640 EXPECT_EQ(0xF00Fu, test.eax());
2641 }
2642
2643 TEST_F(AssemblerX8664Test, CallReg) {
2644 #define TestImpl(Dst, Src) \
2645 do { \
2646 __ call(Immediate(16)); \
2647 int CallTargetAddr = codeBytesSize() + 12; \
2648 __ popl(Encoded_GPR_##Dst()); \
2649 __ pushl(Encoded_GPR_##Dst()); \
2650 __ ret(); \
2651 for (int I = codeBytesSize(); I < CallTargetAddr; ++I) { \
2652 __ hlt(); \
2653 } \
2654 __ popl(Encoded_GPR_##Src()); \
2655 __ call(Encoded_GPR_##Src()); \
2656 \
2657 AssembledTest test = assemble(); \
2658 \
2659 test.run(); \
2660 \
2661 ASSERT_LE(15u, test.Dst() - test.Src()) << "(" #Dst ", " #Src ")"; \
2662 reset(); \
2663 } while (0)
2664
2665 TestImpl(r1, r2);
2666 TestImpl(r2, r3);
2667 TestImpl(r3, r4);
2668 TestImpl(r4, r5);
2669 TestImpl(r5, r6);
2670 TestImpl(r6, r7);
2671 TestImpl(r7, r8);
2672 TestImpl(r8, r10);
2673 TestImpl(r10, r11);
2674 TestImpl(r11, r12);
2675 TestImpl(r12, r13);
2676 TestImpl(r13, r14);
2677 TestImpl(r14, r15);
2678 TestImpl(r15, r1);
2679
2680 #undef TestImpl
2681 }
2682
2683 TEST_F(AssemblerX8664Test, CallAddr) {
2684 #define TestImpl(Dst, Src) \
2685 do { \
2686 const uint32_t T0 = allocateQword(); \
2687 const uint64_t V0 = 0xA0C0FFEEBEEFFEEFull; \
2688 __ call(Immediate(16)); \
2689 int CallTargetAddr = codeBytesSize() + 12; \
2690 __ mov(IceType_i8, Encoded_GPR_##Dst##l(), Immediate(0xf4)); \
2691 __ ret(); \
2692 for (int I = codeBytesSize(); I < CallTargetAddr; ++I) { \
2693 __ hlt(); \
2694 } \
2695 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
2696 __ mov(IceType_i64, Encoded_GPR_##Src##q(), Encoded_GPR_rsp()); \
2697 __ call(Address(Encoded_GPR_##Src##q(), 0)); \
2698 __ popl(Encoded_GPR_##Src##q()); \
2699 \
2700 AssembledTest test = assemble(); \
2701 test.setQwordTo(T0, V0); \
2702 test.run(); \
2703 \
2704 ASSERT_EQ(0xA0C0FFEEBEEFFEF4ull, test.Dst##q()) << "(" #Dst ", " #Src ")"; \
2705 reset(); \
2706 } while (0)
2707
2708 TestImpl(r1, r2);
2709 TestImpl(r2, r3);
2710 TestImpl(r3, r4);
2711 TestImpl(r4, r5);
2712 TestImpl(r5, r6);
2713 TestImpl(r6, r7);
2714 TestImpl(r7, r8);
2715 TestImpl(r8, r10);
2716 TestImpl(r10, r11);
2717 TestImpl(r11, r12);
2718 TestImpl(r12, r13);
2719 TestImpl(r13, r14);
2720 TestImpl(r14, r15);
2721 TestImpl(r15, r1);
2722
2723 #undef TestImpl
2724 }
2725
2726 TEST_F(AssemblerX8664Test, Movzx) {
2727 static constexpr uint32_t Mask8 = 0x000000FF;
2728 static constexpr uint32_t Mask16 = 0x0000FFFF;
2729
2730 #define TestImplRegReg(Dst, Src, Suffix, Size) \
2731 do { \
2732 const uint32_t T0 = allocateDqword(); \
2733 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
2734 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \
2735 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
2736 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \
2737 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), \
2738 Encoded_GPR_##Src##Suffix()); \
2739 AssembledTest test = assemble(); \
2740 test.setQwordTo(T0, V0); \
2741 test.run(); \
2742 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")"; \
2743 reset(); \
2744 } while (0)
2745
2746 #define TestImplRegAddr(Dst, Suffix, Size) \
2747 do { \
2748 const uint32_t T0 = allocateDqword(); \
2749 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
2750 static constexpr uint32_t Value = (0xBEEF) & Mask##Size; \
2751 __ movzx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \
2752 \
2753 AssembledTest test = assemble(); \
2754 test.setQwordTo(T0, (V0 & ~Mask##Size) | Value); \
2755 test.run(); \
2756 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")"; \
2757 reset(); \
2758 } while (0)
2759
2760 #define TestImpl(Dst, Src) \
2761 do { \
2762 TestImplRegReg(Dst, Src, l, 8); \
2763 TestImplRegAddr(Dst, l, 8); \
2764 TestImplRegReg(Dst, Src, w, 16); \
2765 TestImplRegAddr(Dst, w, 16); \
2766 } while (0)
2767
2768 TestImpl(r1, r2);
2769 TestImpl(r2, r3);
2770 TestImpl(r3, r4);
2771 TestImpl(r4, r5);
2772 TestImpl(r5, r6);
2773 TestImpl(r6, r7);
2774 TestImpl(r7, r8);
2775 TestImpl(r8, r10);
2776 TestImpl(r10, r11);
2777 TestImpl(r11, r12);
2778 TestImpl(r12, r13);
2779 TestImpl(r13, r14);
2780 TestImpl(r14, r15);
2781 TestImpl(r15, r1);
2782
2783 #undef TestImpl
2784 #undef TestImplRegAddr
2785 #undef TestImplRegReg
2786 }
2787
2788 TEST_F(AssemblerX8664Test, Movsx) {
2789 static constexpr uint32_t Mask8 = 0x000000FF;
2790 static constexpr uint32_t Mask16 = 0x0000FFFF;
2791
2792 #define TestImplRegReg(Dst, Src, Suffix, Size) \
2793 do { \
2794 const uint32_t T0 = allocateDqword(); \
2795 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
2796 static constexpr uint32_t Value = \
2797 (uint32_t(-1) & ~Mask##Size) | (0xBEEF) & Mask##Size; \
2798 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
2799 __ mov(IceType_i##Size, Encoded_GPR_##Src##Suffix(), Immediate(Value)); \
2800 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), \
2801 Encoded_GPR_##Src##Suffix()); \
2802 AssembledTest test = assemble(); \
2803 test.setQwordTo(T0, V0); \
2804 test.run(); \
2805 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", " #Src ", " #Size ")"; \
2806 reset(); \
2807 } while (0)
2808
2809 #define TestImplRegAddr(Dst, Suffix, Size) \
2810 do { \
2811 const uint32_t T0 = allocateDqword(); \
2812 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
2813 static constexpr uint32_t Value = \
2814 (uint32_t(-1) & ~Mask##Size) | (0xBEEF) & Mask##Size; \
2815 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \
2816 \
2817 AssembledTest test = assemble(); \
2818 test.setQwordTo(T0, (V0 & ~Mask##Size) | Value); \
2819 test.run(); \
2820 ASSERT_EQ(Value, test.Dst##q()) << "(" #Dst ", Addr, " #Size ")"; \
2821 reset(); \
2822 } while (0)
2823
2824 #define TestImpl(Dst, Src) \
2825 do { \
2826 TestImplRegReg(Dst, Src, l, 8); \
2827 TestImplRegAddr(Dst, l, 8); \
2828 TestImplRegReg(Dst, Src, w, 16); \
2829 TestImplRegAddr(Dst, w, 16); \
2830 } while (0)
2831
2832 TestImpl(r1, r2);
2833 TestImpl(r2, r3);
2834 TestImpl(r3, r4);
2835 TestImpl(r4, r5);
2836 TestImpl(r5, r6);
2837 TestImpl(r6, r7);
2838 TestImpl(r7, r8);
2839 TestImpl(r8, r10);
2840 TestImpl(r10, r11);
2841 TestImpl(r11, r12);
2842 TestImpl(r12, r13);
2843 TestImpl(r13, r14);
2844 TestImpl(r14, r15);
2845 TestImpl(r15, r1);
2846
2847 #undef TestImpl
2848 #undef TestImplRegAddr
2849 #undef TestImplRegReg
2850 }
2851
2852 TEST_F(AssemblerX8664Test, Lea) {
2853 #define TestLeaBaseDisp(Base, BaseValue, Disp, Dst) \
2854 do { \
2855 static constexpr char TestString[] = \
2856 "(" #Base ", " #BaseValue ", " #Dst ")"; \
2857 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
2858 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
2859 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
2860 } \
2861 __ lea(IceType_i32, Encoded_GPR_##Dst(), \
2862 Address(Encoded_GPR_##Base(), Disp)); \
2863 AssembledTest test = assemble(); \
2864 test.run(); \
2865 ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d()) \
2866 << TestString << " with Disp " << Disp; \
2867 reset(); \
2868 } while (0)
2869
2870 #define TestLeaIndex32bitDisp(Index, IndexValue, Disp, Dst0, Dst1, Dst2, Dst3) \
2871 do { \
2872 static constexpr char TestString[] = \
2873 "(" #Index ", " #IndexValue ", " #Dst0 ", " #Dst1 ", " #Dst2 \
2874 ", " #Dst3 ")"; \
2875 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
2876 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
2877 } \
2878 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
2879 Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp)); \
2880 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
2881 Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp)); \
2882 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
2883 Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp)); \
2884 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
2885 Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp)); \
2886 AssembledTest test = assemble(); \
2887 test.run(); \
2888 ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d()) \
2889 << TestString << " " << Disp; \
2890 ASSERT_EQ((test.Index##d() << Traits::TIMES_2) + (Disp), test.Dst1##d()) \
2891 << TestString << " " << Disp; \
2892 ASSERT_EQ((test.Index##d() << Traits::TIMES_4) + (Disp), test.Dst2##d()) \
2893 << TestString << " " << Disp; \
2894 ASSERT_EQ((test.Index##d() << Traits::TIMES_8) + (Disp), test.Dst3##d()) \
2895 << TestString << " " << Disp; \
2896 reset(); \
2897 } while (0)
2898
2899 #define TestLeaBaseIndexDisp(Base, BaseValue, Index, IndexValue, Disp, Dst0, \
2900 Dst1, Dst2, Dst3) \
2901 do { \
2902 static constexpr char TestString[] = \
2903 "(" #Base ", " #BaseValue ", " #Index ", " #IndexValue ", " #Dst0 \
2904 ", " #Dst1 ", " #Dst2 ", " #Dst3 ")"; \
2905 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
2906 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
2907 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
2908 } \
2909 \
2910 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
2911 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
2912 } \
2913 \
2914 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
2915 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2916 Traits::TIMES_1, Disp)); \
2917 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
2918 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2919 Traits::TIMES_2, Disp)); \
2920 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
2921 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2922 Traits::TIMES_4, Disp)); \
2923 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
2924 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2925 Traits::TIMES_8, Disp)); \
2926 AssembledTest test = assemble(); \
2927 test.run(); \
2928 uint32_t ExpectedIndexValue = test.Index(); \
2929 if (Encoded_GPR_##Index() == Encoded_GPR_esp()) { \
2930 ExpectedIndexValue = 0; \
2931 } \
2932 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_1) + \
2933 (Disp), \
2934 test.Dst0##d()) \
2935 << TestString << " " << Disp; \
2936 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_2) + \
2937 (Disp), \
2938 test.Dst1##d()) \
2939 << TestString << " " << Disp; \
2940 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_4) + \
2941 (Disp), \
2942 test.Dst2##d()) \
2943 << TestString << " " << Disp; \
2944 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_8) + \
2945 (Disp), \
2946 test.Dst3##d()) \
2947 << TestString << " " << Disp; \
2948 reset(); \
2949 } while (0)
2950
2951 for (const int32_t Disp :
2952 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2953 TestLeaBaseDisp(r0, 0x22080Fu, Disp, r1);
2954 TestLeaBaseDisp(r1, 0x10000Fu, Disp, r2);
2955 TestLeaBaseDisp(r2, 0x20000Fu, Disp, r3);
2956 TestLeaBaseDisp(r3, 0x30000Fu, Disp, r4);
2957 TestLeaBaseDisp(r4, 0x40000Fu, Disp, r5);
2958 TestLeaBaseDisp(r5, 0x50000Fu, Disp, r6);
2959 TestLeaBaseDisp(r6, 0x60000Fu, Disp, r7);
2960 TestLeaBaseDisp(r7, 0x11000Fu, Disp, r8);
2961 TestLeaBaseDisp(r8, 0x11200Fu, Disp, r10);
2962 TestLeaBaseDisp(r9, 0x000000u, Disp, r10);
2963 TestLeaBaseDisp(r10, 0x22000Fu, Disp, r11);
2964 TestLeaBaseDisp(r11, 0x22030Fu, Disp, r12);
2965 TestLeaBaseDisp(r12, 0x22040Fu, Disp, r13);
2966 TestLeaBaseDisp(r13, 0x22050Fu, Disp, r14);
2967 TestLeaBaseDisp(r14, 0x22060Fu, Disp, r15);
2968 TestLeaBaseDisp(r15, 0x22070Fu, Disp, r1);
2969 }
2970
2971 // esp is not a valid index register.
2972 // ebp is not valid in this addressing mode (rm = 0).
2973 for (const int32_t Disp :
2974 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2975 TestLeaIndex32bitDisp(r1, 0x2000u, Disp, r2, r3, r4, r6);
2976 TestLeaIndex32bitDisp(r2, 0x4010u, Disp, r3, r4, r6, r7);
2977 TestLeaIndex32bitDisp(r3, 0x6020u, Disp, r4, r6, r7, r5);
2978 TestLeaIndex32bitDisp(r4, 0x8030u, Disp, r6, r7, r5, r10);
2979 TestLeaIndex32bitDisp(r6, 0xA040u, Disp, r7, r5, r10, r1);
2980 TestLeaIndex32bitDisp(r7, 0xC050u, Disp, r5, r10, r1, r11);
2981 TestLeaIndex32bitDisp(r8, 0xC060u, Disp, r10, r1, r11, r12);
2982 TestLeaIndex32bitDisp(r9, 0x0000u, Disp, r1, r11, r12, r13);
2983 TestLeaIndex32bitDisp(r10, 0xC008u, Disp, r11, r12, r13, r14);
2984 TestLeaIndex32bitDisp(r11, 0xC009u, Disp, r12, r13, r14, r15);
2985 TestLeaIndex32bitDisp(r12, 0xC00Au, Disp, r13, r14, r15, r1);
2986 TestLeaIndex32bitDisp(r13, 0xC00Bu, Disp, r14, r15, r1, r2);
2987 TestLeaIndex32bitDisp(r14, 0xC00Cu, Disp, r15, r1, r2, r3);
2988 TestLeaIndex32bitDisp(r15, 0xC00Du, Disp, r1, r2, r3, r4);
2989 }
2990
2991 for (const int32_t Disp :
2992 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2993 TestLeaBaseIndexDisp(r1, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
2994 TestLeaBaseIndexDisp(r2, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
2995 TestLeaBaseIndexDisp(r3, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r5);
2996 TestLeaBaseIndexDisp(r4, 0x400000u, r6, 0x300u, Disp, r7, r8, r5, r10);
2997 TestLeaBaseIndexDisp(r6, 0x500000u, r7, 0x200u, Disp, r8, r5, r10, r11);
2998 TestLeaBaseIndexDisp(r7, 0x600000u, r8, 0x100u, Disp, r5, r10, r11, r12);
2999 TestLeaBaseIndexDisp(r8, 0x600000u, r9, 0x1A0u, Disp, r10, r11, r12, r13);
3000 TestLeaBaseIndexDisp(r9, 0x000000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3001 TestLeaBaseIndexDisp(r10, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3002 TestLeaBaseIndexDisp(r11, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3003 TestLeaBaseIndexDisp(r12, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3004 TestLeaBaseIndexDisp(r13, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3005 TestLeaBaseIndexDisp(r14, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
3006 TestLeaBaseIndexDisp(r15, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3007
3008 TestLeaBaseIndexDisp(r0, 0, r2, 0x600u, Disp, r3, r4, r6, r7);
3009 TestLeaBaseIndexDisp(r0, 0, r3, 0x500u, Disp, r4, r6, r7, r8);
3010 TestLeaBaseIndexDisp(r0, 0, r4, 0x400u, Disp, r6, r7, r8, r5);
3011 TestLeaBaseIndexDisp(r0, 0, r6, 0x300u, Disp, r7, r8, r5, r10);
3012 TestLeaBaseIndexDisp(r0, 0, r7, 0x200u, Disp, r8, r5, r10, r11);
3013 TestLeaBaseIndexDisp(r0, 0, r8, 0x100u, Disp, r5, r10, r11, r12);
3014 TestLeaBaseIndexDisp(r0, 0, r9, 0x000u, Disp, r10, r11, r12, r13);
3015 TestLeaBaseIndexDisp(r0, 0, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3016 TestLeaBaseIndexDisp(r0, 0, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3017 TestLeaBaseIndexDisp(r0, 0, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3018 TestLeaBaseIndexDisp(r0, 0, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3019 TestLeaBaseIndexDisp(r0, 0, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3020 TestLeaBaseIndexDisp(r0, 0, r15, 0x10Au, Disp, r1, r2, r3, r4);
3021 TestLeaBaseIndexDisp(r0, 0, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3022
3023 TestLeaBaseIndexDisp(r5, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
3024 TestLeaBaseIndexDisp(r5, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
3025 TestLeaBaseIndexDisp(r5, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r1);
3026 TestLeaBaseIndexDisp(r5, 0x400000u, r6, 0x300u, Disp, r7, r8, r1, r10);
3027 TestLeaBaseIndexDisp(r5, 0x500000u, r7, 0x200u, Disp, r8, r1, r10, r11);
3028 TestLeaBaseIndexDisp(r5, 0x600000u, r8, 0x100u, Disp, r1, r10, r11, r12);
3029 TestLeaBaseIndexDisp(r5, 0x600000u, r9, 0x000u, Disp, r10, r11, r12, r13);
3030 TestLeaBaseIndexDisp(r5, 0x601000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3031 TestLeaBaseIndexDisp(r5, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3032 TestLeaBaseIndexDisp(r5, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3033 TestLeaBaseIndexDisp(r5, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3034 TestLeaBaseIndexDisp(r5, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3035 TestLeaBaseIndexDisp(r5, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
3036 TestLeaBaseIndexDisp(r5, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3037
3038 TestLeaBaseIndexDisp(r2, 0x100000u, r5, 0x600u, Disp, r3, r4, r6, r7);
3039 TestLeaBaseIndexDisp(r3, 0x200000u, r5, 0x500u, Disp, r4, r6, r7, r8);
3040 TestLeaBaseIndexDisp(r4, 0x300000u, r5, 0x400u, Disp, r6, r7, r8, r1);
3041 TestLeaBaseIndexDisp(r6, 0x400000u, r5, 0x300u, Disp, r7, r8, r1, r10);
3042 TestLeaBaseIndexDisp(r7, 0x500000u, r5, 0x200u, Disp, r8, r1, r10, r11);
3043 TestLeaBaseIndexDisp(r8, 0x600000u, r5, 0x100u, Disp, r1, r10, r11, r12);
3044 TestLeaBaseIndexDisp(r9, 0x000000u, r5, 0x1A0u, Disp, r10, r11, r12, r13);
3045 TestLeaBaseIndexDisp(r10, 0x601000u, r5, 0x1B0u, Disp, r11, r12, r13, r14);
3046 TestLeaBaseIndexDisp(r11, 0x602000u, r5, 0x1C0u, Disp, r12, r13, r14, r15);
3047 TestLeaBaseIndexDisp(r12, 0x603000u, r5, 0x1D0u, Disp, r13, r14, r15, r1);
3048 TestLeaBaseIndexDisp(r13, 0x604000u, r5, 0x1E0u, Disp, r14, r15, r1, r2);
3049 TestLeaBaseIndexDisp(r14, 0x605000u, r5, 0x1F0u, Disp, r15, r1, r2, r3);
3050 TestLeaBaseIndexDisp(r15, 0x606000u, r5, 0x10Au, Disp, r1, r2, r3, r4);
3051 TestLeaBaseIndexDisp(r1, 0x607000u, r5, 0x10Bu, Disp, r2, r3, r4, r6);
3052
3053 TestLeaBaseIndexDisp(r0, 0, r5, 0xC0BEBEEF, Disp, r2, r3, r4, r6);
3054 }
3055
3056 // Absolute addressing mode is tested in the Low Level tests. The encoding used
3057 // by the assembler has different meanings in x86-32 and x86-64.
3058 #undef TestLeaBaseIndexDisp
3059 #undef TestLeaScaled32bitDisp
3060 #undef TestLeaBaseDisp
3061 }
3062
3063 TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
3064 #define TestLeaAbsolute(Dst, Value) \
3065 do { \
3066 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
3067 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
3068 Address(Address::ABSOLUTE, Value)); \
3069 static constexpr uint32_t ByteCount = 6; \
3070 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
3071 static constexpr uint8_t Opcode = 0x8D; \
3072 static constexpr uint8_t ModRM = \
3073 /*mod=*/0x00 | /*reg*/ (GPRRegister::Encoded_Reg_##Dst << 3) | \
3074 /*rm*/ GPRRegister::Encoded_Reg_ebp; \
3075 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, (Value)&0xFF, \
3076 (Value >> 8) & 0xFF, (Value >> 16) & 0xFF, \
3077 (Value >> 24) & 0xFF); \
3078 reset(); \
3079 } while (0)
3080
3081 TestLeaAbsolute(eax, 0x11BEEF22);
3082 TestLeaAbsolute(ebx, 0x33BEEF44);
3083 TestLeaAbsolute(ecx, 0x55BEEF66);
3084 TestLeaAbsolute(edx, 0x77BEEF88);
3085 TestLeaAbsolute(esi, 0x99BEEFAA);
3086 TestLeaAbsolute(edi, 0xBBBEEFBB);
3087
3088 #undef TesLeaAbsolute
3089 }
3090
3091 TEST_F(AssemblerX8664Test, Cmov) {
3092 #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
3093 do { \
3094 static constexpr char TestString[] = \
3095 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \
3096 ", " #Value1 ")"; \
3097 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
3098 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
3099 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
3100 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
3101 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
3102 Encoded_GPR_##Src1()); \
3103 \
3104 AssembledTest test = assemble(); \
3105 test.run(); \
3106 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
3107 \
3108 reset(); \
3109 } while (0)
3110
3111 #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1) \
3112 do { \
3113 static constexpr char TestString[] = \
3114 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 \
3115 ", Addr, " #Value1 ")"; \
3116 const uint32_t T0 = allocateDword(); \
3117 const uint32_t V0 = Value1; \
3118 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
3119 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
3120 __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0)); \
3121 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
3122 dwordAddress(T0)); \
3123 \
3124 AssembledTest test = assemble(); \
3125 test.setDwordTo(T0, V0); \
3126 test.run(); \
3127 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
3128 \
3129 reset(); \
3130 } while (0)
3131
3132 #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
3133 do { \
3134 TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1); \
3135 TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1); \
3136 } while (0)
3137
3138 #define TestImpl(Dest, Src0, Src1) \
3139 do { \
3140 TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3141 TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \
3142 TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \
3143 TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3144 TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \
3145 TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3146 TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3147 TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3148 TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \
3149 TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \
3150 TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3151 TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \
3152 TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3153 TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3154 TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3155 TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3156 TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3157 TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3158 TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3159 TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3160 TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3161 TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3162 TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3163 TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3164 TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3165 TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3166 TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3167 TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3168 TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3169 TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3170 } while (0)
3171
3172 TestImpl(r1, r2, r3);
3173
3174 #undef TestImpl
3175 #undef TestValue
3176 #undef TestRegAddr
3177 #undef TestRegReg
3178 }
3179
3180 TEST_F(AssemblerX8664LowLevelTest, RepMovsb) {
3181 __ rep_movsb();
3182
3183 static constexpr uint32_t ByteCount = 2;
3184 static constexpr uint8_t Prefix = 0xF3;
3185 static constexpr uint8_t Opcode = 0xA4;
3186
3187 ASSERT_EQ(ByteCount, codeBytesSize());
3188 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode);
3189 }
3190
3191 TEST_F(AssemblerX8664Test, MovssXmmAddr) {
3192 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \
3193 do { \
3194 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3195 "Invalid fp length #FloatLength"); \
3196 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3197 \
3198 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
3199 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3200 const uint32_t T0 = allocateQword(); \
3201 const Type V0 = Value; \
3202 \
3203 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
3204 \
3205 AssembledTest test = assemble(); \
3206 if (IsDouble) { \
3207 test.setQwordTo(T0, static_cast<double>(V0)); \
3208 } else { \
3209 test.setDwordTo(T0, static_cast<float>(V0)); \
3210 } \
3211 test.run(); \
3212 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
3213 << Value; \
3214 reset(); \
3215 } while (0)
3216
3217 #define TestMovssXmmAddr(FloatLength) \
3218 do { \
3219 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3220 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3221 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \
3222 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \
3223 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \
3224 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \
3225 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \
3226 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \
3227 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \
3228 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \
3229 TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value); \
3230 TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value); \
3231 TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value); \
3232 TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value); \
3233 TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value); \
3234 TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value); \
3235 TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value); \
3236 TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value); \
3237 } \
3238 } while (0)
3239
3240 TestMovssXmmAddr(32);
3241 TestMovssXmmAddr(64);
3242
3243 #undef TestMovssXmmAddr
3244 #undef TestMovssXmmAddrType
3245 }
3246
3247 TEST_F(AssemblerX8664Test, MovssAddrXmm) {
3248 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \
3249 do { \
3250 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3251 "Invalid fp length #FloatLength"); \
3252 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3253 \
3254 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
3255 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3256 const uint32_t T0 = allocateQword(); \
3257 const Type V0 = Value; \
3258 const uint32_t T1 = allocateQword(); \
3259 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
3260 "f" #FloatLength " does not have quiet nan."); \
3261 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
3262 \
3263 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
3264 \
3265 AssembledTest test = assemble(); \
3266 if (IsDouble) { \
3267 test.setQwordTo(T0, static_cast<double>(V0)); \
3268 test.setQwordTo(T1, static_cast<double>(V1)); \
3269 } else { \
3270 test.setDwordTo(T0, static_cast<float>(V0)); \
3271 test.setDwordTo(T1, static_cast<float>(V1)); \
3272 } \
3273 test.run(); \
3274 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
3275 << Value; \
3276 reset(); \
3277 } while (0)
3278
3279 #define TestMovssAddrXmm(FloatLength) \
3280 do { \
3281 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3282 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3283 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \
3284 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \
3285 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \
3286 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \
3287 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \
3288 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \
3289 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \
3290 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \
3291 TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value); \
3292 TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value); \
3293 TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value); \
3294 TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value); \
3295 TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value); \
3296 TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value); \
3297 TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value); \
3298 TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value); \
3299 } \
3300 } while (0)
3301
3302 TestMovssAddrXmm(32);
3303 TestMovssAddrXmm(64);
3304
3305 #undef TestMovssAddrXmm
3306 #undef TestMovssAddrXmmType
3307 }
3308
3309 TEST_F(AssemblerX8664Test, MovssXmmXmm) {
3310 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \
3311 do { \
3312 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3313 "Invalid fp length #FloatLength"); \
3314 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3315 \
3316 static constexpr char TestString[] = \
3317 "(" #FloatLength ", " #Src ", " #Dst ")"; \
3318 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3319 const uint32_t T0 = allocateQword(); \
3320 const Type V0 = Value; \
3321 const uint32_t T1 = allocateQword(); \
3322 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
3323 "f" #FloatLength " does not have quiet nan."); \
3324 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
3325 \
3326 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3327 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3328 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), \
3329 Encoded_Xmm_##Src()); \
3330 \
3331 AssembledTest test = assemble(); \
3332 if (IsDouble) { \
3333 test.setQwordTo(T0, static_cast<double>(V0)); \
3334 test.setQwordTo(T1, static_cast<double>(V1)); \
3335 } else { \
3336 test.setDwordTo(T0, static_cast<float>(V0)); \
3337 test.setDwordTo(T1, static_cast<float>(V1)); \
3338 } \
3339 test.run(); \
3340 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \
3341 << Value; \
3342 reset(); \
3343 } while (0)
3344
3345 #define TestMovssXmmXmm(FloatLength) \
3346 do { \
3347 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3348 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3349 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \
3350 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \
3351 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \
3352 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \
3353 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \
3354 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \
3355 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \
3356 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value); \
3357 TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value); \
3358 TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value); \
3359 TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value); \
3360 TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value); \
3361 TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value); \
3362 TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value); \
3363 TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value); \
3364 TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value); \
3365 } \
3366 } while (0)
3367
3368 TestMovssXmmXmm(32);
3369 TestMovssXmmXmm(64);
3370
3371 #undef TestMovssXmmXmm
3372 #undef TestMovssXmmXmmType
3373 }
3374
3375 TEST_F(AssemblerX8664Test, MovdToXmm) {
3376 #define TestMovdXmmReg(Src, Dst, Value) \
3377 do { \
3378 assert(((Value)&0xFFFFFFFF) == (Value)); \
3379 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3380 const uint32_t T0 = allocateQword(); \
3381 const uint64_t V0 = 0xFFFFFFFF00000000ull; \
3382 \
3383 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \
3384 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3385 __ movd(Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \
3386 \
3387 AssembledTest test = assemble(); \
3388 \
3389 test.setQwordTo(T0, V0); \
3390 test.run(); \
3391 \
3392 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3393 << Value; \
3394 reset(); \
3395 } while (0)
3396
3397 #define TestMovdXmmAddr(Dst, Value) \
3398 do { \
3399 assert(((Value)&0xFFFFFFFF) == (Value)); \
3400 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3401 const uint32_t T0 = allocateQword(); \
3402 const uint32_t V0 = Value; \
3403 const uint32_t T1 = allocateQword(); \
3404 const uint64_t V1 = 0xFFFFFFFF00000000ull; \
3405 \
3406 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3407 __ movd(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3408 \
3409 AssembledTest test = assemble(); \
3410 \
3411 test.setDwordTo(T0, V0); \
3412 test.setQwordTo(T1, V1); \
3413 test.run(); \
3414 \
3415 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3416 << Value; \
3417 reset(); \
3418 } while (0)
3419
3420 #define TestMovd(Dst) \
3421 do { \
3422 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
3423 TestMovdXmmReg(r1, Dst, Value); \
3424 TestMovdXmmReg(r2, Dst, Value); \
3425 TestMovdXmmReg(r3, Dst, Value); \
3426 TestMovdXmmReg(r4, Dst, Value); \
3427 TestMovdXmmReg(r5, Dst, Value); \
3428 TestMovdXmmReg(r6, Dst, Value); \
3429 TestMovdXmmReg(r7, Dst, Value); \
3430 TestMovdXmmReg(r8, Dst, Value); \
3431 TestMovdXmmReg(r10, Dst, Value); \
3432 TestMovdXmmReg(r11, Dst, Value); \
3433 TestMovdXmmReg(r12, Dst, Value); \
3434 TestMovdXmmReg(r13, Dst, Value); \
3435 TestMovdXmmReg(r14, Dst, Value); \
3436 TestMovdXmmReg(r15, Dst, Value); \
3437 TestMovdXmmAddr(Dst, Value); \
3438 } \
3439 } while (0)
3440
3441 TestMovd(xmm0);
3442 TestMovd(xmm1);
3443 TestMovd(xmm2);
3444 TestMovd(xmm3);
3445 TestMovd(xmm4);
3446 TestMovd(xmm5);
3447 TestMovd(xmm6);
3448 TestMovd(xmm7);
3449 TestMovd(xmm8);
3450 TestMovd(xmm9);
3451 TestMovd(xmm10);
3452 TestMovd(xmm11);
3453 TestMovd(xmm12);
3454 TestMovd(xmm13);
3455 TestMovd(xmm14);
3456 TestMovd(xmm15);
3457
3458 #undef TestMovdXmmAddr
3459 #undef TestMovdXmmReg
3460 #undef TestMovd
3461 }
3462
3463 TEST_F(AssemblerX8664Test, MovdFromXmm) {
3464 #define TestMovdRegXmm(Src, Dst, Value) \
3465 do { \
3466 assert(((Value)&0xFFFFFFFF) == (Value)); \
3467 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3468 const uint32_t T0 = allocateDword(); \
3469 const uint32_t V0 = Value; \
3470 \
3471 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3472 __ movd(Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \
3473 \
3474 AssembledTest test = assemble(); \
3475 \
3476 test.setDwordTo(T0, V0); \
3477 test.run(); \
3478 \
3479 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \
3480 << Value; \
3481 reset(); \
3482 } while (0)
3483
3484 #define TestMovdAddrXmm(Src, Value) \
3485 do { \
3486 assert(((Value)&0xFFFFFFFF) == (Value)); \
3487 static constexpr char TestString[] = "(" #Src ", Addr)"; \
3488 const uint32_t T0 = allocateDword(); \
3489 const uint32_t V0 = Value; \
3490 const uint32_t T1 = allocateDword(); \
3491 const uint32_t V1 = ~(Value); \
3492 \
3493 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3494 __ movd(dwordAddress(T1), Encoded_Xmm_##Src()); \
3495 \
3496 AssembledTest test = assemble(); \
3497 \
3498 test.setDwordTo(T0, V0); \
3499 test.setDwordTo(T1, V1); \
3500 test.run(); \
3501 \
3502 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \
3503 << Value; \
3504 reset(); \
3505 } while (0)
3506
3507 #define TestMovd(Src) \
3508 do { \
3509 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
3510 TestMovdRegXmm(Src, r1, Value); \
3511 TestMovdRegXmm(Src, r2, Value); \
3512 TestMovdRegXmm(Src, r3, Value); \
3513 TestMovdRegXmm(Src, r4, Value); \
3514 TestMovdRegXmm(Src, r5, Value); \
3515 TestMovdRegXmm(Src, r6, Value); \
3516 TestMovdRegXmm(Src, r7, Value); \
3517 TestMovdRegXmm(Src, r8, Value); \
3518 TestMovdRegXmm(Src, r10, Value); \
3519 TestMovdRegXmm(Src, r11, Value); \
3520 TestMovdRegXmm(Src, r12, Value); \
3521 TestMovdRegXmm(Src, r13, Value); \
3522 TestMovdRegXmm(Src, r14, Value); \
3523 TestMovdRegXmm(Src, r15, Value); \
3524 TestMovdAddrXmm(Src, Value); \
3525 } \
3526 } while (0)
3527
3528 TestMovd(xmm0);
3529 TestMovd(xmm1);
3530 TestMovd(xmm2);
3531 TestMovd(xmm3);
3532 TestMovd(xmm4);
3533 TestMovd(xmm5);
3534 TestMovd(xmm6);
3535 TestMovd(xmm7);
3536 TestMovd(xmm8);
3537 TestMovd(xmm9);
3538 TestMovd(xmm10);
3539 TestMovd(xmm11);
3540 TestMovd(xmm12);
3541 TestMovd(xmm13);
3542 TestMovd(xmm14);
3543 TestMovd(xmm15);
3544
3545 #undef TestMovdAddrXmm
3546 #undef TestMovdRegXmm
3547 #undef TestMovd
3548 }
3549
3550 TEST_F(AssemblerX8664Test, MovqXmmAddr) {
3551 #define TestMovd(Dst, Value) \
3552 do { \
3553 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3554 const uint32_t T0 = allocateQword(); \
3555 const uint64_t V0 = Value; \
3556 const uint32_t T1 = allocateQword(); \
3557 const uint64_t V1 = ~(Value); \
3558 \
3559 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3560 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3561 \
3562 AssembledTest test = assemble(); \
3563 \
3564 test.setQwordTo(T0, V0); \
3565 test.setQwordTo(T1, V1); \
3566 test.run(); \
3567 \
3568 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3569 << Value; \
3570 reset(); \
3571 } while (0)
3572
3573 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3574 TestMovd(xmm0, Value);
3575 TestMovd(xmm1, Value);
3576 TestMovd(xmm2, Value);
3577 TestMovd(xmm3, Value);
3578 TestMovd(xmm4, Value);
3579 TestMovd(xmm5, Value);
3580 TestMovd(xmm6, Value);
3581 TestMovd(xmm7, Value);
3582 TestMovd(xmm8, Value);
3583 TestMovd(xmm9, Value);
3584 TestMovd(xmm10, Value);
3585 TestMovd(xmm11, Value);
3586 TestMovd(xmm12, Value);
3587 TestMovd(xmm13, Value);
3588 TestMovd(xmm14, Value);
3589 TestMovd(xmm15, Value);
3590 }
3591
3592 #undef TestMovd
3593 }
3594
3595 TEST_F(AssemblerX8664Test, MovqAddrXmm) {
3596 #define TestMovd(Dst, Value) \
3597 do { \
3598 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3599 const uint32_t T0 = allocateQword(); \
3600 const uint64_t V0 = Value; \
3601 const uint32_t T1 = allocateQword(); \
3602 const uint64_t V1 = ~(Value); \
3603 \
3604 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3605 __ movq(dwordAddress(T1), Encoded_Xmm_##Dst()); \
3606 \
3607 AssembledTest test = assemble(); \
3608 \
3609 test.setQwordTo(T0, V0); \
3610 test.setQwordTo(T1, V1); \
3611 test.run(); \
3612 \
3613 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3614 << Value; \
3615 reset(); \
3616 } while (0)
3617
3618 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3619 TestMovd(xmm0, Value);
3620 TestMovd(xmm1, Value);
3621 TestMovd(xmm2, Value);
3622 TestMovd(xmm3, Value);
3623 TestMovd(xmm4, Value);
3624 TestMovd(xmm5, Value);
3625 TestMovd(xmm6, Value);
3626 TestMovd(xmm7, Value);
3627 TestMovd(xmm8, Value);
3628 TestMovd(xmm9, Value);
3629 TestMovd(xmm10, Value);
3630 TestMovd(xmm11, Value);
3631 TestMovd(xmm12, Value);
3632 TestMovd(xmm13, Value);
3633 TestMovd(xmm14, Value);
3634 TestMovd(xmm15, Value);
3635 }
3636
3637 #undef TestMovd
3638 }
3639
3640 TEST_F(AssemblerX8664Test, MovqXmmXmm) {
3641 #define TestMovd(Src, Dst, Value) \
3642 do { \
3643 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3644 const uint32_t T0 = allocateQword(); \
3645 const uint64_t V0 = Value; \
3646 const uint32_t T1 = allocateQword(); \
3647 const uint64_t V1 = ~(Value); \
3648 \
3649 __ movq(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3650 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3651 __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3652 \
3653 AssembledTest test = assemble(); \
3654 \
3655 test.setQwordTo(T0, V0); \
3656 test.setQwordTo(T1, V1); \
3657 test.run(); \
3658 \
3659 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3660 << Value; \
3661 reset(); \
3662 } while (0)
3663
3664 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3665 TestMovd(xmm0, xmm1, Value);
3666 TestMovd(xmm1, xmm2, Value);
3667 TestMovd(xmm2, xmm3, Value);
3668 TestMovd(xmm3, xmm4, Value);
3669 TestMovd(xmm4, xmm5, Value);
3670 TestMovd(xmm5, xmm6, Value);
3671 TestMovd(xmm6, xmm7, Value);
3672 TestMovd(xmm7, xmm8, Value);
3673 TestMovd(xmm8, xmm9, Value);
3674 TestMovd(xmm9, xmm10, Value);
3675 TestMovd(xmm10, xmm11, Value);
3676 TestMovd(xmm11, xmm12, Value);
3677 TestMovd(xmm12, xmm13, Value);
3678 TestMovd(xmm13, xmm14, Value);
3679 TestMovd(xmm14, xmm15, Value);
3680 TestMovd(xmm15, xmm0, Value);
3681 }
3682
3683 #undef TestMovd
3684 }
3685
3686 TEST_F(AssemblerX8664Test, ArithSS) {
3687 #define TestArithSSXmmXmm(FloatSize, Src, Value0, Dst, Value1, Inst, Op) \
3688 do { \
3689 static_assert(FloatSize == 32 || FloatSize == 64, \
3690 "Invalid fp size " #FloatSize); \
3691 static constexpr char TestString[] = \
3692 "(" #FloatSize ", " #Src ", " #Value0 ", " #Dst ", " #Value1 \
3693 ", " #Inst ", " #Op ")"; \
3694 static constexpr bool IsDouble = FloatSize == 64; \
3695 using Type = std::conditional<IsDouble, double, float>::type; \
3696 const uint32_t T0 = allocateQword(); \
3697 const Type V0 = Value0; \
3698 const uint32_t T1 = allocateQword(); \
3699 const Type V1 = Value1; \
3700 \
3701 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3702 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Src(), dwordAddress(T1)); \
3703 __ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3704 \
3705 AssembledTest test = assemble(); \
3706 if (IsDouble) { \
3707 test.setQwordTo(T0, static_cast<double>(V0)); \
3708 test.setQwordTo(T1, static_cast<double>(V1)); \
3709 } else { \
3710 test.setDwordTo(T0, static_cast<float>(V0)); \
3711 test.setDwordTo(T1, static_cast<float>(V1)); \
3712 } \
3713 \
3714 test.run(); \
3715 \
3716 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
3717 reset(); \
3718 } while (0)
3719
3720 #define TestArithSSXmmAddr(FloatSize, Value0, Dst, Value1, Inst, Op) \
3721 do { \
3722 static_assert(FloatSize == 32 || FloatSize == 64, \
3723 "Invalid fp size " #FloatSize); \
3724 static constexpr char TestString[] = \
3725 "(" #FloatSize ", Addr, " #Value0 ", " #Dst ", " #Value1 ", " #Inst \
3726 ", " #Op ")"; \
3727 static constexpr bool IsDouble = FloatSize == 64; \
3728 using Type = std::conditional<IsDouble, double, float>::type; \
3729 const uint32_t T0 = allocateQword(); \
3730 const Type V0 = Value0; \
3731 const uint32_t T1 = allocateQword(); \
3732 const Type V1 = Value1; \
3733 \
3734 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3735 __ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3736 \
3737 AssembledTest test = assemble(); \
3738 if (IsDouble) { \
3739 test.setQwordTo(T0, static_cast<double>(V0)); \
3740 test.setQwordTo(T1, static_cast<double>(V1)); \
3741 } else { \
3742 test.setDwordTo(T0, static_cast<float>(V0)); \
3743 test.setDwordTo(T1, static_cast<float>(V1)); \
3744 } \
3745 \
3746 test.run(); \
3747 \
3748 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
3749 reset(); \
3750 } while (0)
3751
3752 #define TestArithSS(FloatSize, Src, Dst0, Dst1) \
3753 do { \
3754 TestArithSSXmmXmm(FloatSize, Src, 1.0, Dst0, 10.0, addss, +); \
3755 TestArithSSXmmAddr(FloatSize, 2.0, Dst1, 20.0, addss, +); \
3756 TestArithSSXmmXmm(FloatSize, Src, 3.0, Dst0, 30.0, subss, -); \
3757 TestArithSSXmmAddr(FloatSize, 4.0, Dst1, 40.0, subss, -); \
3758 TestArithSSXmmXmm(FloatSize, Src, 5.0, Dst0, 50.0, mulss, *); \
3759 TestArithSSXmmAddr(FloatSize, 6.0, Dst1, 60.0, mulss, *); \
3760 TestArithSSXmmXmm(FloatSize, Src, 7.0, Dst0, 70.0, divss, / ); \
3761 TestArithSSXmmAddr(FloatSize, 8.0, Dst1, 80.0, divss, / ); \
3762 } while (0)
3763
3764 #define TestImpl(Src, Dst0, Dst1) \
3765 do { \
3766 TestArithSS(32, Src, Dst0, Dst1); \
3767 TestArithSS(64, Src, Dst0, Dst1); \
3768 } while (0)
3769
3770 TestImpl(xmm0, xmm1, xmm2);
3771 TestImpl(xmm1, xmm2, xmm3);
3772 TestImpl(xmm2, xmm3, xmm4);
3773 TestImpl(xmm3, xmm4, xmm5);
3774 TestImpl(xmm4, xmm5, xmm6);
3775 TestImpl(xmm5, xmm6, xmm7);
3776 TestImpl(xmm6, xmm7, xmm8);
3777 TestImpl(xmm7, xmm8, xmm9);
3778 TestImpl(xmm8, xmm9, xmm10);
3779 TestImpl(xmm9, xmm10, xmm11);
3780 TestImpl(xmm10, xmm11, xmm12);
3781 TestImpl(xmm11, xmm12, xmm13);
3782 TestImpl(xmm12, xmm13, xmm14);
3783 TestImpl(xmm13, xmm14, xmm15);
3784 TestImpl(xmm14, xmm15, xmm0);
3785 TestImpl(xmm15, xmm0, xmm1);
3786
3787 #undef TestImpl
3788 #undef TestArithSS
3789 #undef TestArithSSXmmAddr
3790 #undef TestArithSSXmmXmm
3791 }
3792
3793 TEST_F(AssemblerX8664Test, MovupsXmmAddr) {
3794 #define TestMovups(Dst) \
3795 do { \
3796 static constexpr char TestString[] = "(" #Dst ")"; \
3797 const uint32_t T0 = allocateDqword(); \
3798 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3799 std::numeric_limits<float>::infinity()); \
3800 \
3801 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3802 \
3803 AssembledTest test = assemble(); \
3804 test.setDqwordTo(T0, V0); \
3805 test.run(); \
3806 \
3807 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3808 reset(); \
3809 } while (0)
3810
3811 TestMovups(xmm0);
3812 TestMovups(xmm1);
3813 TestMovups(xmm2);
3814 TestMovups(xmm3);
3815 TestMovups(xmm4);
3816 TestMovups(xmm5);
3817 TestMovups(xmm6);
3818 TestMovups(xmm7);
3819 TestMovups(xmm8);
3820 TestMovups(xmm9);
3821 TestMovups(xmm10);
3822 TestMovups(xmm11);
3823 TestMovups(xmm12);
3824 TestMovups(xmm13);
3825 TestMovups(xmm14);
3826 TestMovups(xmm15);
3827
3828 #undef TestMovups
3829 }
3830
3831 TEST_F(AssemblerX8664Test, MovupsAddrXmm) {
3832 #define TestMovups(Src) \
3833 do { \
3834 static constexpr char TestString[] = "(" #Src ")"; \
3835 const uint32_t T0 = allocateDqword(); \
3836 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3837 std::numeric_limits<float>::infinity()); \
3838 const uint32_t T1 = allocateDqword(); \
3839 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3840 \
3841 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3842 __ movups(dwordAddress(T1), Encoded_Xmm_##Src()); \
3843 \
3844 AssembledTest test = assemble(); \
3845 test.setDqwordTo(T0, V0); \
3846 test.setDqwordTo(T1, V1); \
3847 test.run(); \
3848 \
3849 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \
3850 reset(); \
3851 } while (0)
3852
3853 TestMovups(xmm0);
3854 TestMovups(xmm1);
3855 TestMovups(xmm2);
3856 TestMovups(xmm3);
3857 TestMovups(xmm4);
3858 TestMovups(xmm5);
3859 TestMovups(xmm6);
3860 TestMovups(xmm7);
3861 TestMovups(xmm8);
3862 TestMovups(xmm9);
3863 TestMovups(xmm10);
3864 TestMovups(xmm11);
3865 TestMovups(xmm12);
3866 TestMovups(xmm13);
3867 TestMovups(xmm14);
3868 TestMovups(xmm15);
3869
3870 #undef TestMovups
3871 }
3872
3873 TEST_F(AssemblerX8664Test, MovupsXmmXmm) {
3874 #define TestMovups(Dst, Src) \
3875 do { \
3876 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
3877 const uint32_t T0 = allocateDqword(); \
3878 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3879 std::numeric_limits<float>::infinity()); \
3880 const uint32_t T1 = allocateDqword(); \
3881 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3882 \
3883 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3884 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3885 __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3886 \
3887 AssembledTest test = assemble(); \
3888 test.setDqwordTo(T0, V0); \
3889 test.setDqwordTo(T1, V1); \
3890 test.run(); \
3891 \
3892 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3893 reset(); \
3894 } while (0)
3895
3896 TestMovups(xmm0, xmm1);
3897 TestMovups(xmm1, xmm2);
3898 TestMovups(xmm2, xmm3);
3899 TestMovups(xmm3, xmm4);
3900 TestMovups(xmm4, xmm5);
3901 TestMovups(xmm5, xmm6);
3902 TestMovups(xmm6, xmm7);
3903 TestMovups(xmm7, xmm8);
3904 TestMovups(xmm8, xmm9);
3905 TestMovups(xmm9, xmm10);
3906 TestMovups(xmm10, xmm11);
3907 TestMovups(xmm11, xmm12);
3908 TestMovups(xmm12, xmm13);
3909 TestMovups(xmm13, xmm14);
3910 TestMovups(xmm14, xmm15);
3911 TestMovups(xmm15, xmm0);
3912
3913 #undef TestMovups
3914 }
3915
3916 TEST_F(AssemblerX8664Test, MovapsXmmXmm) {
3917 #define TestMovaps(Dst, Src) \
3918 do { \
3919 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
3920 const uint32_t T0 = allocateDqword(); \
3921 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3922 std::numeric_limits<float>::infinity()); \
3923 const uint32_t T1 = allocateDqword(); \
3924 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3925 \
3926 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3927 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3928 __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3929 \
3930 AssembledTest test = assemble(); \
3931 test.setDqwordTo(T0, V0); \
3932 test.setDqwordTo(T1, V1); \
3933 test.run(); \
3934 \
3935 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3936 reset(); \
3937 } while (0)
3938
3939 TestMovaps(xmm0, xmm1);
3940 TestMovaps(xmm1, xmm2);
3941 TestMovaps(xmm2, xmm3);
3942 TestMovaps(xmm3, xmm4);
3943 TestMovaps(xmm4, xmm5);
3944 TestMovaps(xmm5, xmm6);
3945 TestMovaps(xmm6, xmm7);
3946 TestMovaps(xmm7, xmm8);
3947 TestMovaps(xmm8, xmm9);
3948 TestMovaps(xmm9, xmm10);
3949 TestMovaps(xmm10, xmm11);
3950 TestMovaps(xmm11, xmm12);
3951 TestMovaps(xmm12, xmm13);
3952 TestMovaps(xmm13, xmm14);
3953 TestMovaps(xmm14, xmm15);
3954 TestMovaps(xmm15, xmm0);
3955
3956 #undef TestMovaps
3957 }
3958
3959 TEST_F(AssemblerX8664Test, PArith) {
3960 #define TestPArithXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type, Size) \
3961 do { \
3962 static constexpr char TestString[] = \
3963 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
3964 ", " #Type ", " #Size ")"; \
3965 const uint32_t T0 = allocateDqword(); \
3966 const Dqword V0 Value0; \
3967 \
3968 const uint32_t T1 = allocateDqword(); \
3969 const Dqword V1 Value1; \
3970 \
3971 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3972 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
3973 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3974 \
3975 AssembledTest test = assemble(); \
3976 test.setDqwordTo(T0, V0); \
3977 test.setDqwordTo(T1, V1); \
3978 test.run(); \
3979 \
3980 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
3981 << TestString; \
3982 reset(); \
3983 } while (0)
3984
3985 #define TestPArithXmmAddr(Dst, Value0, Value1, Inst, Op, Type, Size) \
3986 do { \
3987 static constexpr char TestString[] = \
3988 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
3989 ", " #Type ", " #Size ")"; \
3990 const uint32_t T0 = allocateDqword(); \
3991 const Dqword V0 Value0; \
3992 \
3993 const uint32_t T1 = allocateDqword(); \
3994 const Dqword V1 Value1; \
3995 \
3996 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3997 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3998 \
3999 AssembledTest test = assemble(); \
4000 test.setDqwordTo(T0, V0); \
4001 test.setDqwordTo(T1, V1); \
4002 test.run(); \
4003 \
4004 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
4005 << TestString; \
4006 reset(); \
4007 } while (0)
4008
4009 #define TestPArithXmmImm(Dst, Value0, Imm, Inst, Op, Type, Size) \
4010 do { \
4011 static constexpr char TestString[] = \
4012 "(" #Dst ", " #Value0 ", " #Imm ", " #Inst ", " #Op ", " #Type \
4013 ", " #Size ")"; \
4014 const uint32_t T0 = allocateDqword(); \
4015 const Dqword V0 Value0; \
4016 \
4017 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4018 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Immediate(Imm)); \
4019 \
4020 AssembledTest test = assemble(); \
4021 test.setDqwordTo(T0, V0); \
4022 test.run(); \
4023 \
4024 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op Imm, test.Dst<Dqword>()) \
4025 << TestString; \
4026 reset(); \
4027 } while (0)
4028
4029 #define TestPAndnXmmXmm(Dst, Value0, Src, Value1, Type, Size) \
4030 do { \
4031 static constexpr char TestString[] = \
4032 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", pandn, " #Type \
4033 ", " #Size ")"; \
4034 const uint32_t T0 = allocateDqword(); \
4035 const Dqword V0 Value0; \
4036 \
4037 const uint32_t T1 = allocateDqword(); \
4038 const Dqword V1 Value1; \
4039 \
4040 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4041 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4042 __ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4043 \
4044 AssembledTest test = assemble(); \
4045 test.setDqwordTo(T0, V0); \
4046 test.setDqwordTo(T1, V1); \
4047 test.run(); \
4048 \
4049 ASSERT_EQ(~(packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
4050 << TestString; \
4051 reset(); \
4052 } while (0)
4053
4054 #define TestPAndnXmmAddr(Dst, Value0, Value1, Type, Size) \
4055 do { \
4056 static constexpr char TestString[] = \
4057 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", pandn, " #Type ", " #Size \
4058 ")"; \
4059 const uint32_t T0 = allocateDqword(); \
4060 const Dqword V0 Value0; \
4061 \
4062 const uint32_t T1 = allocateDqword(); \
4063 const Dqword V1 Value1; \
4064 \
4065 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4066 __ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4067 \
4068 AssembledTest test = assemble(); \
4069 test.setDqwordTo(T0, V0); \
4070 test.setDqwordTo(T1, V1); \
4071 test.run(); \
4072 \
4073 ASSERT_EQ((~packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
4074 << TestString; \
4075 reset(); \
4076 } while (0)
4077
4078 #define TestPArithSize(Dst, Src, Size) \
4079 do { \
4080 static_assert(Size == 8 || Size == 16 || Size == 32, "Invalid size."); \
4081 if (Size != 8) { \
4082 TestPArithXmmXmm( \
4083 Dst, \
4084 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4085 Src, (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
4086 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4087 uint64_t(0x8080404002020101ull)), \
4088 (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
4089 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4090 uint64_t(0x8080404002020101ull)), \
4091 3u, psra, >>, int, Size); \
4092 TestPArithXmmXmm( \
4093 Dst, \
4094 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4095 Src, (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
4096 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4097 uint64_t(0x8080404002020101ull)), \
4098 (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
4099 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4100 uint64_t(0x8080404002020101ull)), \
4101 3u, psrl, >>, uint, Size); \
4102 TestPArithXmmXmm( \
4103 Dst, \
4104 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4105 Src, (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
4106 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4107 uint64_t(0x8080404002020101ull)), \
4108 (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
4109 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4110 uint64_t(0x8080404002020101ull)), \
4111 3u, psll, <<, uint, Size); \
4112 \
4113 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4114 uint64_t(0x8080404002020101ull)), \
4115 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4116 uint64_t(0x0123456789ABCDEull)), \
4117 pmull, *, int, Size); \
4118 TestPArithXmmAddr( \
4119 Dst, \
4120 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4121 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4122 pmull, *, int, Size); \
4123 if (Size != 16) { \
4124 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4125 uint64_t(0x8080404002020101ull)), \
4126 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4127 uint64_t(0x0123456789ABCDEull)), \
4128 pmuludq, *, uint, Size); \
4129 TestPArithXmmAddr( \
4130 Dst, (uint64_t(0x8040201008040201ull), \
4131 uint64_t(0x8080404002020101ull)), \
4132 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4133 pmuludq, *, uint, Size); \
4134 } \
4135 } \
4136 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4137 uint64_t(0x8080404002020101ull)), \
4138 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4139 uint64_t(0x0123456789ABCDEull)), \
4140 padd, +, int, Size); \
4141 TestPArithXmmAddr( \
4142 Dst, \
4143 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4144 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4145 padd, +, int, Size); \
4146 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4147 uint64_t(0x8080404002020101ull)), \
4148 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4149 uint64_t(0x0123456789ABCDEull)), \
4150 psub, -, int, Size); \
4151 TestPArithXmmAddr( \
4152 Dst, \
4153 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4154 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4155 psub, -, int, Size); \
4156 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4157 uint64_t(0x8080404002020101ull)), \
4158 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4159 uint64_t(0x0123456789ABCDEull)), \
4160 pand, &, int, Size); \
4161 TestPArithXmmAddr( \
4162 Dst, \
4163 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4164 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4165 pand, &, int, Size); \
4166 \
4167 TestPAndnXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4168 uint64_t(0x8080404002020101ull)), \
4169 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4170 uint64_t(0x0123456789ABCDEull)), \
4171 int, Size); \
4172 TestPAndnXmmAddr( \
4173 Dst, \
4174 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4175 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4176 int, Size); \
4177 \
4178 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4179 uint64_t(0x8080404002020101ull)), \
4180 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4181 uint64_t(0x0123456789ABCDEull)), \
4182 por, |, int, Size); \
4183 TestPArithXmmAddr( \
4184 Dst, \
4185 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4186 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4187 por, |, int, Size); \
4188 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4189 uint64_t(0x8080404002020101ull)), \
4190 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4191 uint64_t(0x0123456789ABCDEull)), \
4192 pxor, ^, int, Size); \
4193 TestPArithXmmAddr( \
4194 Dst, \
4195 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4196 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4197 pxor, ^, int, Size); \
4198 } while (0)
4199
4200 #define TestPArith(Src, Dst) \
4201 do { \
4202 TestPArithSize(Src, Dst, 8); \
4203 TestPArithSize(Src, Dst, 16); \
4204 TestPArithSize(Src, Dst, 32); \
4205 } while (0)
4206
4207 TestPArith(xmm0, xmm1);
4208 TestPArith(xmm1, xmm2);
4209 TestPArith(xmm2, xmm3);
4210 TestPArith(xmm3, xmm4);
4211 TestPArith(xmm4, xmm5);
4212 TestPArith(xmm5, xmm6);
4213 TestPArith(xmm6, xmm7);
4214 TestPArith(xmm7, xmm8);
4215 TestPArith(xmm8, xmm9);
4216 TestPArith(xmm9, xmm10);
4217 TestPArith(xmm10, xmm11);
4218 TestPArith(xmm11, xmm12);
4219 TestPArith(xmm12, xmm13);
4220 TestPArith(xmm13, xmm14);
4221 TestPArith(xmm14, xmm15);
4222 TestPArith(xmm15, xmm0);
4223
4224 #undef TestPArith
4225 #undef TestPArithSize
4226 #undef TestPAndnXmmAddr
4227 #undef TestPAndnXmmXmm
4228 #undef TestPArithXmmImm
4229 #undef TestPArithXmmAddr
4230 #undef TestPArithXmmXmm
4231 }
4232
4233 TEST_F(AssemblerX8664Test, ArithPS) {
4234 #define TestArithPSXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type) \
4235 do { \
4236 static constexpr char TestString[] = \
4237 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
4238 ", " #Type ")"; \
4239 const uint32_t T0 = allocateDqword(); \
4240 const Dqword V0 Value0; \
4241 const uint32_t T1 = allocateDqword(); \
4242 const Dqword V1 Value1; \
4243 \
4244 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4245 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4246 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4247 \
4248 AssembledTest test = assemble(); \
4249 test.setDqwordTo(T0, V0); \
4250 test.setDqwordTo(T1, V1); \
4251 test.run(); \
4252 \
4253 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4254 \
4255 reset(); \
4256 } while (0)
4257
4258 #define TestArithPSXmmXmmUntyped(Dst, Value0, Src, Value1, Inst, Op, Type) \
4259 do { \
4260 static constexpr char TestString[] = \
4261 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
4262 ", " #Type ")"; \
4263 const uint32_t T0 = allocateDqword(); \
4264 const Dqword V0 Value0; \
4265 const uint32_t T1 = allocateDqword(); \
4266 const Dqword V1 Value1; \
4267 \
4268 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4269 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4270 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4271 \
4272 AssembledTest test = assemble(); \
4273 test.setDqwordTo(T0, V0); \
4274 test.setDqwordTo(T1, V1); \
4275 test.run(); \
4276 \
4277 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4278 \
4279 reset(); \
4280 } while (0)
4281
4282 #define TestArithPSXmmAddrUntyped(Dst, Value0, Value1, Inst, Op, Type) \
4283 do { \
4284 static constexpr char TestString[] = \
4285 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
4286 ", " #Type ")"; \
4287 const uint32_t T0 = allocateDqword(); \
4288 const Dqword V0 Value0; \
4289 const uint32_t T1 = allocateDqword(); \
4290 const Dqword V1 Value1; \
4291 \
4292 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4293 __ Inst(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4294 \
4295 AssembledTest test = assemble(); \
4296 test.setDqwordTo(T0, V0); \
4297 test.setDqwordTo(T1, V1); \
4298 test.run(); \
4299 \
4300 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4301 \
4302 reset(); \
4303 } while (0)
4304
4305 #define TestMinMaxPS(Dst, Value0, Src, Value1, Inst, Type) \
4306 do { \
4307 static constexpr char TestString[] = \
4308 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Type \
4309 ")"; \
4310 const uint32_t T0 = allocateDqword(); \
4311 const Dqword V0 Value0; \
4312 const uint32_t T1 = allocateDqword(); \
4313 const Dqword V1 Value1; \
4314 \
4315 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4316 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4317 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4318 \
4319 AssembledTest test = assemble(); \
4320 test.setDqwordTo(T0, V0); \
4321 test.setDqwordTo(T1, V1); \
4322 test.run(); \
4323 \
4324 ASSERT_EQ(packedAs<Type>(V0).Inst(V1), test.Dst<Dqword>()) << TestString; \
4325 \
4326 reset(); \
4327 } while (0)
4328
4329 #define TestArithPSXmmAddr(Dst, Value0, Value1, Inst, Op, Type) \
4330 do { \
4331 static constexpr char TestString[] = \
4332 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
4333 ", " #Type ")"; \
4334 const uint32_t T0 = allocateDqword(); \
4335 const Dqword V0 Value0; \
4336 const uint32_t T1 = allocateDqword(); \
4337 const Dqword V1 Value1; \
4338 \
4339 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4340 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4341 \
4342 AssembledTest test = assemble(); \
4343 test.setDqwordTo(T0, V0); \
4344 test.setDqwordTo(T1, V1); \
4345 test.run(); \
4346 \
4347 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4348 \
4349 reset(); \
4350 } while (0)
4351
4352 #define TestArithPS(Dst, Src) \
4353 do { \
4354 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4355 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
4356 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4357 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
4358 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4359 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
4360 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4361 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
4362 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4363 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
4364 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4365 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
4366 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4367 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
4368 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4369 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
4370 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4371 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
4372 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
4373 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
4374 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), andpd, &, \
4375 double); \
4376 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), andpd, &, \
4377 double); \
4378 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4379 (0.55, 0.43, 0.23, 1.21), orps, |, float); \
4380 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), orpd, |, \
4381 double); \
4382 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4383 (0.55, 0.43, 0.23, 1.21), minps, float); \
4384 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4385 (0.55, 0.43, 0.23, 1.21), maxps, float); \
4386 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), minpd, double); \
4387 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxpd, double); \
4388 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4389 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
4390 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
4391 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
4392 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorpd, ^, \
4393 double); \
4394 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), xorpd, ^, \
4395 double); \
4396 } while (0)
4397
4398 TestArithPS(xmm0, xmm1);
4399 TestArithPS(xmm1, xmm2);
4400 TestArithPS(xmm2, xmm3);
4401 TestArithPS(xmm3, xmm4);
4402 TestArithPS(xmm4, xmm5);
4403 TestArithPS(xmm5, xmm6);
4404 TestArithPS(xmm6, xmm7);
4405 TestArithPS(xmm7, xmm8);
4406 TestArithPS(xmm8, xmm9);
4407 TestArithPS(xmm9, xmm10);
4408 TestArithPS(xmm10, xmm11);
4409 TestArithPS(xmm11, xmm12);
4410 TestArithPS(xmm12, xmm13);
4411 TestArithPS(xmm13, xmm14);
4412 TestArithPS(xmm14, xmm15);
4413 TestArithPS(xmm15, xmm0);
4414
4415 #undef TestArithPs
4416 #undef TestMinMaxPS
4417 #undef TestArithPSXmmXmmUntyped
4418 #undef TestArithPSXmmAddr
4419 #undef TestArithPSXmmXmm
4420 }
4421
4422 TEST_F(AssemblerX8664Test, Blending) {
4423 using f32 = float;
4424 using i8 = uint8_t;
4425
4426 #define TestBlendingXmmXmm(Dst, Value0, Src, Value1, M /*ask*/, Inst, Type) \
4427 do { \
4428 static constexpr char TestString[] = \
4429 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #M ", " #Inst \
4430 ", " #Type ")"; \
4431 const uint32_t T0 = allocateDqword(); \
4432 const Dqword V0 Value0; \
4433 const uint32_t T1 = allocateDqword(); \
4434 const Dqword V1 Value1; \
4435 const uint32_t Mask = allocateDqword(); \
4436 const Dqword MaskValue M; \
4437 \
4438 __ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
4439 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4440 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4441 __ Inst(IceType_##Type, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4442 \
4443 AssembledTest test = assemble(); \
4444 test.setDqwordTo(T0, V0); \
4445 test.setDqwordTo(T1, V1); \
4446 test.setDqwordTo(Mask, MaskValue); \
4447 test.run(); \
4448 \
4449 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
4450 << TestString; \
4451 reset(); \
4452 } while (0)
4453
4454 #define TestBlendingXmmAddr(Dst, Value0, Value1, M /*ask*/, Inst, Type) \
4455 do { \
4456 static constexpr char TestString[] = \
4457 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #M ", " #Inst ", " #Type \
4458 ")"; \
4459 const uint32_t T0 = allocateDqword(); \
4460 const Dqword V0 Value0; \
4461 const uint32_t T1 = allocateDqword(); \
4462 const Dqword V1 Value1; \
4463 const uint32_t Mask = allocateDqword(); \
4464 const Dqword MaskValue M; \
4465 \
4466 __ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
4467 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4468 __ Inst(IceType_##Type, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4469 \
4470 AssembledTest test = assemble(); \
4471 test.setDqwordTo(T0, V0); \
4472 test.setDqwordTo(T1, V1); \
4473 test.setDqwordTo(Mask, MaskValue); \
4474 test.run(); \
4475 \
4476 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
4477 << TestString; \
4478 reset(); \
4479 } while (0)
4480
4481 #define TestBlending(Src, Dst) \
4482 do { \
4483 TestBlendingXmmXmm( \
4484 Dst, (1.0, 2.0, 1.0, 2.0), Src, (-1.0, -2.0, -1.0, -2.0), \
4485 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
4486 blendvps, f32); \
4487 TestBlendingXmmAddr( \
4488 Dst, (1.0, 2.0, 1.0, 2.0), (-1.0, -2.0, -1.0, -2.0), \
4489 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
4490 blendvps, f32); \
4491 TestBlendingXmmXmm( \
4492 Dst, \
4493 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
4494 Src, \
4495 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
4496 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
4497 pblendvb, i8); \
4498 TestBlendingXmmAddr( \
4499 Dst, \
4500 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
4501 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
4502 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
4503 pblendvb, i8); \
4504 } while (0)
4505
4506 /* xmm0 is taken. It is the implicit mask . */
4507 TestBlending(xmm1, xmm2);
4508 TestBlending(xmm2, xmm3);
4509 TestBlending(xmm3, xmm4);
4510 TestBlending(xmm4, xmm5);
4511 TestBlending(xmm5, xmm6);
4512 TestBlending(xmm6, xmm7);
4513 TestBlending(xmm7, xmm8);
4514 TestBlending(xmm8, xmm9);
4515 TestBlending(xmm9, xmm10);
4516 TestBlending(xmm10, xmm11);
4517 TestBlending(xmm11, xmm12);
4518 TestBlending(xmm12, xmm13);
4519 TestBlending(xmm13, xmm14);
4520 TestBlending(xmm14, xmm15);
4521 TestBlending(xmm15, xmm1);
4522
4523 #undef TestBlending
4524 #undef TestBlendingXmmAddr
4525 #undef TestBlendingXmmXmm
4526 }
4527
4528 TEST_F(AssemblerX8664Test, Cmpps) {
4529 #define TestCmppsXmmXmm(Dst, Src, C, Op) \
4530 do { \
4531 static constexpr char TestString[] = \
4532 "(" #Src ", " #Dst ", " #C ", " #Op ")"; \
4533 const uint32_t T0 = allocateDqword(); \
4534 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
4535 const uint32_t T1 = allocateDqword(); \
4536 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
4537 \
4538 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4539 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4540 __ cmpps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Cond::Cmpps_##C); \
4541 \
4542 AssembledTest test = assemble(); \
4543 test.setDqwordTo(T0, V0); \
4544 test.setDqwordTo(T1, V1); \
4545 test.run(); \
4546 \
4547 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4548 ; \
4549 reset(); \
4550 } while (0)
4551
4552 #define TestCmppsXmmAddr(Dst, C, Op) \
4553 do { \
4554 static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \
4555 const uint32_t T0 = allocateDqword(); \
4556 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
4557 const uint32_t T1 = allocateDqword(); \
4558 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
4559 \
4560 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4561 __ cmpps(Encoded_Xmm_##Dst(), dwordAddress(T1), Cond::Cmpps_##C); \
4562 \
4563 AssembledTest test = assemble(); \
4564 test.setDqwordTo(T0, V0); \
4565 test.setDqwordTo(T1, V1); \
4566 test.run(); \
4567 \
4568 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4569 ; \
4570 reset(); \
4571 } while (0)
4572
4573 #define TestCmppsOrdUnordXmmXmm(Dst, Src, C) \
4574 do { \
4575 static constexpr char TestString[] = "(" #Src ", " #Dst ", " #C ")"; \
4576 const uint32_t T0 = allocateDqword(); \
4577 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
4578 std::numeric_limits<float>::quiet_NaN()); \
4579 const uint32_t T1 = allocateDqword(); \
4580 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
4581 std::numeric_limits<float>::quiet_NaN()); \
4582 \
4583 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4584 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4585 __ cmpps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Cond::Cmpps_##C); \
4586 \
4587 AssembledTest test = assemble(); \
4588 test.setDqwordTo(T0, V0); \
4589 test.setDqwordTo(T1, V1); \
4590 test.run(); \
4591 \
4592 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
4593 ; \
4594 reset(); \
4595 } while (0)
4596
4597 #define TestCmppsOrdUnordXmmAddr(Dst, C) \
4598 do { \
4599 static constexpr char TestString[] = "(" #Dst ", " #C ")"; \
4600 const uint32_t T0 = allocateDqword(); \
4601 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
4602 std::numeric_limits<float>::quiet_NaN()); \
4603 const uint32_t T1 = allocateDqword(); \
4604 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
4605 std::numeric_limits<float>::quiet_NaN()); \
4606 \
4607 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4608 __ cmpps(Encoded_Xmm_##Dst(), dwordAddress(T1), Cond::Cmpps_##C); \
4609 \
4610 AssembledTest test = assemble(); \
4611 test.setDqwordTo(T0, V0); \
4612 test.setDqwordTo(T1, V1); \
4613 test.run(); \
4614 \
4615 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
4616 ; \
4617 reset(); \
4618 } while (0)
4619
4620 #define TestCmpps(Dst, Src) \
4621 do { \
4622 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4623 TestCmppsXmmAddr(Dst, eq, == ); \
4624 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4625 TestCmppsXmmAddr(Dst, eq, == ); \
4626 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4627 TestCmppsXmmAddr(Dst, eq, == ); \
4628 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
4629 TestCmppsOrdUnordXmmAddr(Dst, unord); \
4630 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4631 TestCmppsXmmAddr(Dst, eq, == ); \
4632 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4633 TestCmppsXmmAddr(Dst, eq, == ); \
4634 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4635 TestCmppsXmmAddr(Dst, eq, == ); \
4636 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
4637 TestCmppsOrdUnordXmmAddr(Dst, unord); \
4638 } while (0)
4639
4640 TestCmpps(xmm0, xmm1);
4641 TestCmpps(xmm1, xmm2);
4642 TestCmpps(xmm2, xmm3);
4643 TestCmpps(xmm3, xmm4);
4644 TestCmpps(xmm4, xmm5);
4645 TestCmpps(xmm5, xmm6);
4646 TestCmpps(xmm6, xmm7);
4647 TestCmpps(xmm7, xmm8);
4648 TestCmpps(xmm8, xmm9);
4649 TestCmpps(xmm9, xmm10);
4650 TestCmpps(xmm10, xmm11);
4651 TestCmpps(xmm11, xmm12);
4652 TestCmpps(xmm12, xmm13);
4653 TestCmpps(xmm13, xmm14);
4654 TestCmpps(xmm14, xmm15);
4655 TestCmpps(xmm15, xmm0);
4656
4657 #undef TestCmpps
4658 #undef TestCmppsOrdUnordXmmAddr
4659 #undef TestCmppsOrdUnordXmmXmm
4660 #undef TestCmppsXmmAddr
4661 #undef TestCmppsXmmXmm
4662 }
4663
4664 TEST_F(AssemblerX8664Test, Sqrtps_Rsqrtps_Reciprocalps_Sqrtpd) {
4665 #define TestImplSingle(Dst, Inst, Expect) \
4666 do { \
4667 static constexpr char TestString[] = "(" #Dst ", " #Inst ")"; \
4668 const uint32_t T0 = allocateDqword(); \
4669 const Dqword V0(1.0, 4.0, 20.0, 3.14); \
4670 \
4671 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4672 __ Inst(Encoded_Xmm_##Dst()); \
4673 \
4674 AssembledTest test = assemble(); \
4675 test.setDqwordTo(T0, V0); \
4676 test.run(); \
4677 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
4678 reset(); \
4679 } while (0)
4680
4681 #define TestImpl(Dst) \
4682 do { \
4683 TestImplSingle(Dst, sqrtps, (uint64_t(0x400000003F800000ull), \
4684 uint64_t(0x3FE2D10B408F1BBDull))); \
4685 TestImplSingle(Dst, rsqrtps, (uint64_t(0x3EFFF0003F7FF000ull), \
4686 uint64_t(0x3F1078003E64F000ull))); \
4687 TestImplSingle(Dst, reciprocalps, (uint64_t(0x3E7FF0003F7FF000ull), \
4688 uint64_t(0x3EA310003D4CC000ull))); \
4689 \
4690 TestImplSingle(Dst, sqrtpd, (uint64_t(0x4036A09E9365F5F3ull), \
4691 uint64_t(0x401C42FAE40282A8ull))); \
4692 } while (0)
4693
4694 TestImpl(xmm0);
4695 TestImpl(xmm1);
4696 TestImpl(xmm2);
4697 TestImpl(xmm3);
4698 TestImpl(xmm4);
4699 TestImpl(xmm5);
4700 TestImpl(xmm6);
4701 TestImpl(xmm7);
4702 TestImpl(xmm8);
4703 TestImpl(xmm9);
4704 TestImpl(xmm10);
4705 TestImpl(xmm11);
4706 TestImpl(xmm12);
4707 TestImpl(xmm13);
4708 TestImpl(xmm14);
4709 TestImpl(xmm15);
4710
4711 #undef TestImpl
4712 #undef TestImplSingle
4713 }
4714
4715 TEST_F(AssemblerX8664Test, Movhlps_Movlhps) {
4716 #define TestImplSingle(Dst, Src, Inst, Expect) \
4717 do { \
4718 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4719 const uint32_t T0 = allocateDqword(); \
4720 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \
4721 uint64_t(0xCCCCCCCCDDDDDDDDull)); \
4722 const uint32_t T1 = allocateDqword(); \
4723 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \
4724 uint64_t(0x9999999988888888ull)); \
4725 \
4726 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4727 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4728 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4729 \
4730 AssembledTest test = assemble(); \
4731 test.setDqwordTo(T0, V0); \
4732 test.setDqwordTo(T1, V1); \
4733 test.run(); \
4734 \
4735 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
4736 reset(); \
4737 } while (0)
4738
4739 #define TestImpl(Dst, Src) \
4740 do { \
4741 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \
4742 uint64_t(0xCCCCCCCCDDDDDDDDull))); \
4743 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \
4744 uint64_t(0xEEEEEEEEFFFFFFFFull))); \
4745 } while (0)
4746
4747 TestImpl(xmm0, xmm1);
4748 TestImpl(xmm1, xmm2);
4749 TestImpl(xmm2, xmm3);
4750 TestImpl(xmm3, xmm4);
4751 TestImpl(xmm4, xmm5);
4752 TestImpl(xmm5, xmm6);
4753 TestImpl(xmm6, xmm7);
4754 TestImpl(xmm7, xmm8);
4755 TestImpl(xmm8, xmm9);
4756 TestImpl(xmm9, xmm10);
4757 TestImpl(xmm10, xmm11);
4758 TestImpl(xmm11, xmm12);
4759 TestImpl(xmm12, xmm13);
4760 TestImpl(xmm13, xmm14);
4761 TestImpl(xmm14, xmm15);
4762 TestImpl(xmm15, xmm0);
4763
4764 #undef TestImpl
4765 #undef TestImplSingle
4766 }
4767
4768 TEST_F(AssemblerX8664Test, Unpck) {
4769 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),
4770 uint64_t(0xCCCCCCCCDDDDDDDDull));
4771 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),
4772 uint64_t(0x9999999988888888ull));
4773
4774 const Dqword unpcklpsExpected(uint64_t(0xFFFFFFFFBBBBBBBBull),
4775 uint64_t(0xEEEEEEEEAAAAAAAAull));
4776 const Dqword unpcklpdExpected(uint64_t(0xAAAAAAAABBBBBBBBull),
4777 uint64_t(0xEEEEEEEEFFFFFFFFull));
4778 const Dqword unpckhpsExpected(uint64_t(0x88888888DDDDDDDDull),
4779 uint64_t(0x99999999CCCCCCCCull));
4780 const Dqword unpckhpdExpected(uint64_t(0xCCCCCCCCDDDDDDDDull),
4781 uint64_t(0x9999999988888888ull));
4782
4783 #define TestImplSingle(Dst, Src, Inst) \
4784 do { \
4785 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4786 const uint32_t T0 = allocateDqword(); \
4787 const uint32_t T1 = allocateDqword(); \
4788 \
4789 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4790 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4791 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4792 \
4793 AssembledTest test = assemble(); \
4794 test.setDqwordTo(T0, V0); \
4795 test.setDqwordTo(T1, V1); \
4796 test.run(); \
4797 \
4798 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4799 reset(); \
4800 } while (0)
4801
4802 #define TestImpl(Dst, Src) \
4803 do { \
4804 TestImplSingle(Dst, Src, unpcklps); \
4805 TestImplSingle(Dst, Src, unpcklpd); \
4806 TestImplSingle(Dst, Src, unpckhps); \
4807 TestImplSingle(Dst, Src, unpckhpd); \
4808 } while (0)
4809
4810 TestImpl(xmm0, xmm1);
4811 TestImpl(xmm1, xmm2);
4812 TestImpl(xmm2, xmm3);
4813 TestImpl(xmm3, xmm4);
4814 TestImpl(xmm4, xmm5);
4815 TestImpl(xmm5, xmm6);
4816 TestImpl(xmm6, xmm7);
4817 TestImpl(xmm7, xmm8);
4818 TestImpl(xmm8, xmm9);
4819 TestImpl(xmm9, xmm10);
4820 TestImpl(xmm10, xmm11);
4821 TestImpl(xmm11, xmm12);
4822 TestImpl(xmm12, xmm13);
4823 TestImpl(xmm13, xmm14);
4824 TestImpl(xmm14, xmm15);
4825 TestImpl(xmm15, xmm0);
4826
4827 #undef TestImpl
4828 #undef TestImplSingle
4829 }
4830
4831 TEST_F(AssemblerX8664Test, Shufp) {
4832 const Dqword V0(uint64_t(0x1111111122222222ull),
4833 uint64_t(0x5555555577777777ull));
4834 const Dqword V1(uint64_t(0xAAAAAAAABBBBBBBBull),
4835 uint64_t(0xCCCCCCCCDDDDDDDDull));
4836
4837 const uint8_t pshufdImm = 0x63;
4838 const Dqword pshufdExpected(uint64_t(0xBBBBBBBBCCCCCCCCull),
4839 uint64_t(0xAAAAAAAADDDDDDDDull));
4840
4841 const uint8_t shufpsImm = 0xf9;
4842 const Dqword shufpsExpected(uint64_t(0x7777777711111111ull),
4843 uint64_t(0xCCCCCCCCCCCCCCCCull));
4844 const Dqword shufpsUntypedExpected(uint64_t(0x7777777711111111ull),
4845 uint64_t(0xCCCCCCCCCCCCCCCCull));
4846
4847 const uint8_t shufpdImm = 0x02;
4848 const Dqword shufpdUntypedExpected(uint64_t(0x1111111122222222ull),
4849 uint64_t(0xCCCCCCCCDDDDDDDDull));
4850
4851 #define TestImplSingleXmmXmm(Dst, Src, Inst) \
4852 do { \
4853 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4854 const uint32_t T0 = allocateDqword(); \
4855 const uint32_t T1 = allocateDqword(); \
4856 \
4857 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4858 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4859 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
4860 Immediate(Inst##Imm)); \
4861 \
4862 AssembledTest test = assemble(); \
4863 test.setDqwordTo(T0, V0); \
4864 test.setDqwordTo(T1, V1); \
4865 test.run(); \
4866 \
4867 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4868 reset(); \
4869 } while (0)
4870
4871 #define TestImplSingleXmmAddr(Dst, Inst) \
4872 do { \
4873 static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \
4874 const uint32_t T0 = allocateDqword(); \
4875 const uint32_t T1 = allocateDqword(); \
4876 \
4877 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4878 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
4879 Immediate(Inst##Imm)); \
4880 \
4881 AssembledTest test = assemble(); \
4882 test.setDqwordTo(T0, V0); \
4883 test.setDqwordTo(T1, V1); \
4884 test.run(); \
4885 \
4886 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4887 reset(); \
4888 } while (0)
4889
4890 #define TestImplSingleXmmXmmUntyped(Dst, Src, Inst) \
4891 do { \
4892 static constexpr char TestString[] = \
4893 "(" #Dst ", " #Src ", " #Inst ", Untyped)"; \
4894 const uint32_t T0 = allocateDqword(); \
4895 const uint32_t T1 = allocateDqword(); \
4896 \
4897 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4898 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4899 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Immediate(Inst##Imm)); \
4900 \
4901 AssembledTest test = assemble(); \
4902 test.setDqwordTo(T0, V0); \
4903 test.setDqwordTo(T1, V1); \
4904 test.run(); \
4905 \
4906 ASSERT_EQ(Inst##UntypedExpected, test.Dst<Dqword>()) << TestString; \
4907 reset(); \
4908 } while (0)
4909
4910 #define TestImpl(Dst, Src) \
4911 do { \
4912 TestImplSingleXmmXmm(Dst, Src, pshufd); \
4913 TestImplSingleXmmAddr(Dst, pshufd); \
4914 TestImplSingleXmmXmm(Dst, Src, shufps); \
4915 TestImplSingleXmmAddr(Dst, shufps); \
4916 TestImplSingleXmmXmmUntyped(Dst, Src, shufps); \
4917 TestImplSingleXmmXmmUntyped(Dst, Src, shufpd); \
4918 } while (0)
4919
4920 TestImpl(xmm0, xmm1);
4921 TestImpl(xmm1, xmm2);
4922 TestImpl(xmm2, xmm3);
4923 TestImpl(xmm3, xmm4);
4924 TestImpl(xmm4, xmm5);
4925 TestImpl(xmm5, xmm6);
4926 TestImpl(xmm6, xmm7);
4927 TestImpl(xmm7, xmm8);
4928 TestImpl(xmm8, xmm9);
4929 TestImpl(xmm9, xmm10);
4930 TestImpl(xmm10, xmm11);
4931 TestImpl(xmm11, xmm12);
4932 TestImpl(xmm12, xmm13);
4933 TestImpl(xmm13, xmm14);
4934 TestImpl(xmm14, xmm15);
4935 TestImpl(xmm15, xmm0);
4936
4937 #undef TestImpl
4938 #undef TestImplSingleXmmXmmUntyped
4939 #undef TestImplSingleXmmAddr
4940 #undef TestImplSingleXmmXmm
4941 }
4942
4943 TEST_F(AssemblerX8664Test, Cvt) {
4944 const Dqword dq2ps32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4945 const Dqword dq2ps32SrcValue(-5, 3, 100, 200);
4946 const Dqword dq2ps32Expected(-5.0f, 3.0f, 100.0, 200.0);
4947
4948 const Dqword dq2ps64DstValue(0.0f, 0.0f, -1.0f, -1.0f);
4949 const Dqword dq2ps64SrcValue(-5, 3, 100, 200);
4950 const Dqword dq2ps64Expected(-5.0f, 3.0f, 100.0, 200.0);
4951
4952 const Dqword tps2dq32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4953 const Dqword tps2dq32SrcValue(-5.0f, 3.0f, 100.0, 200.0);
4954 const Dqword tps2dq32Expected(-5, 3, 100, 200);
4955
4956 const Dqword tps2dq64DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4957 const Dqword tps2dq64SrcValue(-5.0f, 3.0f, 100.0, 200.0);
4958 const Dqword tps2dq64Expected(-5, 3, 100, 200);
4959
4960 const Dqword si2ss32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4961 const int32_t si2ss32SrcValue = 5;
4962 const Dqword si2ss32Expected(5.0f, -1.0f, -1.0f, -1.0f);
4963
4964 const Dqword si2ss64DstValue(-1.0, -1.0);
4965 const int32_t si2ss64SrcValue = 5;
4966 const Dqword si2ss64Expected(5.0, -1.0);
4967
4968 const int32_t tss2si32DstValue = 0xF00F0FF0;
4969 const Dqword tss2si32SrcValue(-5.0f, -1.0f, -1.0f, -1.0f);
4970 const int32_t tss2si32Expected = -5;
4971
4972 const int32_t tss2si64DstValue = 0xF00F0FF0;
4973 const Dqword tss2si64SrcValue(-5.0, -1.0);
4974 const int32_t tss2si64Expected = -5;
4975
4976 const Dqword float2float32DstValue(-1.0, -1.0);
4977 const Dqword float2float32SrcValue(-5.0, 3, 100, 200);
4978 const Dqword float2float32Expected(-5.0, -1.0);
4979
4980 const Dqword float2float64DstValue(-1.0, -1.0, -1.0, -1.0);
4981 const Dqword float2float64SrcValue(-5.0, 3.0);
4982 const Dqword float2float64Expected(-5.0, -1.0, -1.0, -1.0);
4983
4984 #define TestImplPXmmXmm(Dst, Src, Inst, Size) \
4985 do { \
4986 static constexpr char TestString[] = \
4987 "(" #Dst ", " #Src ", cvt" #Inst ", f" #Size ")"; \
4988 const uint32_t T0 = allocateDqword(); \
4989 const uint32_t T1 = allocateDqword(); \
4990 \
4991 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4992 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4993 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4994 \
4995 AssembledTest test = assemble(); \
4996 test.setDqwordTo(T0, Inst##Size##DstValue); \
4997 test.setDqwordTo(T1, Inst##Size##SrcValue); \
4998 test.run(); \
4999 \
5000 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5001 reset(); \
5002 } while (0)
5003
5004 #define TestImplSXmmReg(Dst, GPR, Inst, Size) \
5005 do { \
5006 static constexpr char TestString[] = \
5007 "(" #Dst ", " #GPR ", cvt" #Inst ", f" #Size ")"; \
5008 const uint32_t T0 = allocateDqword(); \
5009 \
5010 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5011 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##SrcValue)); \
5012 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_GPR_##GPR()); \
5013 \
5014 AssembledTest test = assemble(); \
5015 test.setDqwordTo(T0, Inst##Size##DstValue); \
5016 test.run(); \
5017 \
5018 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5019 reset(); \
5020 } while (0)
5021
5022 #define TestImplSRegXmm(GPR, Src, Inst, Size) \
5023 do { \
5024 static constexpr char TestString[] = \
5025 "(" #GPR ", " #Src ", cvt" #Inst ", f" #Size ")"; \
5026 const uint32_t T0 = allocateDqword(); \
5027 \
5028 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
5029 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5030 __ cvt##Inst(IceType_f##Size, Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \
5031 \
5032 AssembledTest test = assemble(); \
5033 test.setDqwordTo(T0, Inst##Size##SrcValue); \
5034 test.run(); \
5035 \
5036 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
5037 << TestString; \
5038 reset(); \
5039 } while (0)
5040
5041 #define TestImplPXmmAddr(Dst, Inst, Size) \
5042 do { \
5043 static constexpr char TestString[] = \
5044 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
5045 const uint32_t T0 = allocateDqword(); \
5046 const uint32_t T1 = allocateDqword(); \
5047 \
5048 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5049 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5050 \
5051 AssembledTest test = assemble(); \
5052 test.setDqwordTo(T0, Inst##Size##DstValue); \
5053 test.setDqwordTo(T1, Inst##Size##SrcValue); \
5054 test.run(); \
5055 \
5056 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5057 reset(); \
5058 } while (0)
5059
5060 #define TestImplSXmmAddr(Dst, Inst, Size) \
5061 do { \
5062 static constexpr char TestString[] = \
5063 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
5064 const uint32_t T0 = allocateDqword(); \
5065 const uint32_t T1 = allocateDword(); \
5066 \
5067 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5068 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5069 \
5070 AssembledTest test = assemble(); \
5071 test.setDqwordTo(T0, Inst##Size##DstValue); \
5072 test.setDwordTo(T1, Inst##Size##SrcValue); \
5073 test.run(); \
5074 \
5075 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5076 reset(); \
5077 } while (0)
5078
5079 #define TestImplSRegAddr(GPR, Inst, Size) \
5080 do { \
5081 static constexpr char TestString[] = \
5082 "(" #GPR ", Addr, cvt" #Inst ", f" #Size ")"; \
5083 const uint32_t T0 = allocateDqword(); \
5084 \
5085 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
5086 __ cvt##Inst(IceType_f##Size, Encoded_GPR_##GPR(), dwordAddress(T0)); \
5087 \
5088 AssembledTest test = assemble(); \
5089 test.setDqwordTo(T0, Inst##Size##SrcValue); \
5090 test.run(); \
5091 \
5092 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
5093 << TestString; \
5094 reset(); \
5095 } while (0)
5096
5097 #define TestImplSize(Dst, Src, GPR, Size) \
5098 do { \
5099 TestImplPXmmXmm(Dst, Src, dq2ps, Size); \
5100 TestImplPXmmAddr(Src, dq2ps, Size); \
5101 TestImplPXmmXmm(Dst, Src, tps2dq, Size); \
5102 TestImplPXmmAddr(Src, tps2dq, Size); \
5103 TestImplSXmmReg(Dst, GPR, si2ss, Size); \
5104 TestImplSXmmAddr(Dst, si2ss, Size); \
5105 TestImplSRegXmm(GPR, Src, tss2si, Size); \
5106 TestImplSRegAddr(GPR, tss2si, Size); \
5107 TestImplPXmmXmm(Dst, Src, float2float, Size); \
5108 TestImplPXmmAddr(Src, float2float, Size); \
5109 } while (0)
5110
5111 #define TestImpl(Dst, Src, GPR) \
5112 do { \
5113 TestImplSize(Dst, Src, GPR, 32); \
5114 TestImplSize(Dst, Src, GPR, 64); \
5115 } while (0)
5116
5117 TestImpl(xmm0, xmm1, r1);
5118 TestImpl(xmm1, xmm2, r2);
5119 TestImpl(xmm2, xmm3, r3);
5120 TestImpl(xmm3, xmm4, r4);
5121 TestImpl(xmm4, xmm5, r5);
5122 TestImpl(xmm5, xmm6, r6);
5123 TestImpl(xmm6, xmm7, r7);
5124 TestImpl(xmm7, xmm8, r8);
5125 TestImpl(xmm8, xmm9, r10);
5126 TestImpl(xmm9, xmm10, r11);
5127 TestImpl(xmm10, xmm11, r12);
5128 TestImpl(xmm11, xmm12, r13);
5129 TestImpl(xmm12, xmm13, r14);
5130 TestImpl(xmm13, xmm14, r15);
5131 TestImpl(xmm14, xmm15, r1);
5132 TestImpl(xmm15, xmm0, r2);
5133
5134 #undef TestImpl
5135 #undef TestImplSize
5136 #undef TestImplSRegAddr
5137 #undef TestImplSXmmAddr
5138 #undef TestImplPXmmAddr
5139 #undef TestImplSRegXmm
5140 #undef TestImplSXmmReg
5141 #undef TestImplPXmmXmm
5142 }
5143
5144 TEST_F(AssemblerX8664Test, Ucomiss) {
5145 static constexpr float qnan32 = std::numeric_limits<float>::quiet_NaN();
5146 static constexpr double qnan64 = std::numeric_limits<float>::quiet_NaN();
5147
5148 Dqword test32DstValue(0.0, qnan32, qnan32, qnan32);
5149 Dqword test32SrcValue(0.0, qnan32, qnan32, qnan32);
5150
5151 Dqword test64DstValue(0.0, qnan64);
5152 Dqword test64SrcValue(0.0, qnan64);
5153
5154 #define TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, \
5155 BOther) \
5156 do { \
5157 static constexpr char NearBranch = AssemblerX8664::kNearJump; \
5158 static constexpr char TestString[] = \
5159 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #CompType \
5160 ", " #BParity ", " #BOther ")"; \
5161 const uint32_t T0 = allocateDqword(); \
5162 test##Size##DstValue.F##Size[0] = Value0; \
5163 const uint32_t T1 = allocateDqword(); \
5164 test##Size##SrcValue.F##Size[0] = Value1; \
5165 const uint32_t ImmIfTrue = 0xBEEF; \
5166 const uint32_t ImmIfFalse = 0xC0FFE; \
5167 \
5168 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5169 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5170 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
5171 __ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5172 Label Done; \
5173 __ j(Cond::Br_##BParity, &Done, NearBranch); \
5174 __ j(Cond::Br_##BOther, &Done, NearBranch); \
5175 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
5176 __ bind(&Done); \
5177 \
5178 AssembledTest test = assemble(); \
5179 test.setDqwordTo(T0, test##Size##DstValue); \
5180 test.setDqwordTo(T1, test##Size##SrcValue); \
5181 test.run(); \
5182 \
5183 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
5184 reset(); \
5185 } while (0)
5186
5187 #define TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther) \
5188 do { \
5189 static constexpr char NearBranch = AssemblerX8664::kNearJump; \
5190 static constexpr char TestString[] = \
5191 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #CompType \
5192 ", " #BParity ", " #BOther ")"; \
5193 const uint32_t T0 = allocateDqword(); \
5194 test##Size##DstValue.F##Size[0] = Value0; \
5195 const uint32_t T1 = allocateDqword(); \
5196 test##Size##SrcValue.F##Size[0] = Value1; \
5197 const uint32_t ImmIfTrue = 0xBEEF; \
5198 const uint32_t ImmIfFalse = 0xC0FFE; \
5199 \
5200 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5201 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
5202 __ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5203 Label Done; \
5204 __ j(Cond::Br_##BParity, &Done, NearBranch); \
5205 __ j(Cond::Br_##BOther, &Done, NearBranch); \
5206 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
5207 __ bind(&Done); \
5208 \
5209 AssembledTest test = assemble(); \
5210 test.setDqwordTo(T0, test##Size##DstValue); \
5211 test.setDqwordTo(T1, test##Size##SrcValue); \
5212 test.run(); \
5213 \
5214 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
5215 reset(); \
5216 } while (0)
5217
5218 #define TestImplCond(Dst, Value0, Src, Value1, Size, CompType, BParity, \
5219 BOther) \
5220 do { \
5221 TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, BOther); \
5222 TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther); \
5223 } while (0)
5224
5225 #define TestImplSize(Dst, Src, Size) \
5226 do { \
5227 TestImplCond(Dst, 1.0, Src, 1.0, Size, isEq, p, ne); \
5228 TestImplCond(Dst, 1.0, Src, 2.0, Size, isNe, p, e); \
5229 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLe, p, a); \
5230 TestImplCond(Dst, 1.0, Src, 1.0, Size, isLe, p, a); \
5231 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLt, p, ae); \
5232 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGe, p, b); \
5233 TestImplCond(Dst, 1.0, Src, 1.0, Size, isGe, p, b); \
5234 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGt, p, be); \
5235 TestImplCond(Dst, qnan##Size, Src, 1.0, Size, isUnord, np, o); \
5236 TestImplCond(Dst, 1.0, Src, qnan##Size, Size, isUnord, np, s); \
5237 TestImplCond(Dst, qnan##Size, Src, qnan##Size, Size, isUnord, np, s); \
5238 } while (0)
5239
5240 #define TestImpl(Dst, Src) \
5241 do { \
5242 TestImplSize(Dst, Src, 32); \
5243 TestImplSize(Dst, Src, 64); \
5244 } while (0)
5245
5246 TestImpl(xmm0, xmm1);
5247 TestImpl(xmm1, xmm2);
5248 TestImpl(xmm2, xmm3);
5249 TestImpl(xmm3, xmm4);
5250 TestImpl(xmm4, xmm5);
5251 TestImpl(xmm5, xmm6);
5252 TestImpl(xmm6, xmm7);
5253 TestImpl(xmm7, xmm8);
5254 TestImpl(xmm8, xmm9);
5255 TestImpl(xmm9, xmm10);
5256 TestImpl(xmm10, xmm11);
5257 TestImpl(xmm11, xmm12);
5258 TestImpl(xmm12, xmm13);
5259 TestImpl(xmm13, xmm14);
5260 TestImpl(xmm14, xmm15);
5261 TestImpl(xmm15, xmm0);
5262
5263 #undef TestImpl
5264 #undef TestImplSize
5265 #undef TestImplCond
5266 #undef TestImplXmmAddr
5267 #undef TestImplXmmXmm
5268 }
5269
5270 TEST_F(AssemblerX8664Test, Movmsk) {
5271 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \
5272 do { \
5273 static constexpr char TestString[] = \
5274 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \
5275 const uint32_t T0 = allocateDqword(); \
5276 const Dqword V0 Value1; \
5277 \
5278 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5279 __ Inst(Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \
5280 \
5281 AssembledTest test = assemble(); \
5282 test.setDqwordTo(T0, V0); \
5283 test.run(); \
5284 \
5285 ASSERT_EQ(Expected, test.GPR()) << TestString; \
5286 reset(); \
5287 } while (0)
5288
5289 #define TestMovmsk(GPR, Src) \
5290 do { \
5291 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmskps); \
5292 TestMovmskGPRXmm(GPR, Src, (1.0, -1.0), 0x02ul, movmskpd); \
5293 } while (0)
5294
5295 TestMovmsk(r1, xmm0);
5296 TestMovmsk(r2, xmm1);
5297 TestMovmsk(r3, xmm2);
5298 TestMovmsk(r4, xmm3);
5299 TestMovmsk(r5, xmm4);
5300 TestMovmsk(r6, xmm5);
5301 TestMovmsk(r7, xmm6);
5302 TestMovmsk(r8, xmm7);
5303 TestMovmsk(r10, xmm8);
5304 TestMovmsk(r11, xmm9);
5305 TestMovmsk(r12, xmm10);
5306 TestMovmsk(r13, xmm11);
5307 TestMovmsk(r14, xmm12);
5308 TestMovmsk(r15, xmm13);
5309 TestMovmsk(r1, xmm14);
5310 TestMovmsk(r2, xmm15);
5311
5312 #undef TestMovmskGPRXmm
5313 #undef TestMovmsk
5314 }
5315
5316 TEST_F(AssemblerX8664Test, Sqrtss) {
5317 Dqword test32SrcValue(-100.0, -100.0, -100.0, -100.0);
5318 Dqword test32DstValue(-1.0, -1.0, -1.0, -1.0);
5319
5320 Dqword test64SrcValue(-100.0, -100.0);
5321 Dqword test64DstValue(-1.0, -1.0);
5322
5323 #define TestSqrtssXmmXmm(Dst, Src, Value1, Result, Size) \
5324 do { \
5325 static constexpr char TestString[] = \
5326 "(" #Dst ", " #Src ", " #Value1 ", " #Result ", " #Size ")"; \
5327 const uint32_t T0 = allocateDqword(); \
5328 test##Size##SrcValue.F##Size[0] = Value1; \
5329 const uint32_t T1 = allocateDqword(); \
5330 \
5331 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5332 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5333 __ sqrtss(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5334 \
5335 AssembledTest test = assemble(); \
5336 test.setDqwordTo(T0, test##Size##SrcValue); \
5337 test.setDqwordTo(T1, test##Size##DstValue); \
5338 test.run(); \
5339 \
5340 Dqword Expected = test##Size##DstValue; \
5341 Expected.F##Size[0] = Result; \
5342 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5343 reset(); \
5344 } while (0)
5345
5346 #define TestSqrtssXmmAddr(Dst, Value1, Result, Size) \
5347 do { \
5348 static constexpr char TestString[] = \
5349 "(" #Dst ", Addr, " #Value1 ", " #Result ", " #Size ")"; \
5350 const uint32_t T0 = allocateDqword(); \
5351 test##Size##SrcValue.F##Size[0] = Value1; \
5352 const uint32_t T1 = allocateDqword(); \
5353 \
5354 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5355 __ sqrtss(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5356 \
5357 AssembledTest test = assemble(); \
5358 test.setDqwordTo(T0, test##Size##SrcValue); \
5359 test.setDqwordTo(T1, test##Size##DstValue); \
5360 test.run(); \
5361 \
5362 Dqword Expected = test##Size##DstValue; \
5363 Expected.F##Size[0] = Result; \
5364 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5365 reset(); \
5366 } while (0)
5367
5368 #define TestSqrtssSize(Dst, Src, Size) \
5369 do { \
5370 TestSqrtssXmmXmm(Dst, Src, 4.0, 2.0, Size); \
5371 TestSqrtssXmmAddr(Dst, 4.0, 2.0, Size); \
5372 TestSqrtssXmmXmm(Dst, Src, 9.0, 3.0, Size); \
5373 TestSqrtssXmmAddr(Dst, 9.0, 3.0, Size); \
5374 TestSqrtssXmmXmm(Dst, Src, 100.0, 10.0, Size); \
5375 TestSqrtssXmmAddr(Dst, 100.0, 10.0, Size); \
5376 } while (0)
5377
5378 #define TestSqrtss(Dst, Src) \
5379 do { \
5380 TestSqrtssSize(Dst, Src, 32); \
5381 TestSqrtssSize(Dst, Src, 64); \
5382 } while (0)
5383
5384 TestSqrtss(xmm0, xmm1);
5385 TestSqrtss(xmm1, xmm2);
5386 TestSqrtss(xmm2, xmm3);
5387 TestSqrtss(xmm3, xmm4);
5388 TestSqrtss(xmm4, xmm5);
5389 TestSqrtss(xmm5, xmm6);
5390 TestSqrtss(xmm6, xmm7);
5391 TestSqrtss(xmm7, xmm8);
5392 TestSqrtss(xmm8, xmm9);
5393 TestSqrtss(xmm9, xmm10);
5394 TestSqrtss(xmm10, xmm11);
5395 TestSqrtss(xmm11, xmm12);
5396 TestSqrtss(xmm12, xmm13);
5397 TestSqrtss(xmm13, xmm14);
5398 TestSqrtss(xmm14, xmm15);
5399 TestSqrtss(xmm15, xmm0);
5400
5401 #undef TestSqrtss
5402 #undef TestSqrtssSize
5403 #undef TestSqrtssXmmAddr
5404 #undef TestSqrtssXmmXmm
5405 }
5406
5407 TEST_F(AssemblerX8664Test, Insertps) {
5408 #define TestInsertpsXmmXmmImm(Dst, Value0, Src, Value1, Imm, Expected) \
5409 do { \
5410 static constexpr char TestString[] = \
5411 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Imm ", " #Expected \
5412 ")"; \
5413 const uint32_t T0 = allocateDqword(); \
5414 const Dqword V0 Value0; \
5415 const uint32_t T1 = allocateDqword(); \
5416 const Dqword V1 Value1; \
5417 \
5418 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5419 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5420 __ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
5421 Immediate(Imm)); \
5422 \
5423 AssembledTest test = assemble(); \
5424 test.setDqwordTo(T0, V0); \
5425 test.setDqwordTo(T1, V1); \
5426 test.run(); \
5427 \
5428 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
5429 reset(); \
5430 } while (0)
5431
5432 #define TestInsertpsXmmAddrImm(Dst, Value0, Value1, Imm, Expected) \
5433 do { \
5434 static constexpr char TestString[] = \
5435 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Expected ")"; \
5436 const uint32_t T0 = allocateDqword(); \
5437 const Dqword V0 Value0; \
5438 const uint32_t T1 = allocateDqword(); \
5439 const Dqword V1 Value1; \
5440 \
5441 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5442 __ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
5443 Immediate(Imm)); \
5444 \
5445 AssembledTest test = assemble(); \
5446 test.setDqwordTo(T0, V0); \
5447 test.setDqwordTo(T1, V1); \
5448 test.run(); \
5449 \
5450 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
5451 reset(); \
5452 } while (0)
5453
5454 #define TestInsertps(Dst, Src) \
5455 do { \
5456 TestInsertpsXmmXmmImm( \
5457 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
5458 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5459 0x99, \
5460 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
5461 TestInsertpsXmmAddrImm( \
5462 Dst, (uint64_t(-1), uint64_t(-1)), \
5463 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5464 0x99, \
5465 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
5466 TestInsertpsXmmXmmImm( \
5467 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
5468 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5469 0x9D, \
5470 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x0000000000000000ull))); \
5471 TestInsertpsXmmAddrImm( \
5472 Dst, (uint64_t(-1), uint64_t(-1)), \
5473 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5474 0x9D, \
5475 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x0000000000000000ull))); \
5476 } while (0)
5477
5478 TestInsertps(xmm0, xmm1);
5479 TestInsertps(xmm1, xmm2);
5480 TestInsertps(xmm2, xmm3);
5481 TestInsertps(xmm3, xmm4);
5482 TestInsertps(xmm4, xmm5);
5483 TestInsertps(xmm5, xmm6);
5484 TestInsertps(xmm6, xmm7);
5485 TestInsertps(xmm7, xmm8);
5486 TestInsertps(xmm8, xmm9);
5487 TestInsertps(xmm9, xmm10);
5488 TestInsertps(xmm10, xmm11);
5489 TestInsertps(xmm11, xmm12);
5490 TestInsertps(xmm12, xmm13);
5491 TestInsertps(xmm13, xmm14);
5492 TestInsertps(xmm14, xmm15);
5493 TestInsertps(xmm15, xmm0);
5494
5495 #undef TestInsertps
5496 #undef TestInsertpsXmmXmmAddr
5497 #undef TestInsertpsXmmXmmImm
5498 }
5499
5500 TEST_F(AssemblerX8664Test, Pinsr) {
5501 static constexpr uint8_t Mask32 = 0x03;
5502 static constexpr uint8_t Mask16 = 0x07;
5503 static constexpr uint8_t Mask8 = 0x0F;
5504
5505 #define TestPinsrXmmGPRImm(Dst, Value0, GPR, Value1, Imm, Size) \
5506 do { \
5507 static constexpr char TestString[] = \
5508 "(" #Dst ", " #Value0 ", " #GPR ", " #Value1 ", " #Imm ", " #Size ")"; \
5509 const uint32_t T0 = allocateDqword(); \
5510 const Dqword V0 Value0; \
5511 \
5512 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5513 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Value1)); \
5514 __ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_GPR_##GPR(), \
5515 Immediate(Imm)); \
5516 \
5517 AssembledTest test = assemble(); \
5518 test.setDqwordTo(T0, V0); \
5519 test.run(); \
5520 \
5521 constexpr uint8_t sel = (Imm)&Mask##Size; \
5522 Dqword Expected = V0; \
5523 Expected.U##Size[sel] = Value1; \
5524 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5525 reset(); \
5526 } while (0)
5527
5528 #define TestPinsrXmmAddrImm(Dst, Value0, Value1, Imm, Size) \
5529 do { \
5530 static constexpr char TestString[] = \
5531 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Size ")"; \
5532 const uint32_t T0 = allocateDqword(); \
5533 const Dqword V0 Value0; \
5534 const uint32_t T1 = allocateDword(); \
5535 const uint32_t V1 = Value1; \
5536 \
5537 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5538 __ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1), \
5539 Immediate(Imm)); \
5540 \
5541 AssembledTest test = assemble(); \
5542 test.setDqwordTo(T0, V0); \
5543 test.setDwordTo(T1, V1); \
5544 test.run(); \
5545 \
5546 constexpr uint8_t sel = (Imm)&Mask##Size; \
5547 Dqword Expected = V0; \
5548 Expected.U##Size[sel] = Value1; \
5549 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5550 reset(); \
5551 } while (0)
5552
5553 #define TestPinsrSize(Dst, GPR, Value1, Imm, Size) \
5554 do { \
5555 TestPinsrXmmGPRImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5556 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5557 GPR, Value1, Imm, Size); \
5558 TestPinsrXmmAddrImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5559 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5560 Value1, Imm, Size); \
5561 } while (0)
5562
5563 #define TestPinsr(Src, Dst) \
5564 do { \
5565 TestPinsrSize(Src, Dst, 0xEE, 0x03, 8); \
5566 TestPinsrSize(Src, Dst, 0xFFEE, 0x03, 16); \
5567 TestPinsrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
5568 } while (0)
5569
5570 TestPinsr(xmm0, r1);
5571 TestPinsr(xmm1, r2);
5572 TestPinsr(xmm2, r3);
5573 TestPinsr(xmm3, r4);
5574 TestPinsr(xmm4, r5);
5575 TestPinsr(xmm5, r6);
5576 TestPinsr(xmm6, r7);
5577 TestPinsr(xmm7, r8);
5578 TestPinsr(xmm8, r10);
5579 TestPinsr(xmm9, r11);
5580 TestPinsr(xmm10, r12);
5581 TestPinsr(xmm11, r13);
5582 TestPinsr(xmm12, r14);
5583 TestPinsr(xmm13, r15);
5584 TestPinsr(xmm14, r1);
5585 TestPinsr(xmm15, r2);
5586
5587 #undef TestPinsr
5588 #undef TestPinsrSize
5589 #undef TestPinsrXmmAddrImm
5590 #undef TestPinsrXmmGPRImm
5591 }
5592
5593 TEST_F(AssemblerX8664Test, Pextr) {
5594 static constexpr uint8_t Mask32 = 0x03;
5595 static constexpr uint8_t Mask16 = 0x07;
5596 static constexpr uint8_t Mask8 = 0x0F;
5597
5598 #define TestPextrGPRXmmImm(GPR, Src, Value1, Imm, Size) \
5599 do { \
5600 static constexpr char TestString[] = \
5601 "(" #GPR ", " #Src ", " #Value1 ", " #Imm ", " #Size ")"; \
5602 const uint32_t T0 = allocateDqword(); \
5603 const Dqword V0 Value1; \
5604 \
5605 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5606 __ pextr(IceType_i##Size, Encoded_GPR_##GPR(), Encoded_Xmm_##Src(), \
5607 Immediate(Imm)); \
5608 \
5609 AssembledTest test = assemble(); \
5610 test.setDqwordTo(T0, V0); \
5611 test.run(); \
5612 \
5613 constexpr uint8_t sel = (Imm)&Mask##Size; \
5614 ASSERT_EQ(V0.U##Size[sel], test.GPR()) << TestString; \
5615 reset(); \
5616 } while (0)
5617
5618 #define TestPextrSize(GPR, Src, Value1, Imm, Size) \
5619 do { \
5620 TestPextrGPRXmmImm(GPR, Src, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5621 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5622 Imm, Size); \
5623 } while (0)
5624
5625 #define TestPextr(Src, Dst) \
5626 do { \
5627 TestPextrSize(Src, Dst, 0xEE, 0x03, 8); \
5628 TestPextrSize(Src, Dst, 0xFFEE, 0x03, 16); \
5629 TestPextrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
5630 } while (0)
5631
5632 TestPextr(r1, xmm0);
5633 TestPextr(r2, xmm1);
5634 TestPextr(r3, xmm2);
5635 TestPextr(r4, xmm3);
5636 TestPextr(r5, xmm4);
5637 TestPextr(r6, xmm5);
5638 TestPextr(r7, xmm6);
5639 TestPextr(r8, xmm7);
5640 TestPextr(r10, xmm8);
5641 TestPextr(r11, xmm9);
5642 TestPextr(r12, xmm10);
5643 TestPextr(r13, xmm11);
5644 TestPextr(r14, xmm12);
5645 TestPextr(r15, xmm13);
5646 TestPextr(r1, xmm14);
5647 TestPextr(r2, xmm15);
5648
5649 #undef TestPextr
5650 #undef TestPextrSize
5651 #undef TestPextrXmmGPRImm
5652 }
5653
5654 TEST_F(AssemblerX8664Test, Pmovsxdq) {
5655 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \
5656 do { \
5657 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \
5658 const uint32_t T0 = allocateDqword(); \
5659 const Dqword V0 Value1; \
5660 const uint32_t T1 = allocateDqword(); \
5661 const Dqword V1(uint64_t(0), uint64_t(0)); \
5662 \
5663 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5664 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5665 __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5666 \
5667 AssembledTest test = assemble(); \
5668 test.setDqwordTo(T0, V0); \
5669 test.setDqwordTo(T1, V1); \
5670 test.run(); \
5671 \
5672 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \
5673 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5674 reset(); \
5675 } while (0)
5676
5677 #define TestPmovsxdq(Dst, Src) \
5678 do { \
5679 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \
5680 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5681 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \
5682 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5683 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \
5684 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5685 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \
5686 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5687 } while (0)
5688
5689 TestPmovsxdq(xmm0, xmm1);
5690 TestPmovsxdq(xmm1, xmm2);
5691 TestPmovsxdq(xmm2, xmm3);
5692 TestPmovsxdq(xmm3, xmm4);
5693 TestPmovsxdq(xmm4, xmm5);
5694 TestPmovsxdq(xmm5, xmm6);
5695 TestPmovsxdq(xmm6, xmm7);
5696 TestPmovsxdq(xmm7, xmm8);
5697 TestPmovsxdq(xmm8, xmm9);
5698 TestPmovsxdq(xmm9, xmm10);
5699 TestPmovsxdq(xmm10, xmm11);
5700 TestPmovsxdq(xmm11, xmm12);
5701 TestPmovsxdq(xmm12, xmm13);
5702 TestPmovsxdq(xmm13, xmm14);
5703 TestPmovsxdq(xmm14, xmm15);
5704 TestPmovsxdq(xmm15, xmm0);
5705
5706 #undef TestPmovsxdq
5707 #undef TestPmovsxdqXmmXmm
5708 }
5709
5710 TEST_F(AssemblerX8664Test, Pcmpeq_Pcmpgt) {
5711 #define TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, Inst, Op) \
5712 do { \
5713 static constexpr char TestString[] = \
5714 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #Op ")"; \
5715 const uint32_t T0 = allocateDqword(); \
5716 const Dqword V0 Value0; \
5717 const uint32_t T1 = allocateDqword(); \
5718 const Dqword V1 Value1; \
5719 \
5720 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5721 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5722 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5723 \
5724 AssembledTest test = assemble(); \
5725 test.setDqwordTo(T0, V0); \
5726 test.setDqwordTo(T1, V1); \
5727 test.run(); \
5728 \
5729 Dqword Expected(uint64_t(0), uint64_t(0)); \
5730 static constexpr uint8_t ArraySize = \
5731 sizeof(Dqword) / sizeof(uint##Size##_t); \
5732 for (uint8_t i = 0; i < ArraySize; ++i) { \
5733 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
5734 } \
5735 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5736 reset(); \
5737 } while (0)
5738
5739 #define TestPcmpXmmAddr(Dst, Value0, Value1, Size, Inst, Op) \
5740 do { \
5741 static constexpr char TestString[] = \
5742 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #Op ")"; \
5743 const uint32_t T0 = allocateDqword(); \
5744 const Dqword V0 Value0; \
5745 const uint32_t T1 = allocateDqword(); \
5746 const Dqword V1 Value1; \
5747 \
5748 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5749 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5750 \
5751 AssembledTest test = assemble(); \
5752 test.setDqwordTo(T0, V0); \
5753 test.setDqwordTo(T1, V1); \
5754 test.run(); \
5755 \
5756 Dqword Expected(uint64_t(0), uint64_t(0)); \
5757 static constexpr uint8_t ArraySize = \
5758 sizeof(Dqword) / sizeof(uint##Size##_t); \
5759 for (uint8_t i = 0; i < ArraySize; ++i) { \
5760 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
5761 } \
5762 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5763 reset(); \
5764 } while (0)
5765
5766 #define TestPcmpValues(Dst, Value0, Src, Value1, Size) \
5767 do { \
5768 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpeq, == ); \
5769 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpeq, == ); \
5770 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpgt, < ); \
5771 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpgt, < ); \
5772 } while (0)
5773
5774 #define TestPcmpSize(Dst, Src, Size) \
5775 do { \
5776 TestPcmpValues(Dst, (uint64_t(0x8888888888888888ull), \
5777 uint64_t(0x0000000000000000ull)), \
5778 Src, (uint64_t(0x0000008800008800ull), \
5779 uint64_t(0xFFFFFFFFFFFFFFFFull)), \
5780 Size); \
5781 TestPcmpValues(Dst, (uint64_t(0x123567ABAB55DE01ull), \
5782 uint64_t(0x12345abcde12345Aull)), \
5783 Src, (uint64_t(0x0000008800008800ull), \
5784 uint64_t(0xAABBCCDD1234321Aull)), \
5785 Size); \
5786 } while (0)
5787
5788 #define TestPcmp(Dst, Src) \
5789 do { \
5790 TestPcmpSize(xmm0, xmm1, 8); \
5791 TestPcmpSize(xmm0, xmm1, 16); \
5792 TestPcmpSize(xmm0, xmm1, 32); \
5793 } while (0)
5794
5795 TestPcmp(xmm0, xmm1);
5796 TestPcmp(xmm1, xmm2);
5797 TestPcmp(xmm2, xmm3);
5798 TestPcmp(xmm3, xmm4);
5799 TestPcmp(xmm4, xmm5);
5800 TestPcmp(xmm5, xmm6);
5801 TestPcmp(xmm6, xmm7);
5802 TestPcmp(xmm7, xmm8);
5803 TestPcmp(xmm8, xmm9);
5804 TestPcmp(xmm9, xmm10);
5805 TestPcmp(xmm10, xmm11);
5806 TestPcmp(xmm11, xmm12);
5807 TestPcmp(xmm12, xmm13);
5808 TestPcmp(xmm13, xmm14);
5809 TestPcmp(xmm14, xmm15);
5810 TestPcmp(xmm15, xmm0);
5811
5812 #undef TestPcmp
5813 #undef TestPcmpSize
5814 #undef TestPcmpValues
5815 #undef TestPcmpXmmAddr
5816 #undef TestPcmpXmmXmm
5817 }
5818
5819 TEST_F(AssemblerX8664Test, Roundsd) {
5820 #define TestRoundsdXmmXmm(Dst, Src, Mode, Input, RN) \
5821 do { \
5822 static constexpr char TestString[] = \
5823 "(" #Dst ", " #Src ", " #Mode ", " #Input ", " #RN ")"; \
5824 const uint32_t T0 = allocateDqword(); \
5825 const Dqword V0(-3.0, -3.0); \
5826 const uint32_t T1 = allocateDqword(); \
5827 const Dqword V1(double(Input), -123.4); \
5828 \
5829 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5830 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5831 __ roundsd(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
5832 AssemblerX8664::k##Mode); \
5833 \
5834 AssembledTest test = assemble(); \
5835 test.setDqwordTo(T0, V0); \
5836 test.setDqwordTo(T1, V1); \
5837 test.run(); \
5838 \
5839 const Dqword Expected(double(RN), -3.0); \
5840 EXPECT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5841 reset(); \
5842 } while (0)
5843
5844 #define TestRoundsd(Dst, Src) \
5845 do { \
5846 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.51, 6); \
5847 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.49, 5); \
5848 TestRoundsdXmmXmm(Dst, Src, RoundDown, 5.51, 5); \
5849 TestRoundsdXmmXmm(Dst, Src, RoundUp, 5.49, 6); \
5850 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.49, 5); \
5851 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.51, 5); \
5852 } while (0)
5853
5854 TestRoundsd(xmm0, xmm1);
5855 TestRoundsd(xmm1, xmm2);
5856 TestRoundsd(xmm2, xmm3);
5857 TestRoundsd(xmm3, xmm4);
5858 TestRoundsd(xmm4, xmm5);
5859 TestRoundsd(xmm5, xmm6);
5860 TestRoundsd(xmm6, xmm7);
5861 TestRoundsd(xmm7, xmm8);
5862 TestRoundsd(xmm8, xmm9);
5863 TestRoundsd(xmm9, xmm10);
5864 TestRoundsd(xmm10, xmm11);
5865 TestRoundsd(xmm11, xmm12);
5866 TestRoundsd(xmm12, xmm13);
5867 TestRoundsd(xmm13, xmm14);
5868 TestRoundsd(xmm14, xmm15);
5869 TestRoundsd(xmm15, xmm0);
5870
5871 #undef TestRoundsd
5872 #undef TestRoundsdXmmXmm
5873 }
5874
5875 TEST_F(AssemblerX8664Test, Test) {
5876 static constexpr uint32_t Mask8 = 0xFF;
5877 static constexpr uint32_t Mask16 = 0xFFFF;
5878 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
5879
5880 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
5881 do { \
5882 static constexpr bool NearJump = true; \
5883 static constexpr char TestString[] = \
5884 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
5885 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5886 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5887 \
5888 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
5889 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
5890 __ test(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
5891 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
5892 Label Done; \
5893 __ j(Cond::Br_e, &Done, NearJump); \
5894 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
5895 __ bind(&Done); \
5896 \
5897 AssembledTest test = assemble(); \
5898 test.run(); \
5899 \
5900 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5901 : ValueIfFalse, \
5902 test.Dst()) \
5903 << TestString; \
5904 reset(); \
5905 } while (0)
5906
5907 #define TestImplRegImm(Dst, Value0, Imm, Size) \
5908 do { \
5909 static constexpr bool NearJump = true; \
5910 static constexpr char TestString[] = \
5911 "(" #Dst ", " #Value0 ", " #Imm ", " #Size ")"; \
5912 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5913 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5914 \
5915 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
5916 __ test(IceType_i##Size, Encoded_GPR_##Dst(), \
5917 Immediate((Imm)&Mask##Size)); \
5918 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
5919 Label Done; \
5920 __ j(Cond::Br_e, &Done, NearJump); \
5921 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
5922 __ bind(&Done); \
5923 \
5924 AssembledTest test = assemble(); \
5925 test.run(); \
5926 \
5927 ASSERT_EQ(((Value0)&Mask##Size) & ((Imm)&Mask##Size) ? ValueIfTrue \
5928 : ValueIfFalse, \
5929 test.Dst()) \
5930 << TestString; \
5931 reset(); \
5932 } while (0)
5933
5934 #define TestImplAddrReg(Value0, Src, Value1, Size) \
5935 do { \
5936 static constexpr bool NearJump = true; \
5937 static constexpr char TestString[] = \
5938 "(Addr, " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
5939 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5940 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5941 const uint32_t T0 = allocateDword(); \
5942 \
5943 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
5944 __ test(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
5945 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
5946 Label Done; \
5947 __ j(Cond::Br_e, &Done, NearJump); \
5948 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
5949 __ bind(&Done); \
5950 \
5951 AssembledTest test = assemble(); \
5952 test.setDwordTo(T0, uint32_t(Value0)); \
5953 test.run(); \
5954 \
5955 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5956 : ValueIfFalse, \
5957 test.contentsOfDword(T0)) \
5958 << TestString; \
5959 reset(); \
5960 } while (0)
5961
5962 #define TestImplAddrImm(Value0, Value1, Size) \
5963 do { \
5964 static constexpr bool NearJump = true; \
5965 static constexpr char TestString[] = \
5966 "(Addr, " #Value0 ", " #Value1 ", " #Size ")"; \
5967 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5968 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5969 const uint32_t T0 = allocateDword(); \
5970 \
5971 __ test(IceType_i##Size, dwordAddress(T0), \
5972 Immediate((Value1)&Mask##Size)); \
5973 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
5974 Label Done; \
5975 __ j(Cond::Br_e, &Done, NearJump); \
5976 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
5977 __ bind(&Done); \
5978 \
5979 AssembledTest test = assemble(); \
5980 test.setDwordTo(T0, uint32_t(Value0)); \
5981 test.run(); \
5982 \
5983 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5984 : ValueIfFalse, \
5985 test.contentsOfDword(T0)) \
5986 << TestString; \
5987 reset(); \
5988 } while (0)
5989
5990 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
5991 do { \
5992 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
5993 TestImplRegImm(Dst, Value0, Value1, Size); \
5994 TestImplAddrReg(Value0, Src, Value1, Size); \
5995 TestImplAddrImm(Value0, Value1, Size); \
5996 } while (0)
5997
5998 #define TestImplSize(Dst, Src, Size) \
5999 do { \
6000 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
6001 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
6002 TestImplValues(Dst, 0x0F00000F, Src, 0xF00000F0, Size); \
6003 } while (0)
6004
6005 #define TestImpl(Dst, Src) \
6006 do { \
6007 TestImplSize(Dst, Src, 8); \
6008 TestImplSize(Dst, Src, 16); \
6009 TestImplSize(Dst, Src, 32); \
6010 } while (0)
6011
6012 TestImpl(r1, r2);
6013 TestImpl(r2, r3);
6014 TestImpl(r3, r4);
6015 TestImpl(r4, r5);
6016 TestImpl(r5, r6);
6017 TestImpl(r6, r7);
6018 TestImpl(r7, r8);
6019 TestImpl(r8, r10);
6020 TestImpl(r10, r11);
6021 TestImpl(r11, r12);
6022 TestImpl(r12, r13);
6023 TestImpl(r13, r14);
6024 TestImpl(r14, r15);
6025 TestImpl(r15, r1);
6026
6027 #undef TestImpl
6028 #undef TestImplSize
6029 #undef TestImplValues
6030 #undef TestImplAddrImm
6031 #undef TestImplAddrReg
6032 #undef TestImplRegImm
6033 #undef TestImplRegReg
6034 }
6035
6036 // No mull/div because x86.
6037 // No shift because x86.
6038 TEST_F(AssemblerX8664Test, Arith_most) {
6039 static constexpr uint32_t Mask8 = 0xFF;
6040 static constexpr uint32_t Mask16 = 0xFFFF;
6041 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6042
6043 #define TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
6044 do { \
6045 static constexpr char TestString[] = \
6046 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
6047 ", " #Type #Size "_t, " #Op ")"; \
6048 \
6049 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6050 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
6051 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6052 \
6053 AssembledTest test = assemble(); \
6054 test.run(); \
6055 \
6056 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6057 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6058 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6059 Mask##Size &test.Dst()) \
6060 << TestString; \
6061 reset(); \
6062 } while (0)
6063
6064 #define TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op) \
6065 do { \
6066 static constexpr char TestString[] = \
6067 "(" #Inst ", " #Dst ", " #Value0 ", Addr, " #Value1 ", " #Type #Size \
6068 "_t, " #Op ")"; \
6069 const uint32_t T0 = allocateDword(); \
6070 const uint32_t V0 = Value1; \
6071 \
6072 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6073 __ mov(IceType_i##Size, dwordAddress(T0), Immediate(Value1)); \
6074 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
6075 \
6076 AssembledTest test = assemble(); \
6077 test.setDwordTo(T0, V0); \
6078 test.run(); \
6079 \
6080 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6081 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6082 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6083 Mask##Size &test.Dst()) \
6084 << TestString; \
6085 reset(); \
6086 } while (0)
6087
6088 #define TestImplRegImm(Inst, Dst, Value0, Imm, Type, Size, Op) \
6089 do { \
6090 static constexpr char TestString[] = \
6091 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Type #Size \
6092 "_t, " #Op ")"; \
6093 \
6094 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6095 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
6096 Immediate((Imm)&Mask##Size)); \
6097 \
6098 AssembledTest test = assemble(); \
6099 test.run(); \
6100 \
6101 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6102 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6103 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
6104 Mask##Size &test.Dst()) \
6105 << TestString; \
6106 reset(); \
6107 } while (0)
6108
6109 #define TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op) \
6110 do { \
6111 static constexpr char TestString[] = \
6112 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Type #Size \
6113 "_t, " #Op ")"; \
6114 const uint32_t T0 = allocateDword(); \
6115 const uint32_t V0 = Value0; \
6116 \
6117 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
6118 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
6119 \
6120 AssembledTest test = assemble(); \
6121 test.setDwordTo(T0, V0); \
6122 test.run(); \
6123 \
6124 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6125 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6126 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6127 Mask##Size &test.contentsOfDword(T0)) \
6128 << TestString; \
6129 reset(); \
6130 } while (0)
6131
6132 #define TestImplAddrImm(Inst, Value0, Imm, Type, Size, Op) \
6133 do { \
6134 static constexpr char TestString[] = \
6135 "(" #Inst ", Addr, " #Value0 ", Imm, " #Imm ", " #Type #Size \
6136 "_t, " #Op ")"; \
6137 const uint32_t T0 = allocateDword(); \
6138 const uint32_t V0 = Value0; \
6139 \
6140 __ Inst(IceType_i##Size, dwordAddress(T0), Immediate((Imm)&Mask##Size)); \
6141 \
6142 AssembledTest test = assemble(); \
6143 test.setDwordTo(T0, V0); \
6144 test.run(); \
6145 \
6146 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6147 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6148 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
6149 Mask##Size &test.contentsOfDword(T0)) \
6150 << TestString; \
6151 reset(); \
6152 } while (0)
6153
6154 #define TestImplOp(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
6155 do { \
6156 TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op); \
6157 TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op); \
6158 TestImplRegImm(Inst, Dst, Value0, Value1, Type, Size, Op); \
6159 TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op); \
6160 TestImplAddrImm(Inst, Value0, Value1, Type, Size, Op); \
6161 } while (0)
6162
6163 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
6164 do { \
6165 TestImplOp(And, Dst, Value0, Src, Value1, int, Size, &); \
6166 TestImplOp(And, Dst, Value0, Src, Value1, uint, Size, &); \
6167 TestImplOp(Or, Dst, Value0, Src, Value1, int, Size, | ); \
6168 TestImplOp(Or, Dst, Value0, Src, Value1, uint, Size, | ); \
6169 TestImplOp(Xor, Dst, Value0, Src, Value1, int, Size, ^); \
6170 TestImplOp(Xor, Dst, Value0, Src, Value1, uint, Size, ^); \
6171 TestImplOp(add, Dst, Value0, Src, Value1, int, Size, +); \
6172 TestImplOp(add, Dst, Value0, Src, Value1, uint, Size, +); \
6173 TestImplOp(sub, Dst, Value0, Src, Value1, int, Size, -); \
6174 TestImplOp(sub, Dst, Value0, Src, Value1, uint, Size, -); \
6175 } while (0)
6176
6177 #define TestImplSize(Dst, Src, Size) \
6178 do { \
6179 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
6180 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
6181 TestImplValues(Dst, 0x0F00000F, Src, 0xF0000070, Size); \
6182 TestImplValues(Dst, 0x0F00F00F, Src, 0xF000F070, Size); \
6183 } while (0)
6184
6185 #define TestImpl(Dst, Src) \
6186 do { \
6187 TestImplSize(Dst, Src, 8); \
6188 TestImplSize(Dst, Src, 16); \
6189 TestImplSize(Dst, Src, 32); \
6190 } while (0)
6191
6192 TestImpl(r1, r2);
6193 TestImpl(r2, r3);
6194 TestImpl(r3, r4);
6195 TestImpl(r4, r5);
6196 TestImpl(r5, r6);
6197 TestImpl(r6, r7);
6198 TestImpl(r7, r8);
6199 TestImpl(r8, r10);
6200 TestImpl(r10, r11);
6201 TestImpl(r11, r12);
6202 TestImpl(r12, r13);
6203 TestImpl(r13, r14);
6204 TestImpl(r14, r15);
6205 TestImpl(r15, r1);
6206
6207 #undef TestImpl
6208 #undef TestImplSize
6209 #undef TestImplValues
6210 #undef TestImplOp
6211 #undef TestImplAddrImm
6212 #undef TestImplAddrReg
6213 #undef TestImplRegImm
6214 #undef TestImplRegAddr
6215 #undef TestImplRegReg
6216 }
6217
6218 TEST_F(AssemblerX8664Test, Arith_BorrowNCarry) {
6219 const uint32_t Mask8 = 0x000000FF;
6220 const uint32_t Mask16 = 0x0000FFFF;
6221 const uint32_t Mask32 = 0xFFFFFFFF;
6222
6223 const uint64_t ResultMask8 = 0x000000000000FFFFull;
6224 const uint64_t ResultMask16 = 0x00000000FFFFFFFFull;
6225 const uint64_t ResultMask32 = 0xFFFFFFFFFFFFFFFFull;
6226
6227 #define TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, \
6228 Op, Size) \
6229 do { \
6230 static_assert(Size == 8 || Size == 16 || Size == 32, \
6231 "Invalid size " #Size); \
6232 static constexpr char TestString[] = \
6233 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 ", " #Src0 \
6234 ", " #Src1 ", " #Value1 ", " #Op ", " #Size ")"; \
6235 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6236 Immediate(uint64_t(Value0) & Mask##Size)); \
6237 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6238 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6239 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
6240 Immediate(uint64_t(Value1) & Mask##Size)); \
6241 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
6242 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
6243 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), Encoded_GPR_##Src0()); \
6244 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), Encoded_GPR_##Src1()); \
6245 \
6246 AssembledTest test = assemble(); \
6247 test.run(); \
6248 \
6249 static constexpr uint64_t Result = \
6250 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6251 ResultMask##Size); \
6252 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6253 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6254 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6255 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6256 reset(); \
6257 } while (0)
6258
6259 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size) \
6260 do { \
6261 static_assert(Size == 8 || Size == 16 || Size == 32, \
6262 "Invalid size " #Size); \
6263 static constexpr char TestString[] = \
6264 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
6265 ", Addr, " #Value1 ", " #Op ", " #Size ")"; \
6266 const uint32_t T0 = allocateDword(); \
6267 const uint32_t V0 = uint64_t(Value1) & Mask##Size; \
6268 const uint32_t T1 = allocateDword(); \
6269 const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size; \
6270 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6271 Immediate(uint64_t(Value0) & Mask##Size)); \
6272 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6273 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6274 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), dwordAddress(T0)); \
6275 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), dwordAddress(T1)); \
6276 \
6277 AssembledTest test = assemble(); \
6278 test.setDwordTo(T0, V0); \
6279 test.setDwordTo(T1, V1); \
6280 test.run(); \
6281 \
6282 static constexpr uint64_t Result = \
6283 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6284 ResultMask##Size); \
6285 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6286 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6287 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6288 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6289 reset(); \
6290 } while (0)
6291
6292 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size) \
6293 do { \
6294 static_assert(Size == 8 || Size == 16 || Size == 32, \
6295 "Invalid size " #Size); \
6296 static constexpr char TestString[] = \
6297 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
6298 ", Imm(" #Imm "), " #Op ", " #Size ")"; \
6299 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6300 Immediate(uint64_t(Value0) & Mask##Size)); \
6301 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6302 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6303 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), \
6304 Immediate(uint64_t(Imm) & Mask##Size)); \
6305 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), \
6306 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
6307 \
6308 AssembledTest test = assemble(); \
6309 test.run(); \
6310 \
6311 static constexpr uint64_t Result = \
6312 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
6313 ResultMask##Size); \
6314 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6315 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6316 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6317 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6318 reset(); \
6319 } while (0)
6320
6321 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size) \
6322 do { \
6323 static_assert(Size == 8 || Size == 16 || Size == 32, \
6324 "Invalid size " #Size); \
6325 static constexpr char TestString[] = \
6326 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1 \
6327 ", " #Value1 ", " #Op ", " #Size ")"; \
6328 const uint32_t T0 = allocateDword(); \
6329 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
6330 const uint32_t T1 = allocateDword(); \
6331 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
6332 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
6333 Immediate(uint64_t(Value1) & Mask##Size)); \
6334 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
6335 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
6336 __ Inst0(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src0()); \
6337 __ Inst1(IceType_i##Size, dwordAddress(T1), Encoded_GPR_##Src1()); \
6338 \
6339 AssembledTest test = assemble(); \
6340 test.setDwordTo(T0, V0); \
6341 test.setDwordTo(T1, V1); \
6342 test.run(); \
6343 \
6344 static constexpr uint64_t Result = \
6345 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6346 ResultMask##Size); \
6347 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6348 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6349 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
6350 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
6351 reset(); \
6352 } while (0)
6353
6354 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size) \
6355 do { \
6356 static_assert(Size == 8 || Size == 16 || Size == 32, \
6357 "Invalid size " #Size); \
6358 static constexpr char TestString[] = \
6359 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op \
6360 ", " #Size ")"; \
6361 const uint32_t T0 = allocateDword(); \
6362 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
6363 const uint32_t T1 = allocateDword(); \
6364 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
6365 __ Inst0(IceType_i##Size, dwordAddress(T0), \
6366 Immediate(uint64_t(Imm) & Mask##Size)); \
6367 __ Inst1(IceType_i##Size, dwordAddress(T1), \
6368 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
6369 \
6370 AssembledTest test = assemble(); \
6371 test.setDwordTo(T0, V0); \
6372 test.setDwordTo(T1, V1); \
6373 test.run(); \
6374 \
6375 static constexpr uint64_t Result = \
6376 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
6377 ResultMask##Size); \
6378 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6379 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6380 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
6381 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
6382 reset(); \
6383 } while (0)
6384
6385 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
6386 Size) \
6387 do { \
6388 TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
6389 Size); \
6390 TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
6391 TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
6392 TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size); \
6393 TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size); \
6394 } while (0)
6395
6396 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size) \
6397 do { \
6398 TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size); \
6399 TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size); \
6400 } while (0)
6401
6402 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size) \
6403 do { \
6404 TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1, \
6405 0xFFFFFFFF0000017Full, Size); \
6406 } while (0)
6407
6408 #define TestImpl(Dst0, Dst1, Src0, Src1) \
6409 do { \
6410 TestImplSize(Dst0, Dst1, Src0, Src1, 8); \
6411 TestImplSize(Dst0, Dst1, Src0, Src1, 16); \
6412 TestImplSize(Dst0, Dst1, Src0, Src1, 32); \
6413 } while (0)
6414
6415 TestImpl(r1, r2, r3, r5);
6416 TestImpl(r2, r3, r4, r6);
6417 TestImpl(r3, r4, r5, r7);
6418 TestImpl(r4, r5, r6, r8);
6419 TestImpl(r5, r6, r7, r10);
6420 TestImpl(r6, r7, r8, r11);
6421 TestImpl(r7, r8, r10, r12);
6422 TestImpl(r8, r10, r11, r13);
6423 TestImpl(r10, r11, r12, r14);
6424 TestImpl(r11, r12, r13, r15);
6425 TestImpl(r12, r13, r14, r1);
6426 TestImpl(r13, r14, r15, r2);
6427 TestImpl(r14, r15, r1, r3);
6428 TestImpl(r15, r1, r2, r4);
6429
6430 #undef TestImpl
6431 #undef TestImplSize
6432 #undef TestImplValues
6433 #undef TestImplOp
6434 #undef TestImplAddrImm
6435 #undef TestImplAddrReg
6436 #undef TestImplRegImm
6437 #undef TestImplRegAddr
6438 #undef TestImplRegReg
6439 }
6440
6441 TEST_F(AssemblerX8664LowLevelTest, Cbw_Cwd_Cdq) {
6442 #define TestImpl(Inst, BytesSize, ...) \
6443 do { \
6444 __ Inst(); \
6445 ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst; \
6446 verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__); \
6447 reset(); \
6448 } while (0)
6449
6450 TestImpl(cbw, 2u, 0x66, 0x98);
6451 TestImpl(cwd, 2u, 0x66, 0x99);
6452 TestImpl(cdq, 1u, 0x99);
6453
6454 #undef TestImpl
6455 }
6456
6457 TEST_F(AssemblerX8664Test, SingleOperandMul) {
6458 static constexpr uint32_t Mask8 = 0x000000FF;
6459 static constexpr uint32_t Mask16 = 0x0000FFFF;
6460 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6461
6462 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
6463 do { \
6464 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
6465 "eax can not be src1."); \
6466 \
6467 static constexpr char TestString[] = \
6468 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
6469 ")"; \
6470 static constexpr Type##64_t OperandEax = \
6471 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
6472 static constexpr Type##64_t OperandOther = \
6473 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
6474 static constexpr uint32_t ExpectedEax = \
6475 Mask##Size & (OperandEax * OperandOther); \
6476 static constexpr uint32_t ExpectedEdx = \
6477 Mask##Size & ((OperandEax * OperandOther) >> Size); \
6478 \
6479 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
6480 Immediate((Value0)&Mask##Size)); \
6481 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6482 Immediate((Value1)&Mask##Size)); \
6483 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
6484 \
6485 if (Size == 8) { \
6486 /* mov %ah, %dl */ \
6487 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6488 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6489 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6490 } \
6491 \
6492 AssembledTest test = assemble(); \
6493 test.run(); \
6494 \
6495 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
6496 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
6497 reset(); \
6498 } while (0)
6499
6500 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
6501 do { \
6502 static constexpr char TestString[] = \
6503 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
6504 static const uint32_t T0 = allocateDword(); \
6505 static constexpr uint32_t V0 = Value1; \
6506 static constexpr Type##64_t OperandEax = \
6507 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
6508 static constexpr Type##64_t OperandOther = \
6509 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
6510 static constexpr uint32_t ExpectedEax = \
6511 Mask##Size & (OperandEax * OperandOther); \
6512 static constexpr uint32_t ExpectedEdx = \
6513 Mask##Size & ((OperandEax * OperandOther) >> Size); \
6514 \
6515 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
6516 Immediate((Value0)&Mask##Size)); \
6517 __ Inst(IceType_i##Size, dwordAddress(T0)); \
6518 \
6519 if (Size == 8) { \
6520 /* mov %ah, %dl */ \
6521 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6522 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6523 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6524 } \
6525 \
6526 AssembledTest test = assemble(); \
6527 test.setDwordTo(T0, V0); \
6528 test.run(); \
6529 \
6530 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
6531 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
6532 reset(); \
6533 } while (0)
6534
6535 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
6536 do { \
6537 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
6538 TestImplAddr(Inst, Value0, Value1, Type, Size); \
6539 } while (0)
6540
6541 #define TestImplValue(Value0, Src, Value1, Size) \
6542 do { \
6543 TestImplOp(mul, Value0, Src, Value1, uint, Size); \
6544 TestImplOp(imul, Value0, Src, Value1, int, Size); \
6545 } while (0)
6546
6547 #define TestImplSize(Src, Size) \
6548 do { \
6549 TestImplValue(10, Src, 1, Size); \
6550 TestImplValue(10, Src, -1, Size); \
6551 TestImplValue(-10, Src, 37, Size); \
6552 TestImplValue(-10, Src, -15, Size); \
6553 } while (0)
6554
6555 #define TestImpl(Src) \
6556 do { \
6557 TestImplSize(Src, 8); \
6558 TestImplSize(Src, 16); \
6559 TestImplSize(Src, 32); \
6560 } while (0)
6561
6562 TestImpl(r2);
6563 TestImpl(r3);
6564 TestImpl(r4);
6565 TestImpl(r5);
6566 TestImpl(r6);
6567 TestImpl(r7);
6568 TestImpl(r8);
6569 TestImpl(r10);
6570 TestImpl(r11);
6571 TestImpl(r12);
6572 TestImpl(r13);
6573 TestImpl(r14);
6574 TestImpl(r15);
6575
6576 #undef TestImpl
6577 #undef TestImplSize
6578 #undef TestImplValue
6579 #undef TestImplOp
6580 #undef TestImplAddr
6581 #undef TestImplReg
6582 }
6583
6584 TEST_F(AssemblerX8664Test, TwoOperandImul) {
6585 static constexpr uint32_t Mask16 = 0x0000FFFF;
6586 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6587
6588 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
6589 do { \
6590 static constexpr char TestString[] = \
6591 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
6592 static constexpr int64_t Operand0 = \
6593 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6594 static constexpr int64_t Operand1 = \
6595 static_cast<int##Size##_t>((Value1)&Mask##Size); \
6596 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6597 \
6598 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6599 Immediate((Value0)&Mask##Size)); \
6600 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6601 Immediate((Value1)&Mask##Size)); \
6602 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6603 \
6604 if (Size == 8) { \
6605 /* mov %ah, %dl */ \
6606 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6607 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6608 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6609 } \
6610 \
6611 AssembledTest test = assemble(); \
6612 test.run(); \
6613 \
6614 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6615 reset(); \
6616 } while (0)
6617
6618 #define TestImplRegImm(Dst, Value0, Imm, Size) \
6619 do { \
6620 static constexpr char TestString[] = \
6621 "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")"; \
6622 static constexpr int64_t Operand0 = \
6623 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6624 static constexpr int64_t Operand1 = \
6625 static_cast<int##Size##_t>((Imm)&Mask##Size); \
6626 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6627 \
6628 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6629 Immediate((Value0)&Mask##Size)); \
6630 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Imm)); \
6631 \
6632 if (Size == 8) { \
6633 /* mov %ah, %dl */ \
6634 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6635 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6636 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6637 } \
6638 \
6639 AssembledTest test = assemble(); \
6640 test.run(); \
6641 \
6642 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6643 reset(); \
6644 } while (0)
6645
6646 #define TestImplRegAddr(Dst, Value0, Value1, Size) \
6647 do { \
6648 static constexpr char TestString[] = \
6649 "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")"; \
6650 static constexpr int64_t Operand0 = \
6651 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6652 static constexpr int64_t Operand1 = \
6653 static_cast<int##Size##_t>((Value1)&Mask##Size); \
6654 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6655 const uint32_t T0 = allocateDword(); \
6656 \
6657 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6658 Immediate((Value0)&Mask##Size)); \
6659 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
6660 \
6661 if (Size == 8) { \
6662 /* mov %ah, %dl */ \
6663 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6664 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6665 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6666 } \
6667 \
6668 AssembledTest test = assemble(); \
6669 test.setDwordTo(T0, static_cast<uint32_t>(Operand1)); \
6670 test.run(); \
6671 \
6672 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6673 reset(); \
6674 } while (0)
6675
6676 #define TestImplValue(Dst, Value0, Src, Value1, Size) \
6677 do { \
6678 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
6679 TestImplRegImm(Dst, Value0, Value1, Size); \
6680 TestImplRegAddr(Dst, Value0, Value1, Size); \
6681 } while (0)
6682
6683 #define TestImplSize(Dst, Src, Size) \
6684 do { \
6685 TestImplValue(Dst, 1, Src, 1, Size); \
6686 TestImplValue(Dst, -10, Src, 0x4050AA20, Size); \
6687 TestImplValue(Dst, -2, Src, -55, Size); \
6688 } while (0)
6689
6690 #define TestImpl(Dst, Src) \
6691 do { \
6692 TestImplSize(Dst, Src, 16); \
6693 TestImplSize(Dst, Src, 32); \
6694 } while (0)
6695
6696 TestImpl(r1, r2);
6697 TestImpl(r2, r3);
6698 TestImpl(r3, r4);
6699 TestImpl(r4, r5);
6700 TestImpl(r5, r6);
6701 TestImpl(r6, r7);
6702 TestImpl(r7, r8);
6703 TestImpl(r8, r10);
6704 TestImpl(r10, r11);
6705 TestImpl(r11, r12);
6706 TestImpl(r12, r13);
6707 TestImpl(r13, r14);
6708 TestImpl(r14, r15);
6709 TestImpl(r15, r1);
6710
6711 #undef TestImpl
6712 #undef TestImplSize
6713 #undef TestImplValue
6714 #undef TestImplRegAddr
6715 #undef TestImplRegImm
6716 #undef TestImplRegReg
6717 }
6718
6719 TEST_F(AssemblerX8664Test, Div) {
6720 static constexpr uint32_t Mask8 = 0x000000FF;
6721 static constexpr uint32_t Mask16 = 0x0000FFFF;
6722 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6723
6724 static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull;
6725 static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull;
6726 static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull;
6727
6728 using Operand0Type_int8 = int16_t;
6729 using Operand0Type_uint8 = uint16_t;
6730 using Operand0Type_int16 = int32_t;
6731 using Operand0Type_uint16 = uint32_t;
6732 using Operand0Type_int32 = int64_t;
6733 using Operand0Type_uint32 = uint64_t;
6734
6735 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
6736 do { \
6737 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
6738 "eax can not be src1."); \
6739 static_assert(Encoded_GPR_edx() != Encoded_GPR_##Src(), \
6740 "edx can not be src1."); \
6741 \
6742 static constexpr char TestString[] = \
6743 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
6744 ")"; \
6745 static constexpr Operand0Type_##Type##Size Operand0 = \
6746 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
6747 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
6748 static constexpr Type##Size##_t Operand0Hi = \
6749 (Operand0 >> Size) & Mask##Size; \
6750 static constexpr Type##Size##_t Operand1 = \
6751 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
6752 if (Size == 8) { \
6753 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
6754 __ mov( \
6755 IceType_i16, Encoded_GPR_eax(), \
6756 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
6757 } else { \
6758 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
6759 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
6760 } \
6761 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Operand1)); \
6762 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
6763 if (Size == 8) { \
6764 /* mov %ah, %dl */ \
6765 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6766 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6767 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
6768 if (Encoded_GPR_##Src() == Encoded_GPR_esi()) { \
6769 __ And(IceType_i16, Encoded_GPR_edx(), Immediate(0x00FF)); \
6770 } \
6771 } \
6772 \
6773 AssembledTest test = assemble(); \
6774 test.run(); \
6775 \
6776 static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size; \
6777 static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size; \
6778 ASSERT_EQ(Quocient, test.eax()) << TestString; \
6779 ASSERT_EQ(Reminder, test.edx()) << TestString; \
6780 reset(); \
6781 } while (0)
6782
6783 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
6784 do { \
6785 static constexpr char TestString[] = \
6786 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
6787 static constexpr Operand0Type_##Type##Size Operand0 = \
6788 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
6789 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
6790 static constexpr Type##Size##_t Operand0Hi = \
6791 (Operand0 >> Size) & Mask##Size; \
6792 const uint32_t T0 = allocateDword(); \
6793 static constexpr Type##Size##_t V0 = \
6794 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
6795 if (Size == 8) { \
6796 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
6797 __ mov( \
6798 IceType_i16, Encoded_GPR_eax(), \
6799 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
6800 } else { \
6801 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
6802 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
6803 } \
6804 __ Inst(IceType_i##Size, dwordAddress(T0)); \
6805 if (Size == 8) { \
6806 /* mov %ah, %dl */ \
6807 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6808 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6809 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
6810 } \
6811 \
6812 AssembledTest test = assemble(); \
6813 test.setDwordTo(T0, static_cast<uint32_t>(V0)); \
6814 test.run(); \
6815 \
6816 static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size; \
6817 static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size; \
6818 ASSERT_EQ(Quocient, test.eax()) << TestString; \
6819 ASSERT_EQ(Reminder, test.edx()) << TestString; \
6820 reset(); \
6821 } while (0)
6822
6823 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
6824 do { \
6825 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
6826 TestImplAddr(Inst, Value0, Value1, Type, Size); \
6827 } while (0)
6828
6829 #define TestImplValue(Value0, Src, Value1, Size) \
6830 do { \
6831 TestImplOp(div, Value0, Src, Value1, uint, Size); \
6832 TestImplOp(idiv, Value0, Src, Value1, int, Size); \
6833 } while (0)
6834
6835 #define TestImplSize(Src, Size) \
6836 do { \
6837 TestImplValue(10, Src, 1, Size); \
6838 TestImplValue(10, Src, -1, Size); \
6839 } while (0)
6840
6841 #define TestImpl(Src) \
6842 do { \
6843 TestImplSize(Src, 8); \
6844 TestImplSize(Src, 16); \
6845 TestImplSize(Src, 32); \
6846 } while (0)
6847
6848 TestImpl(r2);
6849 TestImpl(r3);
6850 TestImpl(r5);
6851 TestImpl(r6);
6852 TestImpl(r7);
6853 TestImpl(r8);
6854 TestImpl(r10);
6855 TestImpl(r11);
6856 TestImpl(r12);
6857 TestImpl(r13);
6858 TestImpl(r14);
6859 TestImpl(r15);
6860
6861 #undef TestImpl
6862 #undef TestImplSize
6863 #undef TestImplValue
6864 #undef TestImplOp
6865 #undef TestImplAddr
6866 #undef TestImplReg
6867 }
6868
6869 TEST_F(AssemblerX8664Test, Incl_Decl_Addr) {
6870 #define TestImpl(Inst, Value0) \
6871 do { \
6872 const bool IsInc = std::string(#Inst).find("incl") != std::string::npos; \
6873 const uint32_t T0 = allocateDword(); \
6874 const uint32_t V0 = Value0; \
6875 \
6876 __ Inst(dwordAddress(T0)); \
6877 \
6878 AssembledTest test = assemble(); \
6879 test.setDwordTo(T0, V0); \
6880 test.run(); \
6881 \
6882 ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)), \
6883 test.contentsOfDword(T0)); \
6884 reset(); \
6885 } while (0)
6886
6887 #define TestInc(Value0) \
6888 do { \
6889 TestImpl(incl, Value0); \
6890 } while (0)
6891
6892 #define TestDec(Value0) \
6893 do { \
6894 TestImpl(decl, Value0); \
6895 } while (0)
6896
6897 TestInc(230);
6898
6899 TestDec(30);
6900
6901 #undef TestInc
6902 #undef TestDec
6903 #undef TestImpl
6904 }
6905
6906 TEST_F(AssemblerX8664Test, Shifts) {
6907 static constexpr uint32_t Mask8 = 0x000000FF;
6908 static constexpr uint32_t Mask16 = 0x0000FFFF;
6909 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6910
6911 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size) \
6912 do { \
6913 static constexpr char TestString[] = \
6914 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type \
6915 ", " #Size ")"; \
6916 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
6917 const uint##Size##_t Expected = \
6918 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) | \
6919 (!IsRol ? 0 : (Value0) >> (Size - Imm))); \
6920 \
6921 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6922 Immediate((Value0)&Mask##Size)); \
6923 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
6924 Immediate((Imm)&Mask##Size)); \
6925 \
6926 AssembledTest test = assemble(); \
6927 test.run(); \
6928 \
6929 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6930 reset(); \
6931 } while (0)
6932
6933 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
6934 Type, Size) \
6935 do { \
6936 static constexpr char TestString[] = \
6937 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
6938 ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
6939 const uint##Size##_t Expected = \
6940 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
6941 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
6942 \
6943 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6944 Immediate((Value0)&Mask##Size)); \
6945 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6946 Immediate((Value1)&Mask##Size)); \
6947 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src(), \
6948 Immediate(Count)); \
6949 \
6950 AssembledTest test = assemble(); \
6951 test.run(); \
6952 \
6953 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6954 reset(); \
6955 } while (0)
6956
6957 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size) \
6958 do { \
6959 static constexpr char TestString[] = \
6960 "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type \
6961 ", " #Size ")"; \
6962 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
6963 const uint##Size##_t Expected = \
6964 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
6965 (!IsRol ? 0 : Value0 >> (Size - Count))); \
6966 \
6967 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6968 Immediate((Value0)&Mask##Size)); \
6969 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
6970 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_ecx()); \
6971 \
6972 AssembledTest test = assemble(); \
6973 test.run(); \
6974 \
6975 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6976 reset(); \
6977 } while (0)
6978
6979 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
6980 Type, Size) \
6981 do { \
6982 static constexpr char TestString[] = \
6983 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count \
6984 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
6985 const uint##Size##_t Expected = \
6986 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
6987 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
6988 \
6989 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6990 Immediate((Value0)&Mask##Size)); \
6991 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6992 Immediate((Value1)&Mask##Size)); \
6993 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
6994 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6995 \
6996 AssembledTest test = assemble(); \
6997 test.run(); \
6998 \
6999 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
7000 reset(); \
7001 } while (0)
7002
7003 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size) \
7004 do { \
7005 static constexpr char TestString[] = \
7006 "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type \
7007 ", " #Size ")"; \
7008 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
7009 const uint##Size##_t Expected = \
7010 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
7011 (!IsRol ? 0 : Value0 >> (Size - Count))); \
7012 const uint32_t T0 = allocateDword(); \
7013 const uint32_t V0 = Value0; \
7014 \
7015 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
7016 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_ecx()); \
7017 \
7018 AssembledTest test = assemble(); \
7019 test.setDwordTo(T0, V0); \
7020 test.run(); \
7021 \
7022 ASSERT_EQ(static_cast<uint32_t>(Expected), \
7023 Mask##Size &test.contentsOfDword(T0)) \
7024 << TestString; \
7025 reset(); \
7026 } while (0)
7027
7028 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7029 Size) \
7030 do { \
7031 static constexpr char TestString[] = \
7032 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count \
7033 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
7034 const uint##Size##_t Expected = \
7035 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
7036 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
7037 const uint32_t T0 = allocateDword(); \
7038 \
7039 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
7040 Immediate((Value1)&Mask##Size)); \
7041 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
7042 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
7043 \
7044 AssembledTest test = assemble(); \
7045 test.setDwordTo(T0, static_cast<uint32_t>(Value0)); \
7046 test.run(); \
7047 \
7048 ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0)) \
7049 << TestString; \
7050 reset(); \
7051 } while (0)
7052
7053 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size) \
7054 do { \
7055 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
7056 "ecx should not be specified as Dst"); \
7057 TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size); \
7058 TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size); \
7059 TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size); \
7060 TestImplAddrCl(Inst, Value0, Count, Op, Type, Size); \
7061 } while (0)
7062
7063 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0, \
7064 Op1, Type, Size) \
7065 do { \
7066 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
7067 "ecx should not be specified as Dst"); \
7068 static_assert(Encoded_GPR_##Src() != Encoded_GPR_ecx(), \
7069 "ecx should not be specified as Src"); \
7070 TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7071 Size); \
7072 TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7073 Size); \
7074 TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \
7075 } while (0)
7076
7077 #define TestImplValue(Dst, Value0, Count, Size) \
7078 do { \
7079 TestImplOp(rol, Dst, Value0, Count, <<, uint, Size); \
7080 TestImplOp(shl, Dst, Value0, Count, <<, uint, Size); \
7081 TestImplOp(shr, Dst, Value0, Count, >>, uint, Size); \
7082 TestImplOp(sar, Dst, Value0, Count, >>, int, Size); \
7083 } while (0)
7084
7085 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size) \
7086 do { \
7087 TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>, \
7088 uint, Size); \
7089 TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<, \
7090 uint, Size); \
7091 } while (0)
7092
7093 #define TestImplSize(Dst, Size) \
7094 do { \
7095 TestImplValue(Dst, 0x8F, 3, Size); \
7096 TestImplValue(Dst, 0x8FFF, 7, Size); \
7097 TestImplValue(Dst, 0x8FFFF, 7, Size); \
7098 } while (0)
7099
7100 #define TestImplThreeOperandSize(Dst, Src, Size) \
7101 do { \
7102 TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size); \
7103 } while (0)
7104
7105 #define TestImpl(Dst, Src) \
7106 do { \
7107 TestImplSize(Dst, 8); \
7108 TestImplSize(Dst, 16); \
7109 TestImplThreeOperandSize(Dst, Src, 16); \
7110 TestImplSize(Dst, 32); \
7111 TestImplThreeOperandSize(Dst, Src, 32); \
7112 } while (0)
7113
7114 TestImpl(r1, r2);
7115 TestImpl(r2, r4);
7116 TestImpl(r4, r5);
7117 TestImpl(r5, r6);
7118 TestImpl(r6, r7);
7119 TestImpl(r7, r8);
7120 TestImpl(r8, r10);
7121 TestImpl(r10, r11);
7122 TestImpl(r11, r12);
7123 TestImpl(r12, r13);
7124 TestImpl(r13, r14);
7125 TestImpl(r14, r15);
7126 TestImpl(r15, r1);
7127
7128 #undef TestImpl
7129 #undef TestImplThreeOperandSize
7130 #undef TestImplSize
7131 #undef TestImplValue
7132 #undef TestImplThreeOperandValue
7133 #undef TestImplOp
7134 #undef TestImplThreeOperandOp
7135 #undef TestImplAddrCl
7136 #undef TestImplRegRegCl
7137 #undef TestImplRegCl
7138 #undef TestImplRegRegImm
7139 #undef TestImplRegImm
7140 }
7141
7142 TEST_F(AssemblerX8664Test, Neg) {
7143 static constexpr uint32_t Mask8 = 0x000000ff;
7144 static constexpr uint32_t Mask16 = 0x0000ffff;
7145 static constexpr uint32_t Mask32 = 0xffffffff;
7146
7147 #define TestImplReg(Dst, Size) \
7148 do { \
7149 static constexpr int32_t Value = 0xFF00A543; \
7150 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
7151 Immediate(static_cast<int##Size##_t>(Value) & Mask##Size)); \
7152 __ neg(IceType_i##Size, Encoded_GPR_##Dst()); \
7153 __ mov(IceType_i##Size, Encoded_GPR_eax(), Encoded_GPR_##Dst()); \
7154 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(Mask##Size)); \
7155 \
7156 AssembledTest test = assemble(); \
7157 test.run(); \
7158 \
7159 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
7160 test.eax()) \
7161 << "(" #Dst ", " #Size ")"; \
7162 reset(); \
7163 } while (0)
7164
7165 #define TestImplAddr(Size) \
7166 do { \
7167 static constexpr int32_t Value = 0xFF00A543; \
7168 const uint32_t T0 = allocateDword(); \
7169 __ neg(IceType_i##Size, dwordAddress(T0)); \
7170 \
7171 AssembledTest test = assemble(); \
7172 test.setDwordTo(T0, Value &Mask##Size); \
7173 test.run(); \
7174 \
7175 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
7176 test.contentsOfDword(T0)) \
7177 << "(Addr, " #Size ")"; \
7178 reset(); \
7179 } while (0)
7180
7181 #define TestImpl(Size) \
7182 do { \
7183 TestImplAddr(Size); \
7184 TestImplReg(r1, Size); \
7185 TestImplReg(r2, Size); \
7186 TestImplReg(r3, Size); \
7187 TestImplReg(r4, Size); \
7188 TestImplReg(r5, Size); \
7189 TestImplReg(r6, Size); \
7190 TestImplReg(r7, Size); \
7191 TestImplReg(r8, Size); \
7192 TestImplReg(r10, Size); \
7193 TestImplReg(r11, Size); \
7194 TestImplReg(r12, Size); \
7195 TestImplReg(r13, Size); \
7196 TestImplReg(r14, Size); \
7197 TestImplReg(r15, Size); \
7198 } while (0)
7199
7200 TestImpl(8);
7201 TestImpl(16);
7202 TestImpl(32);
7203
7204 #undef TestImpl
7205 #undef TestImplAddr
7206 #undef TestImplReg
7207 }
7208
7209 TEST_F(AssemblerX8664Test, Not) {
7210 #define TestImpl(Dst) \
7211 do { \
7212 static constexpr uint32_t Value = 0xFF00A543; \
7213 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
7214 __ notl(Encoded_GPR_##Dst()); \
7215 \
7216 AssembledTest test = assemble(); \
7217 test.run(); \
7218 \
7219 ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")"; \
7220 reset(); \
7221 } while (0)
7222
7223 TestImpl(r1);
7224 TestImpl(r2);
7225 TestImpl(r3);
7226 TestImpl(r4);
7227 TestImpl(r5);
7228 TestImpl(r6);
7229 TestImpl(r7);
7230 TestImpl(r8);
7231 TestImpl(r10);
7232 TestImpl(r11);
7233 TestImpl(r12);
7234 TestImpl(r13);
7235 TestImpl(r14);
7236 TestImpl(r15);
7237
7238 #undef TestImpl
7239 }
7240
7241 TEST_F(AssemblerX8664Test, Bswap) {
7242 #define TestImpl(Dst) \
7243 do { \
7244 static constexpr uint32_t Value = 0xFF00A543; \
7245 static constexpr uint32_t Expected = 0x43A500FF; \
7246 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
7247 __ bswap(IceType_i32, Encoded_GPR_##Dst()); \
7248 \
7249 AssembledTest test = assemble(); \
7250 test.run(); \
7251 \
7252 ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")"; \
7253 reset(); \
7254 } while (0)
7255
7256 TestImpl(r1);
7257 TestImpl(r2);
7258 TestImpl(r3);
7259 TestImpl(r4);
7260 TestImpl(r5);
7261 TestImpl(r6);
7262 TestImpl(r7);
7263 TestImpl(r8);
7264 TestImpl(r10);
7265 TestImpl(r11);
7266 TestImpl(r12);
7267 TestImpl(r13);
7268 TestImpl(r14);
7269 TestImpl(r15);
7270
7271 #undef TestImpl
7272 }
7273
7274 TEST_F(AssemblerX8664Test, Bt) {
7275 #define TestImpl(Dst, Value0, Src, Value1) \
7276 do { \
7277 static constexpr char TestString[] = \
7278 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")"; \
7279 static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0; \
7280 \
7281 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value0)); \
7282 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value1)); \
7283 __ bt(Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
7284 __ setcc(Cond::Br_b, ByteRegister::Encoded_Reg_al); \
7285 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(0xFFu)); \
7286 \
7287 AssembledTest test = assemble(); \
7288 test.run(); \
7289 \
7290 ASSERT_EQ(Expected, test.eax()) << TestString; \
7291 reset(); \
7292 } while (0)
7293
7294 TestImpl(r1, 0x08000000, r2, 27u);
7295 TestImpl(r2, 0x08000000, r3, 23u);
7296 TestImpl(r3, 0x00000000, r4, 1u);
7297 TestImpl(r4, 0x08000300, r5, 9u);
7298 TestImpl(r5, 0x08000300, r6, 10u);
7299 TestImpl(r6, 0x7FFFEFFF, r7, 13u);
7300 TestImpl(r7, 0x08000000, r8, 27u);
7301 TestImpl(r8, 0x08000000, r10, 23u);
7302 TestImpl(r10, 0x00000000, r11, 1u);
7303 TestImpl(r11, 0x08000300, r12, 9u);
7304 TestImpl(r12, 0x08000300, r13, 10u);
7305 TestImpl(r13, 0x7FFFEFFF, r14, 13u);
7306 TestImpl(r14, 0x08000000, r15, 27u);
7307 TestImpl(r15, 0x08000000, r1, 23u);
7308
7309 #undef TestImpl
7310 }
7311
7312 template <uint32_t Value, uint32_t Bits> class BitScanHelper {
7313 BitScanHelper() = delete;
7314
7315 public:
7316 static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32");
7317 using ValueType =
7318 typename std::conditional<Bits == 16, uint16_t, uint32_t>::type;
7319
7320 private:
7321 static constexpr ValueType BitIndex(bool Forward, ValueType Index) {
7322 return (Value == 0)
7323 ? BitScanHelper<Value, Bits>::NoBitSet
7324 : (Value & (1u << Index)
7325 ? Index
7326 : BitIndex(Forward, (Forward ? Index + 1 : Index - 1)));
7327 }
7328
7329 public:
7330 static constexpr ValueType NoBitSet = static_cast<ValueType>(-1);
7331 static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0);
7332 static constexpr ValueType bsr =
7333 BitIndex(/*Forward*/ false, /*Index=*/Bits - 1);
7334 };
7335
7336 TEST_F(AssemblerX8664Test, BitScanOperations) {
7337 #define TestImplRegReg(Inst, Dst, Src, Value1, Size) \
7338 do { \
7339 static constexpr char TestString[] = \
7340 "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")"; \
7341 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
7342 const uint32_t ZeroFlag = allocateDword(); \
7343 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
7344 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
7345 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7346 \
7347 AssembledTest test = assemble(); \
7348 test.setDwordTo(ZeroFlag, 0u); \
7349 test.run(); \
7350 \
7351 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
7352 test.contentsOfDword(ZeroFlag)) \
7353 << TestString; \
7354 if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) { \
7355 ASSERT_EQ(Expected, test.Dst()) << TestString; \
7356 } \
7357 reset(); \
7358 } while (0)
7359
7360 #define TestImplRegAddr(Inst, Dst, Value1, Size) \
7361 do { \
7362 static constexpr char TestString[] = \
7363 "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")"; \
7364 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
7365 const uint32_t T0 = allocateDword(); \
7366 const uint32_t ZeroFlag = allocateDword(); \
7367 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
7368 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7369 \
7370 AssembledTest test = assemble(); \
7371 test.setDwordTo(T0, Value1); \
7372 test.setDwordTo(ZeroFlag, 0u); \
7373 test.run(); \
7374 \
7375 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
7376 test.contentsOfDword(ZeroFlag)) \
7377 << TestString; \
7378 if (Expected != BitScanHelper<Value1, Size>::NoBitSet) { \
7379 ASSERT_EQ(Expected, test.Dst()) << TestString; \
7380 } \
7381 reset(); \
7382 } while (0)
7383
7384 #define TestImplSize(Dst, Src, Value1, Size) \
7385 do { \
7386 TestImplRegReg(bsf, Dst, Src, Value1, Size); \
7387 TestImplRegAddr(bsf, Dst, Value1, Size); \
7388 TestImplRegReg(bsr, Dst, Src, Value1, Size); \
7389 TestImplRegAddr(bsf, Dst, Value1, Size); \
7390 } while (0)
7391
7392 #define TestImplValue(Dst, Src, Value1) \
7393 do { \
7394 TestImplSize(Dst, Src, Value1, 16); \
7395 TestImplSize(Dst, Src, Value1, 32); \
7396 } while (0)
7397
7398 #define TestImpl(Dst, Src) \
7399 do { \
7400 TestImplValue(Dst, Src, 0x80000001); \
7401 TestImplValue(Dst, Src, 0x00000000); \
7402 TestImplValue(Dst, Src, 0x80001000); \
7403 TestImplValue(Dst, Src, 0x00FFFF00); \
7404 } while (0)
7405
7406 TestImpl(r1, r2);
7407 TestImpl(r2, r3);
7408 TestImpl(r3, r4);
7409 TestImpl(r4, r5);
7410 TestImpl(r5, r6);
7411 TestImpl(r6, r7);
7412 TestImpl(r7, r8);
7413 TestImpl(r8, r10);
7414 TestImpl(r10, r11);
7415 TestImpl(r11, r12);
7416 TestImpl(r12, r13);
7417 TestImpl(r13, r14);
7418 TestImpl(r14, r15);
7419 TestImpl(r15, r1);
7420
7421 #undef TestImpl
7422 #undef TestImplValue
7423 #undef TestImplSize
7424 #undef TestImplRegAddr
7425 #undef TestImplRegReg
7426 }
7427
7428 TEST_F(AssemblerX8664LowLevelTest, Nop) {
7429 #define TestImpl(Size, ...) \
7430 do { \
7431 static constexpr char TestString[] = "(" #Size ", " #__VA_ARGS__ ")"; \
7432 __ nop(Size); \
7433 ASSERT_EQ(Size##u, codeBytesSize()) << TestString; \
7434 ASSERT_TRUE(verifyBytes<Size>(codeBytes(), __VA_ARGS__)) << TestString; \
7435 reset(); \
7436 } while (0);
7437
7438 TestImpl(1, 0x90);
7439 TestImpl(2, 0x66, 0x90);
7440 TestImpl(3, 0x0F, 0x1F, 0x00);
7441 TestImpl(4, 0x0F, 0x1F, 0x40, 0x00);
7442 TestImpl(5, 0x0F, 0x1F, 0x44, 0x00, 0x00);
7443 TestImpl(6, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00);
7444 TestImpl(7, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00);
7445 TestImpl(8, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00);
7446
7447 #undef TestImpl
7448 }
7449
7450 TEST_F(AssemblerX8664LowLevelTest, Int3) {
7451 __ int3();
7452 static constexpr uint32_t ByteCount = 1;
7453 ASSERT_EQ(ByteCount, codeBytesSize());
7454 verifyBytes<ByteCount>(codeBytes(), 0xCC);
7455 }
7456
7457 TEST_F(AssemblerX8664LowLevelTest, Hlt) {
7458 __ hlt();
7459 static constexpr uint32_t ByteCount = 1;
7460 ASSERT_EQ(ByteCount, codeBytesSize());
7461 verifyBytes<ByteCount>(codeBytes(), 0xF4);
7462 }
7463
7464 TEST_F(AssemblerX8664LowLevelTest, Ud2) {
7465 __ ud2();
7466 static constexpr uint32_t ByteCount = 2;
7467 ASSERT_EQ(ByteCount, codeBytesSize());
7468 verifyBytes<ByteCount>(codeBytes(), 0x0F, 0x0B);
7469 }
7470
7471 TEST_F(AssemblerX8664Test, Jmp) {
7472 // TestImplReg uses jmp(Label), so jmp(Label) needs to be tested before it.
7473 #define TestImplAddr(Near) \
7474 do { \
7475 Label ForwardJmp; \
7476 Label BackwardJmp; \
7477 Label Done; \
7478 \
7479 __ jmp(&ForwardJmp, AssemblerX8664::k##Near##Jump); \
7480 __ hlt(); \
7481 __ hlt(); \
7482 __ hlt(); \
7483 __ hlt(); \
7484 __ hlt(); \
7485 __ hlt(); \
7486 __ hlt(); \
7487 __ hlt(); \
7488 __ hlt(); \
7489 __ hlt(); \
7490 __ bind(&BackwardJmp); \
7491 __ jmp(&Done, AssemblerX8664::k##Near##Jump); \
7492 __ hlt(); \
7493 __ hlt(); \
7494 __ hlt(); \
7495 __ hlt(); \
7496 __ hlt(); \
7497 __ hlt(); \
7498 __ hlt(); \
7499 __ hlt(); \
7500 __ hlt(); \
7501 __ hlt(); \
7502 __ bind(&ForwardJmp); \
7503 __ jmp(&BackwardJmp, AssemblerX8664::k##NearJump); \
7504 __ hlt(); \
7505 __ hlt(); \
7506 __ hlt(); \
7507 __ hlt(); \
7508 __ hlt(); \
7509 __ hlt(); \
7510 __ hlt(); \
7511 __ hlt(); \
7512 __ hlt(); \
7513 __ hlt(); \
7514 __ bind(&Done); \
7515 } while (0)
7516
7517 #define TestImplReg(Dst) \
7518 do { \
7519 __ call(Immediate(16)); \
7520 Label Done; \
7521 __ jmp(&Done, AssemblerX8664::kNearJump); \
7522 __ hlt(); \
7523 __ hlt(); \
7524 __ hlt(); \
7525 __ hlt(); \
7526 __ hlt(); \
7527 __ hlt(); \
7528 __ hlt(); \
7529 __ hlt(); \
7530 __ hlt(); \
7531 __ hlt(); \
7532 __ popl(Encoded_GPR_##Dst()); \
7533 __ jmp(Encoded_GPR_##Dst()); \
7534 __ hlt(); \
7535 __ hlt(); \
7536 __ hlt(); \
7537 __ hlt(); \
7538 __ hlt(); \
7539 __ hlt(); \
7540 __ hlt(); \
7541 __ hlt(); \
7542 __ hlt(); \
7543 __ hlt(); \
7544 __ bind(&Done); \
7545 \
7546 AssembledTest test = assemble(); \
7547 test.run(); \
7548 \
7549 reset(); \
7550 } while (0)
7551
7552 TestImplAddr(Near);
7553 TestImplAddr(Far);
7554
7555 TestImplReg(r1);
7556 TestImplReg(r2);
7557 TestImplReg(r3);
7558 TestImplReg(r4);
7559 TestImplReg(r5);
7560 TestImplReg(r6);
7561 TestImplReg(r7);
7562 TestImplReg(r8);
7563 TestImplReg(r10);
7564 TestImplReg(r11);
7565 TestImplReg(r12);
7566 TestImplReg(r13);
7567 TestImplReg(r14);
7568 TestImplReg(r15);
7569
7570 #undef TestImplReg
7571 #undef TestImplAddr
7572 }
7573
7574 TEST_F(AssemblerX8664LowLevelTest, Mfence) {
7575 __ mfence();
7576
7577 static constexpr uint8_t ByteCount = 3;
7578 ASSERT_EQ(ByteCount, codeBytesSize());
7579 verifyBytes<ByteCount>(codeBytes(), 0x0F, 0xAE, 0xF0);
7580 }
7581
7582 TEST_F(AssemblerX8664LowLevelTest, Lock) {
7583 __ lock();
7584
7585 static constexpr uint8_t ByteCount = 1;
7586 ASSERT_EQ(ByteCount, codeBytesSize());
7587 verifyBytes<ByteCount>(codeBytes(), 0xF0);
7588 }
7589
7590 TEST_F(AssemblerX8664Test, Xchg) {
7591 static constexpr uint32_t Mask8 = 0x000000FF;
7592 static constexpr uint32_t Mask16 = 0x0000FFFF;
7593 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7594
7595 #define TestImplAddrReg(Value0, Dst1, Value1, Size) \
7596 do { \
7597 static constexpr char TestString[] = \
7598 "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
7599 const uint32_t T0 = allocateDword(); \
7600 const uint32_t V0 = (Value0)&Mask##Size; \
7601 const uint32_t V1 = (Value1)&Mask##Size; \
7602 \
7603 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), Immediate(Value1)); \
7604 __ xchg(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Dst1()); \
7605 __ And(IceType_i32, Encoded_GPR_##Dst1(), Immediate(Mask##Size)); \
7606 \
7607 AssembledTest test = assemble(); \
7608 test.setDwordTo(T0, V0); \
7609 test.run(); \
7610 \
7611 ASSERT_EQ(V0, test.Dst1()) << TestString; \
7612 ASSERT_EQ(V1, test.contentsOfDword(T0)) << TestString; \
7613 reset(); \
7614 } while (0)
7615
7616 #define TestImplSize(Dst1, Size) \
7617 do { \
7618 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Size); \
7619 } while (0)
7620
7621 #define TestImpl(Dst1) \
7622 do { \
7623 TestImplSize(Dst1, 8); \
7624 TestImplSize(Dst1, 16); \
7625 TestImplSize(Dst1, 32); \
7626 } while (0)
7627
7628 TestImpl(r1);
7629 TestImpl(r2);
7630 TestImpl(r3);
7631 TestImpl(r4);
7632 TestImpl(r5);
7633 TestImpl(r6);
7634 TestImpl(r7);
7635 TestImpl(r8);
7636 TestImpl(r10);
7637 TestImpl(r11);
7638 TestImpl(r12);
7639 TestImpl(r13);
7640 TestImpl(r14);
7641 TestImpl(r15);
7642
7643 #undef TestImpl
7644 #undef TestImplSize
7645 #undef TestImplAddrReg
7646 }
7647
7648 TEST_F(AssemblerX8664Test, Xadd) {
7649 static constexpr bool NotLocked = false;
7650 static constexpr bool Locked = true;
7651
7652 static constexpr uint32_t Mask8 = 0x000000FF;
7653 static constexpr uint32_t Mask16 = 0x0000FFFF;
7654 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7655
7656 #define TestImplAddrReg(Value0, Dst1, Value1, LockedOrNot, Size) \
7657 do { \
7658 static constexpr char TestString[] = \
7659 "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
7660 const uint32_t T0 = allocateDword(); \
7661 const uint32_t V0 = (Value0)&Mask##Size; \
7662 const uint32_t V1 = (Value1)&Mask##Size; \
7663 \
7664 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), Immediate(Value1)); \
7665 __ xadd(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Dst1(), \
7666 LockedOrNot); \
7667 __ And(IceType_i32, Encoded_GPR_##Dst1(), Immediate(Mask##Size)); \
7668 \
7669 AssembledTest test = assemble(); \
7670 test.setDwordTo(T0, V0); \
7671 test.run(); \
7672 \
7673 ASSERT_EQ(V0, test.Dst1()) << TestString; \
7674 ASSERT_EQ(Mask##Size &(V1 + V0), test.contentsOfDword(T0)) << TestString; \
7675 reset(); \
7676 } while (0)
7677
7678 #define TestImplSize(Dst1, Size) \
7679 do { \
7680 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, NotLocked, Size); \
7681 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Locked, Size); \
7682 } while (0)
7683
7684 #define TestImpl(Dst1) \
7685 do { \
7686 TestImplSize(Dst1, 8); \
7687 TestImplSize(Dst1, 16); \
7688 TestImplSize(Dst1, 32); \
7689 } while (0)
7690
7691 TestImpl(r1);
7692 TestImpl(r2);
7693 TestImpl(r3);
7694 TestImpl(r4);
7695 TestImpl(r5);
7696 TestImpl(r6);
7697 TestImpl(r7);
7698 TestImpl(r8);
7699 TestImpl(r10);
7700 TestImpl(r11);
7701 TestImpl(r12);
7702 TestImpl(r13);
7703 TestImpl(r14);
7704 TestImpl(r15);
7705
7706 #undef TestImpl
7707 #undef TestImplSize
7708 #undef TestImplAddrReg
7709 }
7710
7711 TEST_F(AssemblerX8664LowLevelTest, Xadd) {
7712 static constexpr bool NotLocked = false;
7713 static constexpr bool Locked = true;
7714
7715 // Ensures that xadd emits a lock prefix accordingly.
7716 {
7717 __ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7718 NotLocked);
7719 static constexpr uint8_t ByteCountNotLocked8 = 8;
7720 ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
7721 verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xC0, 0x35, 0x00,
7722 0xFF, 0x01, 0x00);
7723 reset();
7724
7725 __ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7726 static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
7727 ASSERT_EQ(ByteCountLocked8, codeBytesSize());
7728 verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x44, 0x0F, 0xC0, 0x35,
7729 0x00, 0xFF, 0x01, 0x00);
7730 reset();
7731 }
7732
7733 {
7734 __ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7735 NotLocked);
7736 static constexpr uint8_t ByteCountNotLocked16 = 9;
7737 ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
7738 verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x44, 0x0F, 0xC1, 0x35,
7739 0x00, 0xFF, 0x01, 0x00);
7740 reset();
7741
7742 __ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7743 static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
7744 ASSERT_EQ(ByteCountLocked16, codeBytesSize());
7745 verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44, 0x0F, 0xC1,
7746 0x35, 0x00, 0xFF, 0x01, 0x00);
7747 reset();
7748 }
7749
7750 {
7751 __ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7752 NotLocked);
7753 static constexpr uint8_t ByteCountNotLocked32 = 8;
7754 ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
7755 verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x44, 0x0F, 0xC1, 0x35, 0x00,
7756 0xFF, 0x01, 0x00);
7757 reset();
7758
7759 __ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7760 static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
7761 ASSERT_EQ(ByteCountLocked32, codeBytesSize());
7762 verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x44, 0x0F, 0xC1, 0x35,
7763 0x00, 0xFF, 0x01, 0x00);
7764 reset();
7765 }
7766 }
7767
7768 TEST_F(AssemblerX8664LowLevelTest, EmitSegmentOverride) {
7769 #define TestImpl(Prefix) \
7770 do { \
7771 static constexpr uint8_t ByteCount = 1; \
7772 __ emitSegmentOverride(Prefix); \
7773 ASSERT_EQ(ByteCount, codeBytesSize()) << Prefix; \
7774 verifyBytes<ByteCount>(codeBytes(), Prefix); \
7775 reset(); \
7776 } while (0)
7777
7778 TestImpl(0x26);
7779 TestImpl(0x2E);
7780 TestImpl(0x36);
7781 TestImpl(0x3E);
7782 TestImpl(0x64);
7783 TestImpl(0x65);
7784 TestImpl(0x66);
7785 TestImpl(0x67);
7786
7787 #undef TestImpl
7788 }
7789
7790 TEST_F(AssemblerX8664Test, Cmpxchg8b) {
7791 static constexpr bool NotLocked = false;
7792 static constexpr bool Locked = true;
7793
7794 #define TestImpl(Value0, Value1, ValueMem, LockedOrNot) \
7795 do { \
7796 static constexpr char TestString[] = \
7797 "(" #Value0 ", " #Value1 ", " #ValueMem ", " #LockedOrNot ")"; \
7798 const uint32_t T0 = allocateQword(); \
7799 static constexpr uint64_t V0 = ValueMem; \
7800 const uint32_t ZeroFlag = allocateDword(); \
7801 \
7802 __ mov(IceType_i32, Encoded_GPR_eax(), \
7803 Immediate(uint64_t(Value0) & 0xFFFFFFFF)); \
7804 __ mov(IceType_i32, Encoded_GPR_edx(), Immediate(uint64_t(Value0) >> 32)); \
7805 __ mov(IceType_i32, Encoded_GPR_ebx(), \
7806 Immediate(uint64_t(Value1) & 0xFFFFFFFF)); \
7807 __ mov(IceType_i32, Encoded_GPR_ecx(), Immediate(uint64_t(Value1) >> 32)); \
7808 __ cmpxchg8b(dwordAddress(T0), LockedOrNot); \
7809 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7810 \
7811 AssembledTest test = assemble(); \
7812 test.setQwordTo(T0, V0); \
7813 test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
7814 test.run(); \
7815 \
7816 if (V0 == (Value0)) { \
7817 ASSERT_EQ(uint64_t(Value1), test.contentsOfQword(T0)) << TestString; \
7818 ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
7819 } else { \
7820 ASSERT_EQ(uint64_t(ValueMem) & 0xFFFFFFFF, test.eax()) << TestString; \
7821 ASSERT_EQ((uint64_t(ValueMem) >> 32) & 0xFFFFFFFF, test.edx()) \
7822 << TestString; \
7823 ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
7824 } \
7825 reset(); \
7826 } while (0)
7827
7828 TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, NotLocked);
7829 TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, Locked);
7830 TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, NotLocked);
7831 TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, Locked);
7832
7833 #undef TestImpl
7834 }
7835
7836 TEST_F(AssemblerX8664LowLevelTest, Cmpxchg8b) {
7837 static constexpr bool NotLocked = false;
7838 static constexpr bool Locked = true;
7839
7840 // Ensures that cmpxchg8b emits a lock prefix accordingly.
7841 __ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked);
7842 static constexpr uint8_t ByteCountNotLocked = 7;
7843 ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
7844 verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
7845 0x01, 0x00);
7846 reset();
7847
7848 __ cmpxchg8b(Address::Absolute(0x1FF00), Locked);
7849 static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
7850 ASSERT_EQ(ByteCountLocked, codeBytesSize());
7851 verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
7852 0x01, 0x00);
7853 reset();
7854 }
7855
7856 TEST_F(AssemblerX8664Test, Cmpxchg) {
7857 static constexpr bool NotLocked = false;
7858 static constexpr bool Locked = true;
7859
7860 static constexpr uint32_t Mask8 = 0x000000FF;
7861 static constexpr uint32_t Mask16 = 0x0000FFFF;
7862 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7863
7864 #define TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, Size) \
7865 do { \
7866 static constexpr char TestString[] = \
7867 "(" #Value0 ", " #Src ", " #Value1 ", " #ValueMem ", " #LockedOrNot \
7868 ", " #Size ")"; \
7869 const uint32_t T0 = allocateDword(); \
7870 static constexpr uint32_t V0 = (ValueMem)&Mask##Size; \
7871 const uint32_t ZeroFlag = allocateDword(); \
7872 \
7873 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
7874 Immediate((Value0)&Mask##Size)); \
7875 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
7876 Immediate((Value1)&Mask##Size)); \
7877 __ cmpxchg(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src(), \
7878 LockedOrNot); \
7879 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7880 \
7881 AssembledTest test = assemble(); \
7882 test.setDwordTo(T0, V0); \
7883 test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
7884 test.run(); \
7885 \
7886 if (V0 == (Mask##Size & (Value0))) { \
7887 ASSERT_EQ(uint32_t((Value1)&Mask##Size), test.contentsOfDword(T0)) \
7888 << TestString; \
7889 ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
7890 } else { \
7891 ASSERT_EQ(uint32_t((ValueMem)&Mask##Size), test.eax()) << TestString; \
7892 ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
7893 } \
7894 reset(); \
7895 } while (0)
7896
7897 #define TestImplValue(Value0, Src, Value1, ValueMem, LockedOrNot) \
7898 do { \
7899 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 8); \
7900 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 16); \
7901 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 32); \
7902 } while (0)
7903
7904 #define TestImpl(Src, LockedOrNot) \
7905 do { \
7906 TestImplValue(0xFFFFFFFF, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
7907 TestImplValue(0x0FFF0F0F, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
7908 } while (0)
7909
7910 TestImpl(r2, Locked);
7911 TestImpl(r2, NotLocked);
7912 TestImpl(r3, Locked);
7913 TestImpl(r3, NotLocked);
7914 TestImpl(r4, Locked);
7915 TestImpl(r4, NotLocked);
7916 TestImpl(r5, Locked);
7917 TestImpl(r5, NotLocked);
7918 TestImpl(r6, Locked);
7919 TestImpl(r6, NotLocked);
7920 TestImpl(r7, Locked);
7921 TestImpl(r7, NotLocked);
7922 TestImpl(r8, Locked);
7923 TestImpl(r8, NotLocked);
7924 TestImpl(r10, Locked);
7925 TestImpl(r10, NotLocked);
7926 TestImpl(r11, Locked);
7927 TestImpl(r11, NotLocked);
7928 TestImpl(r12, Locked);
7929 TestImpl(r12, NotLocked);
7930 TestImpl(r13, Locked);
7931 TestImpl(r13, NotLocked);
7932 TestImpl(r14, Locked);
7933 TestImpl(r14, NotLocked);
7934 TestImpl(r15, Locked);
7935 TestImpl(r15, NotLocked);
7936
7937 #undef TestImpl
7938 #undef TestImplValue
7939 #undef TestImplAddrReg
7940 }
7941
7942 TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
7943 static constexpr bool NotLocked = false;
7944 static constexpr bool Locked = true;
7945
7946 // Ensures that cmpxchg emits a lock prefix accordingly.
7947 {
7948 __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7949 NotLocked);
7950 static constexpr uint8_t ByteCountNotLocked8 = 8;
7951 ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
7952 verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xB0, 0x35, 0x00,
7953 0xFF, 0x01, 0x00);
7954 reset();
7955
7956 __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7957 Locked);
7958 static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
7959 ASSERT_EQ(ByteCountLocked8, codeBytesSize());
7960 verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x44, 0x0F, 0xB0, 0x35,
7961 0x00, 0xFF, 0x01, 0x00);
7962 reset();
7963 }
7964
7965 {
7966 __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7967 NotLocked);
7968 static constexpr uint8_t ByteCountNotLocked16 = 9;
7969 ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
7970 verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x44, 0x0F, 0xB1, 0x35,
7971 0x00, 0xFF, 0x01, 0x00);
7972 reset();
7973
7974 __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7975 Locked);
7976 static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
7977 ASSERT_EQ(ByteCountLocked16, codeBytesSize());
7978 verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44, 0x0F, 0xB1,
7979 0x35, 0x00, 0xFF, 0x01, 0x00);
7980 reset();
7981 }
7982
7983 {
7984 __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7985 NotLocked);
7986 static constexpr uint8_t ByteCountNotLocked32 = 8;
7987 ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
7988 verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x44, 0x0F, 0xB1, 0x35, 0x00,
7989 0xFF, 0x01, 0x00);
7990 reset();
7991
7992 __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7993 Locked);
7994 static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
7995 ASSERT_EQ(ByteCountLocked32, codeBytesSize());
7996 verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x44, 0x0F, 0xB1, 0x35,
7997 0x00, 0xFF, 0x01, 0x00);
7998 reset();
7999 }
8000 }
8001
8002 TEST_F(AssemblerX8664Test, Set1ps) {
8003 #define TestImpl(Xmm, Src, Imm) \
8004 do { \
8005 __ set1ps(Encoded_Xmm_##Xmm(), Encoded_GPR_##Src(), Immediate(Imm)); \
8006 \
8007 AssembledTest test = assemble(); \
8008 test.run(); \
8009 \
8010 const Dqword Expected((uint64_t(Imm) << 32) | uint32_t(Imm), \
8011 (uint64_t(Imm) << 32) | uint32_t(Imm)); \
8012 ASSERT_EQ(Expected, test.Xmm<Dqword>()) \
8013 << "(" #Xmm ", " #Src ", " #Imm ")"; \
8014 reset(); \
8015 } while (0)
8016
8017 TestImpl(xmm0, r1, 1);
8018 TestImpl(xmm1, r2, 12);
8019 TestImpl(xmm2, r3, 22);
8020 TestImpl(xmm3, r4, 54);
8021 TestImpl(xmm4, r5, 80);
8022 TestImpl(xmm5, r6, 32);
8023 TestImpl(xmm6, r7, 55);
8024 TestImpl(xmm7, r8, 44);
8025 TestImpl(xmm8, r10, 10);
8026 TestImpl(xmm9, r11, 155);
8027 TestImpl(xmm10, r12, 165);
8028 TestImpl(xmm11, r13, 170);
8029 TestImpl(xmm12, r14, 200);
8030 TestImpl(xmm13, r15, 124);
8031 TestImpl(xmm14, r1, 101);
8032 TestImpl(xmm15, r2, 166);
8033
8034 #undef TestImpl
8035 }
8036
8037 #undef __
8038
8039 } // end of anonymous namespace
8040 } // end of namespace X8664
8041 } // end of namespace Ice
OLDNEW
« src/IceTargetLoweringX8664Traits.h ('K') | « unittest/IceAssemblerX8632Test.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698