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

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: Addresses comments; changes emitRex.* logic. 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
« src/IceRegistersX8664.h ('K') | « unittest/IceAssemblerX8632Test.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/unittest/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 // movups %xmm3, {152 + $ScratchpadOffset}(%rbp)
1334 // movups %xmm4, {160 + $ScratchpadOffset}(%rbp)
1335 // movups %xmm5, {168 + $ScratchpadOffset}(%rbp)
1336 // movups %xmm6, {176 + $ScratchpadOffset}(%rbp)
1337 // movups %xmm7, {184 + $ScratchpadOffset}(%rbp)
1338 // movups %xmm8, {192 + $ScratchpadOffset}(%rbp)
1339 // movups %xmm9, {200 + $ScratchpadOffset}(%rbp)
1340 // movups %xmm10, {208 + $ScratchpadOffset}(%rbp)
1341 // movups %xmm11, {216 + $ScratchpadOffset}(%rbp)
1342 // movups %xmm12, {224 + $ScratchpadOffset}(%rbp)
1343 // movups %xmm13, {232 + $ScratchpadOffset}(%rbp)
1344 // movups %xmm14, {240 + $ScratchpadOffset}(%rbp)
1345 // movups %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 uint64_t Mask8 = 0x000000FF;
2790 static constexpr uint64_t Mask16 = 0x0000FFFF;
2791 static constexpr uint64_t Mask32 = 0xFFFFFFFF;
2792
2793 #define TestImplRegReg(Dst, Src, Suffix, Size) \
2794 do { \
2795 const uint32_t T0 = allocateDqword(); \
2796 static constexpr uint64_t V0 = 0xAAAAAAAAAAAAAAAAull; \
2797 static constexpr uint64_t Value = (0xC0BEBEEF) & 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((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \
2806 << "(" #Dst ", " #Src ", " #Size ")"; \
2807 reset(); \
2808 } while (0)
2809
2810 #define TestImplRegAddr(Dst, Suffix, Size) \
2811 do { \
2812 const uint32_t T0 = allocateDqword(); \
2813 static constexpr uint64_t V0 = 0xC0BEBEEF & Mask##Size; \
2814 static constexpr uint64_t Value = (0xC0BEBEEF) & Mask##Size; \
2815 __ movsx(IceType_i##Size, Encoded_GPR_##Dst##d(), dwordAddress(T0)); \
2816 \
2817 AssembledTest test = assemble(); \
2818 test.setQwordTo(T0, V0); \
2819 test.run(); \
2820 ASSERT_EQ((uint64_t(-1) & ~Mask##Size) | Value, test.Dst##q()) \
2821 << "(" #Dst ", Addr, " #Size ")"; \
2822 reset(); \
2823 } while (0)
2824
2825 #define TestImpl(Dst, Src) \
2826 do { \
2827 TestImplRegReg(Dst, Src, l, 8); \
2828 TestImplRegAddr(Dst, l, 8); \
2829 TestImplRegReg(Dst, Src, w, 16); \
2830 TestImplRegAddr(Dst, w, 16); \
2831 TestImplRegReg(Dst, Src, w, 32); \
2832 TestImplRegAddr(Dst, w, 32); \
2833 } while (0)
2834
2835 TestImpl(r1, r2);
2836 TestImpl(r2, r3);
2837 TestImpl(r3, r4);
2838 TestImpl(r4, r5);
2839 TestImpl(r5, r6);
2840 TestImpl(r6, r7);
2841 TestImpl(r7, r8);
2842 TestImpl(r8, r10);
2843 TestImpl(r10, r11);
2844 TestImpl(r11, r12);
2845 TestImpl(r12, r13);
2846 TestImpl(r13, r14);
2847 TestImpl(r14, r15);
2848 TestImpl(r15, r1);
2849
2850 #undef TestImpl
2851 #undef TestImplRegAddr
2852 #undef TestImplRegReg
2853 }
2854
2855 TEST_F(AssemblerX8664Test, Lea) {
2856 #define TestLeaBaseDisp(Base, BaseValue, Disp, Dst) \
2857 do { \
2858 static constexpr char TestString[] = \
2859 "(" #Base ", " #BaseValue ", " #Dst ")"; \
2860 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
2861 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
2862 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
2863 } \
2864 __ lea(IceType_i32, Encoded_GPR_##Dst(), \
2865 Address(Encoded_GPR_##Base(), Disp)); \
2866 AssembledTest test = assemble(); \
2867 test.run(); \
2868 ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d()) \
2869 << TestString << " with Disp " << Disp; \
2870 reset(); \
2871 } while (0)
2872
2873 #define TestLeaIndex32bitDisp(Index, IndexValue, Disp, Dst0, Dst1, Dst2, Dst3) \
2874 do { \
2875 static constexpr char TestString[] = \
2876 "(" #Index ", " #IndexValue ", " #Dst0 ", " #Dst1 ", " #Dst2 \
2877 ", " #Dst3 ")"; \
2878 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
2879 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
2880 } \
2881 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
2882 Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp)); \
2883 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
2884 Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp)); \
2885 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
2886 Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp)); \
2887 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
2888 Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp)); \
2889 AssembledTest test = assemble(); \
2890 test.run(); \
2891 ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d()) \
2892 << TestString << " " << Disp; \
2893 ASSERT_EQ((test.Index##d() << Traits::TIMES_2) + (Disp), test.Dst1##d()) \
2894 << TestString << " " << Disp; \
2895 ASSERT_EQ((test.Index##d() << Traits::TIMES_4) + (Disp), test.Dst2##d()) \
2896 << TestString << " " << Disp; \
2897 ASSERT_EQ((test.Index##d() << Traits::TIMES_8) + (Disp), test.Dst3##d()) \
2898 << TestString << " " << Disp; \
2899 reset(); \
2900 } while (0)
2901
2902 #define TestLeaBaseIndexDisp(Base, BaseValue, Index, IndexValue, Disp, Dst0, \
2903 Dst1, Dst2, Dst3) \
2904 do { \
2905 static constexpr char TestString[] = \
2906 "(" #Base ", " #BaseValue ", " #Index ", " #IndexValue ", " #Dst0 \
2907 ", " #Dst1 ", " #Dst2 ", " #Dst3 ")"; \
2908 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
2909 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
2910 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
2911 } \
2912 \
2913 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
2914 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
2915 } \
2916 \
2917 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
2918 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2919 Traits::TIMES_1, Disp)); \
2920 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
2921 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2922 Traits::TIMES_2, Disp)); \
2923 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
2924 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2925 Traits::TIMES_4, Disp)); \
2926 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
2927 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
2928 Traits::TIMES_8, Disp)); \
2929 AssembledTest test = assemble(); \
2930 test.run(); \
2931 uint32_t ExpectedIndexValue = test.Index(); \
2932 if (Encoded_GPR_##Index() == Encoded_GPR_esp()) { \
2933 ExpectedIndexValue = 0; \
2934 } \
2935 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_1) + \
2936 (Disp), \
2937 test.Dst0##d()) \
2938 << TestString << " " << Disp; \
2939 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_2) + \
2940 (Disp), \
2941 test.Dst1##d()) \
2942 << TestString << " " << Disp; \
2943 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_4) + \
2944 (Disp), \
2945 test.Dst2##d()) \
2946 << TestString << " " << Disp; \
2947 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_8) + \
2948 (Disp), \
2949 test.Dst3##d()) \
2950 << TestString << " " << Disp; \
2951 reset(); \
2952 } while (0)
2953
2954 for (const int32_t Disp :
2955 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2956 TestLeaBaseDisp(r0, 0x22080Fu, Disp, r1);
2957 TestLeaBaseDisp(r1, 0x10000Fu, Disp, r2);
2958 TestLeaBaseDisp(r2, 0x20000Fu, Disp, r3);
2959 TestLeaBaseDisp(r3, 0x30000Fu, Disp, r4);
2960 TestLeaBaseDisp(r4, 0x40000Fu, Disp, r5);
2961 TestLeaBaseDisp(r5, 0x50000Fu, Disp, r6);
2962 TestLeaBaseDisp(r6, 0x60000Fu, Disp, r7);
2963 TestLeaBaseDisp(r7, 0x11000Fu, Disp, r8);
2964 TestLeaBaseDisp(r8, 0x11200Fu, Disp, r10);
2965 TestLeaBaseDisp(r9, 0x000000u, Disp, r10);
2966 TestLeaBaseDisp(r10, 0x22000Fu, Disp, r11);
2967 TestLeaBaseDisp(r11, 0x22030Fu, Disp, r12);
2968 TestLeaBaseDisp(r12, 0x22040Fu, Disp, r13);
2969 TestLeaBaseDisp(r13, 0x22050Fu, Disp, r14);
2970 TestLeaBaseDisp(r14, 0x22060Fu, Disp, r15);
2971 TestLeaBaseDisp(r15, 0x22070Fu, Disp, r1);
2972 }
2973
2974 // esp is not a valid index register.
2975 // ebp is not valid in this addressing mode (rm = 0).
2976 for (const int32_t Disp :
2977 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2978 TestLeaIndex32bitDisp(r1, 0x2000u, Disp, r2, r3, r4, r6);
2979 TestLeaIndex32bitDisp(r2, 0x4010u, Disp, r3, r4, r6, r7);
2980 TestLeaIndex32bitDisp(r3, 0x6020u, Disp, r4, r6, r7, r5);
2981 TestLeaIndex32bitDisp(r4, 0x8030u, Disp, r6, r7, r5, r10);
2982 TestLeaIndex32bitDisp(r6, 0xA040u, Disp, r7, r5, r10, r1);
2983 TestLeaIndex32bitDisp(r7, 0xC050u, Disp, r5, r10, r1, r11);
2984 TestLeaIndex32bitDisp(r8, 0xC060u, Disp, r10, r1, r11, r12);
2985 TestLeaIndex32bitDisp(r9, 0x0000u, Disp, r1, r11, r12, r13);
2986 TestLeaIndex32bitDisp(r10, 0xC008u, Disp, r11, r12, r13, r14);
2987 TestLeaIndex32bitDisp(r11, 0xC009u, Disp, r12, r13, r14, r15);
2988 TestLeaIndex32bitDisp(r12, 0xC00Au, Disp, r13, r14, r15, r1);
2989 TestLeaIndex32bitDisp(r13, 0xC00Bu, Disp, r14, r15, r1, r2);
2990 TestLeaIndex32bitDisp(r14, 0xC00Cu, Disp, r15, r1, r2, r3);
2991 TestLeaIndex32bitDisp(r15, 0xC00Du, Disp, r1, r2, r3, r4);
2992 }
2993
2994 for (const int32_t Disp :
2995 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
2996 TestLeaBaseIndexDisp(r1, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
2997 TestLeaBaseIndexDisp(r2, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
2998 TestLeaBaseIndexDisp(r3, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r5);
2999 TestLeaBaseIndexDisp(r4, 0x400000u, r6, 0x300u, Disp, r7, r8, r5, r10);
3000 TestLeaBaseIndexDisp(r6, 0x500000u, r7, 0x200u, Disp, r8, r5, r10, r11);
3001 TestLeaBaseIndexDisp(r7, 0x600000u, r8, 0x100u, Disp, r5, r10, r11, r12);
3002 TestLeaBaseIndexDisp(r8, 0x600000u, r9, 0x1A0u, Disp, r10, r11, r12, r13);
3003 TestLeaBaseIndexDisp(r9, 0x000000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3004 TestLeaBaseIndexDisp(r10, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3005 TestLeaBaseIndexDisp(r11, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3006 TestLeaBaseIndexDisp(r12, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3007 TestLeaBaseIndexDisp(r13, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3008 TestLeaBaseIndexDisp(r14, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
3009 TestLeaBaseIndexDisp(r15, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3010
3011 TestLeaBaseIndexDisp(r0, 0, r2, 0x600u, Disp, r3, r4, r6, r7);
3012 TestLeaBaseIndexDisp(r0, 0, r3, 0x500u, Disp, r4, r6, r7, r8);
3013 TestLeaBaseIndexDisp(r0, 0, r4, 0x400u, Disp, r6, r7, r8, r5);
3014 TestLeaBaseIndexDisp(r0, 0, r6, 0x300u, Disp, r7, r8, r5, r10);
3015 TestLeaBaseIndexDisp(r0, 0, r7, 0x200u, Disp, r8, r5, r10, r11);
3016 TestLeaBaseIndexDisp(r0, 0, r8, 0x100u, Disp, r5, r10, r11, r12);
3017 TestLeaBaseIndexDisp(r0, 0, r9, 0x000u, Disp, r10, r11, r12, r13);
3018 TestLeaBaseIndexDisp(r0, 0, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3019 TestLeaBaseIndexDisp(r0, 0, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3020 TestLeaBaseIndexDisp(r0, 0, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3021 TestLeaBaseIndexDisp(r0, 0, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3022 TestLeaBaseIndexDisp(r0, 0, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3023 TestLeaBaseIndexDisp(r0, 0, r15, 0x10Au, Disp, r1, r2, r3, r4);
3024 TestLeaBaseIndexDisp(r0, 0, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3025
3026 TestLeaBaseIndexDisp(r5, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
3027 TestLeaBaseIndexDisp(r5, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
3028 TestLeaBaseIndexDisp(r5, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r1);
3029 TestLeaBaseIndexDisp(r5, 0x400000u, r6, 0x300u, Disp, r7, r8, r1, r10);
3030 TestLeaBaseIndexDisp(r5, 0x500000u, r7, 0x200u, Disp, r8, r1, r10, r11);
3031 TestLeaBaseIndexDisp(r5, 0x600000u, r8, 0x100u, Disp, r1, r10, r11, r12);
3032 TestLeaBaseIndexDisp(r5, 0x600000u, r9, 0x000u, Disp, r10, r11, r12, r13);
3033 TestLeaBaseIndexDisp(r5, 0x601000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
3034 TestLeaBaseIndexDisp(r5, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
3035 TestLeaBaseIndexDisp(r5, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
3036 TestLeaBaseIndexDisp(r5, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
3037 TestLeaBaseIndexDisp(r5, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
3038 TestLeaBaseIndexDisp(r5, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
3039 TestLeaBaseIndexDisp(r5, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
3040
3041 TestLeaBaseIndexDisp(r2, 0x100000u, r5, 0x600u, Disp, r3, r4, r6, r7);
3042 TestLeaBaseIndexDisp(r3, 0x200000u, r5, 0x500u, Disp, r4, r6, r7, r8);
3043 TestLeaBaseIndexDisp(r4, 0x300000u, r5, 0x400u, Disp, r6, r7, r8, r1);
3044 TestLeaBaseIndexDisp(r6, 0x400000u, r5, 0x300u, Disp, r7, r8, r1, r10);
3045 TestLeaBaseIndexDisp(r7, 0x500000u, r5, 0x200u, Disp, r8, r1, r10, r11);
3046 TestLeaBaseIndexDisp(r8, 0x600000u, r5, 0x100u, Disp, r1, r10, r11, r12);
3047 TestLeaBaseIndexDisp(r9, 0x000000u, r5, 0x1A0u, Disp, r10, r11, r12, r13);
3048 TestLeaBaseIndexDisp(r10, 0x601000u, r5, 0x1B0u, Disp, r11, r12, r13, r14);
3049 TestLeaBaseIndexDisp(r11, 0x602000u, r5, 0x1C0u, Disp, r12, r13, r14, r15);
3050 TestLeaBaseIndexDisp(r12, 0x603000u, r5, 0x1D0u, Disp, r13, r14, r15, r1);
3051 TestLeaBaseIndexDisp(r13, 0x604000u, r5, 0x1E0u, Disp, r14, r15, r1, r2);
3052 TestLeaBaseIndexDisp(r14, 0x605000u, r5, 0x1F0u, Disp, r15, r1, r2, r3);
3053 TestLeaBaseIndexDisp(r15, 0x606000u, r5, 0x10Au, Disp, r1, r2, r3, r4);
3054 TestLeaBaseIndexDisp(r1, 0x607000u, r5, 0x10Bu, Disp, r2, r3, r4, r6);
3055
3056 TestLeaBaseIndexDisp(r0, 0, r5, 0xC0BEBEEF, Disp, r2, r3, r4, r6);
3057 }
3058
3059 // Absolute addressing mode is tested in the Low Level tests. The encoding used
3060 // by the assembler has different meanings in x86-32 and x86-64.
3061 #undef TestLeaBaseIndexDisp
3062 #undef TestLeaScaled32bitDisp
3063 #undef TestLeaBaseDisp
3064 }
3065
3066 TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
3067 #define TestLeaAbsolute(Dst, Value) \
3068 do { \
3069 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
3070 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
3071 Address(Address::ABSOLUTE, Value)); \
3072 static constexpr uint32_t ByteCount = 6; \
3073 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
3074 static constexpr uint8_t Opcode = 0x8D; \
3075 static constexpr uint8_t ModRM = \
3076 /*mod=*/0x00 | /*reg*/ (GPRRegister::Encoded_Reg_##Dst << 3) | \
3077 /*rm*/ GPRRegister::Encoded_Reg_ebp; \
3078 ASSERT_TRUE(verifyBytes<ByteCount>( \
3079 codeBytes(), Opcode, ModRM, (Value)&0xFF, (Value >> 8) & 0xFF, \
3080 (Value >> 16) & 0xFF, (Value >> 24) & 0xFF)); \
3081 reset(); \
3082 } while (0)
3083
3084 TestLeaAbsolute(eax, 0x11BEEF22);
3085 TestLeaAbsolute(ebx, 0x33BEEF44);
3086 TestLeaAbsolute(ecx, 0x55BEEF66);
3087 TestLeaAbsolute(edx, 0x77BEEF88);
3088 TestLeaAbsolute(esi, 0x99BEEFAA);
3089 TestLeaAbsolute(edi, 0xBBBEEFBB);
3090
3091 #undef TesLeaAbsolute
3092 }
3093
3094 TEST_F(AssemblerX8664Test, Cmov) {
3095 #define TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
3096 do { \
3097 static constexpr char TestString[] = \
3098 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \
3099 ", " #Value1 ")"; \
3100 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
3101 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
3102 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
3103 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
3104 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
3105 Encoded_GPR_##Src1()); \
3106 \
3107 AssembledTest test = assemble(); \
3108 test.run(); \
3109 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
3110 \
3111 reset(); \
3112 } while (0)
3113
3114 #define TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1) \
3115 do { \
3116 static constexpr char TestString[] = \
3117 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 \
3118 ", Addr, " #Value1 ")"; \
3119 const uint32_t T0 = allocateDword(); \
3120 const uint32_t V0 = Value1; \
3121 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
3122 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(Value0)); \
3123 __ cmp(IceType_i32, Encoded_GPR_##Src0(), dwordAddress(T0)); \
3124 __ cmov(IceType_i32, Cond::Br_##C, Encoded_GPR_##Dest(), \
3125 dwordAddress(T0)); \
3126 \
3127 AssembledTest test = assemble(); \
3128 test.setDwordTo(T0, V0); \
3129 test.run(); \
3130 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) << TestString; \
3131 \
3132 reset(); \
3133 } while (0)
3134
3135 #define TestValue(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
3136 do { \
3137 TestRegReg(C, Dest, IsTrue, Src0, Value0, Src1, Value1); \
3138 TestRegAddr(C, Dest, IsTrue, Src0, Value0, Value1); \
3139 } while (0)
3140
3141 #define TestImpl(Dest, Src0, Src1) \
3142 do { \
3143 TestValue(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3144 TestValue(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \
3145 TestValue(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \
3146 TestValue(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3147 TestValue(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \
3148 TestValue(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3149 TestValue(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3150 TestValue(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3151 TestValue(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \
3152 TestValue(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \
3153 TestValue(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3154 TestValue(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \
3155 TestValue(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3156 TestValue(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3157 TestValue(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3158 TestValue(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3159 TestValue(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3160 TestValue(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3161 TestValue(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3162 TestValue(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3163 TestValue(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3164 TestValue(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3165 TestValue(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3166 TestValue(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3167 TestValue(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3168 TestValue(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3169 TestValue(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
3170 TestValue(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
3171 TestValue(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
3172 TestValue(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
3173 } while (0)
3174
3175 TestImpl(r1, r2, r3);
3176
3177 #undef TestImpl
3178 #undef TestValue
3179 #undef TestRegAddr
3180 #undef TestRegReg
3181 }
3182
3183 TEST_F(AssemblerX8664LowLevelTest, RepMovsb) {
3184 __ rep_movsb();
3185
3186 static constexpr uint32_t ByteCount = 2;
3187 static constexpr uint8_t Prefix = 0xF3;
3188 static constexpr uint8_t Opcode = 0xA4;
3189
3190 ASSERT_EQ(ByteCount, codeBytesSize());
3191 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode);
3192 }
3193
3194 TEST_F(AssemblerX8664Test, MovssXmmAddr) {
3195 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \
3196 do { \
3197 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3198 "Invalid fp length #FloatLength"); \
3199 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3200 \
3201 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
3202 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3203 const uint32_t T0 = allocateQword(); \
3204 const Type V0 = Value; \
3205 \
3206 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
3207 \
3208 AssembledTest test = assemble(); \
3209 if (IsDouble) { \
3210 test.setQwordTo(T0, static_cast<double>(V0)); \
3211 } else { \
3212 test.setDwordTo(T0, static_cast<float>(V0)); \
3213 } \
3214 test.run(); \
3215 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
3216 << Value; \
3217 reset(); \
3218 } while (0)
3219
3220 #define TestMovssXmmAddr(FloatLength) \
3221 do { \
3222 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3223 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3224 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \
3225 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \
3226 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \
3227 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \
3228 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \
3229 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \
3230 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \
3231 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \
3232 TestMovssXmmAddrFloatLength(FloatLength, xmm8, Value); \
3233 TestMovssXmmAddrFloatLength(FloatLength, xmm9, Value); \
3234 TestMovssXmmAddrFloatLength(FloatLength, xmm10, Value); \
3235 TestMovssXmmAddrFloatLength(FloatLength, xmm11, Value); \
3236 TestMovssXmmAddrFloatLength(FloatLength, xmm12, Value); \
3237 TestMovssXmmAddrFloatLength(FloatLength, xmm13, Value); \
3238 TestMovssXmmAddrFloatLength(FloatLength, xmm14, Value); \
3239 TestMovssXmmAddrFloatLength(FloatLength, xmm15, Value); \
3240 } \
3241 } while (0)
3242
3243 TestMovssXmmAddr(32);
3244 TestMovssXmmAddr(64);
3245
3246 #undef TestMovssXmmAddr
3247 #undef TestMovssXmmAddrType
3248 }
3249
3250 TEST_F(AssemblerX8664Test, MovssAddrXmm) {
3251 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \
3252 do { \
3253 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3254 "Invalid fp length #FloatLength"); \
3255 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3256 \
3257 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \
3258 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3259 const uint32_t T0 = allocateQword(); \
3260 const Type V0 = Value; \
3261 const uint32_t T1 = allocateQword(); \
3262 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
3263 "f" #FloatLength " does not have quiet nan."); \
3264 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
3265 \
3266 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Xmm(), dwordAddress(T0)); \
3267 \
3268 AssembledTest test = assemble(); \
3269 if (IsDouble) { \
3270 test.setQwordTo(T0, static_cast<double>(V0)); \
3271 test.setQwordTo(T1, static_cast<double>(V1)); \
3272 } else { \
3273 test.setDwordTo(T0, static_cast<float>(V0)); \
3274 test.setDwordTo(T1, static_cast<float>(V1)); \
3275 } \
3276 test.run(); \
3277 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \
3278 << Value; \
3279 reset(); \
3280 } while (0)
3281
3282 #define TestMovssAddrXmm(FloatLength) \
3283 do { \
3284 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3285 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3286 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \
3287 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \
3288 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \
3289 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \
3290 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \
3291 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \
3292 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \
3293 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \
3294 TestMovssAddrXmmFloatLength(FloatLength, xmm8, Value); \
3295 TestMovssAddrXmmFloatLength(FloatLength, xmm9, Value); \
3296 TestMovssAddrXmmFloatLength(FloatLength, xmm10, Value); \
3297 TestMovssAddrXmmFloatLength(FloatLength, xmm11, Value); \
3298 TestMovssAddrXmmFloatLength(FloatLength, xmm12, Value); \
3299 TestMovssAddrXmmFloatLength(FloatLength, xmm13, Value); \
3300 TestMovssAddrXmmFloatLength(FloatLength, xmm14, Value); \
3301 TestMovssAddrXmmFloatLength(FloatLength, xmm15, Value); \
3302 } \
3303 } while (0)
3304
3305 TestMovssAddrXmm(32);
3306 TestMovssAddrXmm(64);
3307
3308 #undef TestMovssAddrXmm
3309 #undef TestMovssAddrXmmType
3310 }
3311
3312 TEST_F(AssemblerX8664Test, MovssXmmXmm) {
3313 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \
3314 do { \
3315 static_assert((FloatLength) == 32 || (FloatLength) == 64, \
3316 "Invalid fp length #FloatLength"); \
3317 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3318 \
3319 static constexpr char TestString[] = \
3320 "(" #FloatLength ", " #Src ", " #Dst ")"; \
3321 static constexpr bool IsDouble = std::is_same<Type, double>::value; \
3322 const uint32_t T0 = allocateQword(); \
3323 const Type V0 = Value; \
3324 const uint32_t T1 = allocateQword(); \
3325 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \
3326 "f" #FloatLength " does not have quiet nan."); \
3327 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \
3328 \
3329 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3330 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3331 __ movss(IceType_f##FloatLength, Encoded_Xmm_##Dst(), \
3332 Encoded_Xmm_##Src()); \
3333 \
3334 AssembledTest test = assemble(); \
3335 if (IsDouble) { \
3336 test.setQwordTo(T0, static_cast<double>(V0)); \
3337 test.setQwordTo(T1, static_cast<double>(V1)); \
3338 } else { \
3339 test.setDwordTo(T0, static_cast<float>(V0)); \
3340 test.setDwordTo(T1, static_cast<float>(V1)); \
3341 } \
3342 test.run(); \
3343 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \
3344 << Value; \
3345 reset(); \
3346 } while (0)
3347
3348 #define TestMovssXmmXmm(FloatLength) \
3349 do { \
3350 using Type = std::conditional<FloatLength == 32, float, double>::type; \
3351 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \
3352 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \
3353 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \
3354 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \
3355 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \
3356 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \
3357 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \
3358 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \
3359 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm8, Value); \
3360 TestMovssXmmXmmFloatLength(FloatLength, xmm8, xmm9, Value); \
3361 TestMovssXmmXmmFloatLength(FloatLength, xmm9, xmm10, Value); \
3362 TestMovssXmmXmmFloatLength(FloatLength, xmm10, xmm11, Value); \
3363 TestMovssXmmXmmFloatLength(FloatLength, xmm11, xmm12, Value); \
3364 TestMovssXmmXmmFloatLength(FloatLength, xmm12, xmm13, Value); \
3365 TestMovssXmmXmmFloatLength(FloatLength, xmm13, xmm14, Value); \
3366 TestMovssXmmXmmFloatLength(FloatLength, xmm14, xmm15, Value); \
3367 TestMovssXmmXmmFloatLength(FloatLength, xmm15, xmm0, Value); \
3368 } \
3369 } while (0)
3370
3371 TestMovssXmmXmm(32);
3372 TestMovssXmmXmm(64);
3373
3374 #undef TestMovssXmmXmm
3375 #undef TestMovssXmmXmmType
3376 }
3377
3378 TEST_F(AssemblerX8664Test, MovdToXmm) {
3379 #define TestMovdXmmReg(Src, Dst, Value) \
3380 do { \
3381 assert(((Value)&0xFFFFFFFF) == (Value)); \
3382 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3383 const uint32_t T0 = allocateQword(); \
3384 const uint64_t V0 = 0xFFFFFFFF00000000ull; \
3385 \
3386 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value)); \
3387 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3388 __ movd(Encoded_Xmm_##Dst(), Encoded_GPR_##Src()); \
3389 \
3390 AssembledTest test = assemble(); \
3391 \
3392 test.setQwordTo(T0, V0); \
3393 test.run(); \
3394 \
3395 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3396 << Value; \
3397 reset(); \
3398 } while (0)
3399
3400 #define TestMovdXmmAddr(Dst, Value) \
3401 do { \
3402 assert(((Value)&0xFFFFFFFF) == (Value)); \
3403 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3404 const uint32_t T0 = allocateQword(); \
3405 const uint32_t V0 = Value; \
3406 const uint32_t T1 = allocateQword(); \
3407 const uint64_t V1 = 0xFFFFFFFF00000000ull; \
3408 \
3409 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3410 __ movd(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3411 \
3412 AssembledTest test = assemble(); \
3413 \
3414 test.setDwordTo(T0, V0); \
3415 test.setQwordTo(T1, V1); \
3416 test.run(); \
3417 \
3418 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3419 << Value; \
3420 reset(); \
3421 } while (0)
3422
3423 #define TestMovd(Dst) \
3424 do { \
3425 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
3426 TestMovdXmmReg(r1, Dst, Value); \
3427 TestMovdXmmReg(r2, Dst, Value); \
3428 TestMovdXmmReg(r3, Dst, Value); \
3429 TestMovdXmmReg(r4, Dst, Value); \
3430 TestMovdXmmReg(r5, Dst, Value); \
3431 TestMovdXmmReg(r6, Dst, Value); \
3432 TestMovdXmmReg(r7, Dst, Value); \
3433 TestMovdXmmReg(r8, Dst, Value); \
3434 TestMovdXmmReg(r10, Dst, Value); \
3435 TestMovdXmmReg(r11, Dst, Value); \
3436 TestMovdXmmReg(r12, Dst, Value); \
3437 TestMovdXmmReg(r13, Dst, Value); \
3438 TestMovdXmmReg(r14, Dst, Value); \
3439 TestMovdXmmReg(r15, Dst, Value); \
3440 TestMovdXmmAddr(Dst, Value); \
3441 } \
3442 } while (0)
3443
3444 TestMovd(xmm0);
3445 TestMovd(xmm1);
3446 TestMovd(xmm2);
3447 TestMovd(xmm3);
3448 TestMovd(xmm4);
3449 TestMovd(xmm5);
3450 TestMovd(xmm6);
3451 TestMovd(xmm7);
3452 TestMovd(xmm8);
3453 TestMovd(xmm9);
3454 TestMovd(xmm10);
3455 TestMovd(xmm11);
3456 TestMovd(xmm12);
3457 TestMovd(xmm13);
3458 TestMovd(xmm14);
3459 TestMovd(xmm15);
3460
3461 #undef TestMovdXmmAddr
3462 #undef TestMovdXmmReg
3463 #undef TestMovd
3464 }
3465
3466 TEST_F(AssemblerX8664Test, MovdFromXmm) {
3467 #define TestMovdRegXmm(Src, Dst, Value) \
3468 do { \
3469 assert(((Value)&0xFFFFFFFF) == (Value)); \
3470 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3471 const uint32_t T0 = allocateDword(); \
3472 const uint32_t V0 = Value; \
3473 \
3474 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3475 __ movd(Encoded_GPR_##Dst(), Encoded_Xmm_##Src()); \
3476 \
3477 AssembledTest test = assemble(); \
3478 \
3479 test.setDwordTo(T0, V0); \
3480 test.run(); \
3481 \
3482 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \
3483 << Value; \
3484 reset(); \
3485 } while (0)
3486
3487 #define TestMovdAddrXmm(Src, Value) \
3488 do { \
3489 assert(((Value)&0xFFFFFFFF) == (Value)); \
3490 static constexpr char TestString[] = "(" #Src ", Addr)"; \
3491 const uint32_t T0 = allocateDword(); \
3492 const uint32_t V0 = Value; \
3493 const uint32_t T1 = allocateDword(); \
3494 const uint32_t V1 = ~(Value); \
3495 \
3496 __ movss(IceType_f64, Encoded_Xmm_##Src(), dwordAddress(T0)); \
3497 __ movd(dwordAddress(T1), Encoded_Xmm_##Src()); \
3498 \
3499 AssembledTest test = assemble(); \
3500 \
3501 test.setDwordTo(T0, V0); \
3502 test.setDwordTo(T1, V1); \
3503 test.run(); \
3504 \
3505 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \
3506 << Value; \
3507 reset(); \
3508 } while (0)
3509
3510 #define TestMovd(Src) \
3511 do { \
3512 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \
3513 TestMovdRegXmm(Src, r1, Value); \
3514 TestMovdRegXmm(Src, r2, Value); \
3515 TestMovdRegXmm(Src, r3, Value); \
3516 TestMovdRegXmm(Src, r4, Value); \
3517 TestMovdRegXmm(Src, r5, Value); \
3518 TestMovdRegXmm(Src, r6, Value); \
3519 TestMovdRegXmm(Src, r7, Value); \
3520 TestMovdRegXmm(Src, r8, Value); \
3521 TestMovdRegXmm(Src, r10, Value); \
3522 TestMovdRegXmm(Src, r11, Value); \
3523 TestMovdRegXmm(Src, r12, Value); \
3524 TestMovdRegXmm(Src, r13, Value); \
3525 TestMovdRegXmm(Src, r14, Value); \
3526 TestMovdRegXmm(Src, r15, Value); \
3527 TestMovdAddrXmm(Src, Value); \
3528 } \
3529 } while (0)
3530
3531 TestMovd(xmm0);
3532 TestMovd(xmm1);
3533 TestMovd(xmm2);
3534 TestMovd(xmm3);
3535 TestMovd(xmm4);
3536 TestMovd(xmm5);
3537 TestMovd(xmm6);
3538 TestMovd(xmm7);
3539 TestMovd(xmm8);
3540 TestMovd(xmm9);
3541 TestMovd(xmm10);
3542 TestMovd(xmm11);
3543 TestMovd(xmm12);
3544 TestMovd(xmm13);
3545 TestMovd(xmm14);
3546 TestMovd(xmm15);
3547
3548 #undef TestMovdAddrXmm
3549 #undef TestMovdRegXmm
3550 #undef TestMovd
3551 }
3552
3553 TEST_F(AssemblerX8664Test, MovqXmmAddr) {
3554 #define TestMovd(Dst, Value) \
3555 do { \
3556 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3557 const uint32_t T0 = allocateQword(); \
3558 const uint64_t V0 = Value; \
3559 const uint32_t T1 = allocateQword(); \
3560 const uint64_t V1 = ~(Value); \
3561 \
3562 __ movss(IceType_f64, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3563 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3564 \
3565 AssembledTest test = assemble(); \
3566 \
3567 test.setQwordTo(T0, V0); \
3568 test.setQwordTo(T1, V1); \
3569 test.run(); \
3570 \
3571 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3572 << Value; \
3573 reset(); \
3574 } while (0)
3575
3576 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3577 TestMovd(xmm0, Value);
3578 TestMovd(xmm1, Value);
3579 TestMovd(xmm2, Value);
3580 TestMovd(xmm3, Value);
3581 TestMovd(xmm4, Value);
3582 TestMovd(xmm5, Value);
3583 TestMovd(xmm6, Value);
3584 TestMovd(xmm7, Value);
3585 TestMovd(xmm8, Value);
3586 TestMovd(xmm9, Value);
3587 TestMovd(xmm10, Value);
3588 TestMovd(xmm11, Value);
3589 TestMovd(xmm12, Value);
3590 TestMovd(xmm13, Value);
3591 TestMovd(xmm14, Value);
3592 TestMovd(xmm15, Value);
3593 }
3594
3595 #undef TestMovd
3596 }
3597
3598 TEST_F(AssemblerX8664Test, MovqAddrXmm) {
3599 #define TestMovd(Dst, Value) \
3600 do { \
3601 static constexpr char TestString[] = "(" #Dst ", Addr)"; \
3602 const uint32_t T0 = allocateQword(); \
3603 const uint64_t V0 = Value; \
3604 const uint32_t T1 = allocateQword(); \
3605 const uint64_t V1 = ~(Value); \
3606 \
3607 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3608 __ movq(dwordAddress(T1), Encoded_Xmm_##Dst()); \
3609 \
3610 AssembledTest test = assemble(); \
3611 \
3612 test.setQwordTo(T0, V0); \
3613 test.setQwordTo(T1, V1); \
3614 test.run(); \
3615 \
3616 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3617 << Value; \
3618 reset(); \
3619 } while (0)
3620
3621 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3622 TestMovd(xmm0, Value);
3623 TestMovd(xmm1, Value);
3624 TestMovd(xmm2, Value);
3625 TestMovd(xmm3, Value);
3626 TestMovd(xmm4, Value);
3627 TestMovd(xmm5, Value);
3628 TestMovd(xmm6, Value);
3629 TestMovd(xmm7, Value);
3630 TestMovd(xmm8, Value);
3631 TestMovd(xmm9, Value);
3632 TestMovd(xmm10, Value);
3633 TestMovd(xmm11, Value);
3634 TestMovd(xmm12, Value);
3635 TestMovd(xmm13, Value);
3636 TestMovd(xmm14, Value);
3637 TestMovd(xmm15, Value);
3638 }
3639
3640 #undef TestMovd
3641 }
3642
3643 TEST_F(AssemblerX8664Test, MovqXmmXmm) {
3644 #define TestMovd(Src, Dst, Value) \
3645 do { \
3646 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \
3647 const uint32_t T0 = allocateQword(); \
3648 const uint64_t V0 = Value; \
3649 const uint32_t T1 = allocateQword(); \
3650 const uint64_t V1 = ~(Value); \
3651 \
3652 __ movq(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3653 __ movq(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3654 __ movq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3655 \
3656 AssembledTest test = assemble(); \
3657 \
3658 test.setQwordTo(T0, V0); \
3659 test.setQwordTo(T1, V1); \
3660 test.run(); \
3661 \
3662 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \
3663 << Value; \
3664 reset(); \
3665 } while (0)
3666
3667 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) {
3668 TestMovd(xmm0, xmm1, Value);
3669 TestMovd(xmm1, xmm2, Value);
3670 TestMovd(xmm2, xmm3, Value);
3671 TestMovd(xmm3, xmm4, Value);
3672 TestMovd(xmm4, xmm5, Value);
3673 TestMovd(xmm5, xmm6, Value);
3674 TestMovd(xmm6, xmm7, Value);
3675 TestMovd(xmm7, xmm8, Value);
3676 TestMovd(xmm8, xmm9, Value);
3677 TestMovd(xmm9, xmm10, Value);
3678 TestMovd(xmm10, xmm11, Value);
3679 TestMovd(xmm11, xmm12, Value);
3680 TestMovd(xmm12, xmm13, Value);
3681 TestMovd(xmm13, xmm14, Value);
3682 TestMovd(xmm14, xmm15, Value);
3683 TestMovd(xmm15, xmm0, Value);
3684 }
3685
3686 #undef TestMovd
3687 }
3688
3689 TEST_F(AssemblerX8664Test, ArithSS) {
3690 #define TestArithSSXmmXmm(FloatSize, Src, Value0, Dst, Value1, Inst, Op) \
3691 do { \
3692 static_assert(FloatSize == 32 || FloatSize == 64, \
3693 "Invalid fp size " #FloatSize); \
3694 static constexpr char TestString[] = \
3695 "(" #FloatSize ", " #Src ", " #Value0 ", " #Dst ", " #Value1 \
3696 ", " #Inst ", " #Op ")"; \
3697 static constexpr bool IsDouble = FloatSize == 64; \
3698 using Type = std::conditional<IsDouble, double, float>::type; \
3699 const uint32_t T0 = allocateQword(); \
3700 const Type V0 = Value0; \
3701 const uint32_t T1 = allocateQword(); \
3702 const Type V1 = Value1; \
3703 \
3704 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3705 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Src(), dwordAddress(T1)); \
3706 __ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3707 \
3708 AssembledTest test = assemble(); \
3709 if (IsDouble) { \
3710 test.setQwordTo(T0, static_cast<double>(V0)); \
3711 test.setQwordTo(T1, static_cast<double>(V1)); \
3712 } else { \
3713 test.setDwordTo(T0, static_cast<float>(V0)); \
3714 test.setDwordTo(T1, static_cast<float>(V1)); \
3715 } \
3716 \
3717 test.run(); \
3718 \
3719 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
3720 reset(); \
3721 } while (0)
3722
3723 #define TestArithSSXmmAddr(FloatSize, Value0, Dst, Value1, Inst, Op) \
3724 do { \
3725 static_assert(FloatSize == 32 || FloatSize == 64, \
3726 "Invalid fp size " #FloatSize); \
3727 static constexpr char TestString[] = \
3728 "(" #FloatSize ", Addr, " #Value0 ", " #Dst ", " #Value1 ", " #Inst \
3729 ", " #Op ")"; \
3730 static constexpr bool IsDouble = FloatSize == 64; \
3731 using Type = std::conditional<IsDouble, double, float>::type; \
3732 const uint32_t T0 = allocateQword(); \
3733 const Type V0 = Value0; \
3734 const uint32_t T1 = allocateQword(); \
3735 const Type V1 = Value1; \
3736 \
3737 __ movss(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3738 __ Inst(IceType_f##FloatSize, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3739 \
3740 AssembledTest test = assemble(); \
3741 if (IsDouble) { \
3742 test.setQwordTo(T0, static_cast<double>(V0)); \
3743 test.setQwordTo(T1, static_cast<double>(V1)); \
3744 } else { \
3745 test.setDwordTo(T0, static_cast<float>(V0)); \
3746 test.setDwordTo(T1, static_cast<float>(V1)); \
3747 } \
3748 \
3749 test.run(); \
3750 \
3751 ASSERT_DOUBLE_EQ(V0 Op V1, test.Dst<Type>()) << TestString; \
3752 reset(); \
3753 } while (0)
3754
3755 #define TestArithSS(FloatSize, Src, Dst0, Dst1) \
3756 do { \
3757 TestArithSSXmmXmm(FloatSize, Src, 1.0, Dst0, 10.0, addss, +); \
3758 TestArithSSXmmAddr(FloatSize, 2.0, Dst1, 20.0, addss, +); \
3759 TestArithSSXmmXmm(FloatSize, Src, 3.0, Dst0, 30.0, subss, -); \
3760 TestArithSSXmmAddr(FloatSize, 4.0, Dst1, 40.0, subss, -); \
3761 TestArithSSXmmXmm(FloatSize, Src, 5.0, Dst0, 50.0, mulss, *); \
3762 TestArithSSXmmAddr(FloatSize, 6.0, Dst1, 60.0, mulss, *); \
3763 TestArithSSXmmXmm(FloatSize, Src, 7.0, Dst0, 70.0, divss, / ); \
3764 TestArithSSXmmAddr(FloatSize, 8.0, Dst1, 80.0, divss, / ); \
3765 } while (0)
3766
3767 #define TestImpl(Src, Dst0, Dst1) \
3768 do { \
3769 TestArithSS(32, Src, Dst0, Dst1); \
3770 TestArithSS(64, Src, Dst0, Dst1); \
3771 } while (0)
3772
3773 TestImpl(xmm0, xmm1, xmm2);
3774 TestImpl(xmm1, xmm2, xmm3);
3775 TestImpl(xmm2, xmm3, xmm4);
3776 TestImpl(xmm3, xmm4, xmm5);
3777 TestImpl(xmm4, xmm5, xmm6);
3778 TestImpl(xmm5, xmm6, xmm7);
3779 TestImpl(xmm6, xmm7, xmm8);
3780 TestImpl(xmm7, xmm8, xmm9);
3781 TestImpl(xmm8, xmm9, xmm10);
3782 TestImpl(xmm9, xmm10, xmm11);
3783 TestImpl(xmm10, xmm11, xmm12);
3784 TestImpl(xmm11, xmm12, xmm13);
3785 TestImpl(xmm12, xmm13, xmm14);
3786 TestImpl(xmm13, xmm14, xmm15);
3787 TestImpl(xmm14, xmm15, xmm0);
3788 TestImpl(xmm15, xmm0, xmm1);
3789
3790 #undef TestImpl
3791 #undef TestArithSS
3792 #undef TestArithSSXmmAddr
3793 #undef TestArithSSXmmXmm
3794 }
3795
3796 TEST_F(AssemblerX8664Test, MovupsXmmAddr) {
3797 #define TestMovups(Dst) \
3798 do { \
3799 static constexpr char TestString[] = "(" #Dst ")"; \
3800 const uint32_t T0 = allocateDqword(); \
3801 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3802 std::numeric_limits<float>::infinity()); \
3803 \
3804 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3805 \
3806 AssembledTest test = assemble(); \
3807 test.setDqwordTo(T0, V0); \
3808 test.run(); \
3809 \
3810 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3811 reset(); \
3812 } while (0)
3813
3814 TestMovups(xmm0);
3815 TestMovups(xmm1);
3816 TestMovups(xmm2);
3817 TestMovups(xmm3);
3818 TestMovups(xmm4);
3819 TestMovups(xmm5);
3820 TestMovups(xmm6);
3821 TestMovups(xmm7);
3822 TestMovups(xmm8);
3823 TestMovups(xmm9);
3824 TestMovups(xmm10);
3825 TestMovups(xmm11);
3826 TestMovups(xmm12);
3827 TestMovups(xmm13);
3828 TestMovups(xmm14);
3829 TestMovups(xmm15);
3830
3831 #undef TestMovups
3832 }
3833
3834 TEST_F(AssemblerX8664Test, MovupsAddrXmm) {
3835 #define TestMovups(Src) \
3836 do { \
3837 static constexpr char TestString[] = "(" #Src ")"; \
3838 const uint32_t T0 = allocateDqword(); \
3839 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3840 std::numeric_limits<float>::infinity()); \
3841 const uint32_t T1 = allocateDqword(); \
3842 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3843 \
3844 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3845 __ movups(dwordAddress(T1), Encoded_Xmm_##Src()); \
3846 \
3847 AssembledTest test = assemble(); \
3848 test.setDqwordTo(T0, V0); \
3849 test.setDqwordTo(T1, V1); \
3850 test.run(); \
3851 \
3852 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \
3853 reset(); \
3854 } while (0)
3855
3856 TestMovups(xmm0);
3857 TestMovups(xmm1);
3858 TestMovups(xmm2);
3859 TestMovups(xmm3);
3860 TestMovups(xmm4);
3861 TestMovups(xmm5);
3862 TestMovups(xmm6);
3863 TestMovups(xmm7);
3864 TestMovups(xmm8);
3865 TestMovups(xmm9);
3866 TestMovups(xmm10);
3867 TestMovups(xmm11);
3868 TestMovups(xmm12);
3869 TestMovups(xmm13);
3870 TestMovups(xmm14);
3871 TestMovups(xmm15);
3872
3873 #undef TestMovups
3874 }
3875
3876 TEST_F(AssemblerX8664Test, MovupsXmmXmm) {
3877 #define TestMovups(Dst, Src) \
3878 do { \
3879 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
3880 const uint32_t T0 = allocateDqword(); \
3881 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3882 std::numeric_limits<float>::infinity()); \
3883 const uint32_t T1 = allocateDqword(); \
3884 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3885 \
3886 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3887 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3888 __ movups(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3889 \
3890 AssembledTest test = assemble(); \
3891 test.setDqwordTo(T0, V0); \
3892 test.setDqwordTo(T1, V1); \
3893 test.run(); \
3894 \
3895 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3896 reset(); \
3897 } while (0)
3898
3899 TestMovups(xmm0, xmm1);
3900 TestMovups(xmm1, xmm2);
3901 TestMovups(xmm2, xmm3);
3902 TestMovups(xmm3, xmm4);
3903 TestMovups(xmm4, xmm5);
3904 TestMovups(xmm5, xmm6);
3905 TestMovups(xmm6, xmm7);
3906 TestMovups(xmm7, xmm8);
3907 TestMovups(xmm8, xmm9);
3908 TestMovups(xmm9, xmm10);
3909 TestMovups(xmm10, xmm11);
3910 TestMovups(xmm11, xmm12);
3911 TestMovups(xmm12, xmm13);
3912 TestMovups(xmm13, xmm14);
3913 TestMovups(xmm14, xmm15);
3914 TestMovups(xmm15, xmm0);
3915
3916 #undef TestMovups
3917 }
3918
3919 TEST_F(AssemblerX8664Test, MovapsXmmXmm) {
3920 #define TestMovaps(Dst, Src) \
3921 do { \
3922 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \
3923 const uint32_t T0 = allocateDqword(); \
3924 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \
3925 std::numeric_limits<float>::infinity()); \
3926 const uint32_t T1 = allocateDqword(); \
3927 const Dqword V1(0.0, 0.0, 0.0, 0.0); \
3928 \
3929 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
3930 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
3931 __ movaps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3932 \
3933 AssembledTest test = assemble(); \
3934 test.setDqwordTo(T0, V0); \
3935 test.setDqwordTo(T1, V1); \
3936 test.run(); \
3937 \
3938 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \
3939 reset(); \
3940 } while (0)
3941
3942 TestMovaps(xmm0, xmm1);
3943 TestMovaps(xmm1, xmm2);
3944 TestMovaps(xmm2, xmm3);
3945 TestMovaps(xmm3, xmm4);
3946 TestMovaps(xmm4, xmm5);
3947 TestMovaps(xmm5, xmm6);
3948 TestMovaps(xmm6, xmm7);
3949 TestMovaps(xmm7, xmm8);
3950 TestMovaps(xmm8, xmm9);
3951 TestMovaps(xmm9, xmm10);
3952 TestMovaps(xmm10, xmm11);
3953 TestMovaps(xmm11, xmm12);
3954 TestMovaps(xmm12, xmm13);
3955 TestMovaps(xmm13, xmm14);
3956 TestMovaps(xmm14, xmm15);
3957 TestMovaps(xmm15, xmm0);
3958
3959 #undef TestMovaps
3960 }
3961
3962 TEST_F(AssemblerX8664Test, PArith) {
3963 #define TestPArithXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type, Size) \
3964 do { \
3965 static constexpr char TestString[] = \
3966 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
3967 ", " #Type ", " #Size ")"; \
3968 const uint32_t T0 = allocateDqword(); \
3969 const Dqword V0 Value0; \
3970 \
3971 const uint32_t T1 = allocateDqword(); \
3972 const Dqword V1 Value1; \
3973 \
3974 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
3975 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
3976 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
3977 \
3978 AssembledTest test = assemble(); \
3979 test.setDqwordTo(T0, V0); \
3980 test.setDqwordTo(T1, V1); \
3981 test.run(); \
3982 \
3983 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
3984 << TestString; \
3985 reset(); \
3986 } while (0)
3987
3988 #define TestPArithXmmAddr(Dst, Value0, Value1, Inst, Op, Type, Size) \
3989 do { \
3990 static constexpr char TestString[] = \
3991 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
3992 ", " #Type ", " #Size ")"; \
3993 const uint32_t T0 = allocateDqword(); \
3994 const Dqword V0 Value0; \
3995 \
3996 const uint32_t T1 = allocateDqword(); \
3997 const Dqword V1 Value1; \
3998 \
3999 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4000 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4001 \
4002 AssembledTest test = assemble(); \
4003 test.setDqwordTo(T0, V0); \
4004 test.setDqwordTo(T1, V1); \
4005 test.run(); \
4006 \
4007 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op V1, test.Dst<Dqword>()) \
4008 << TestString; \
4009 reset(); \
4010 } while (0)
4011
4012 #define TestPArithXmmImm(Dst, Value0, Imm, Inst, Op, Type, Size) \
4013 do { \
4014 static constexpr char TestString[] = \
4015 "(" #Dst ", " #Value0 ", " #Imm ", " #Inst ", " #Op ", " #Type \
4016 ", " #Size ")"; \
4017 const uint32_t T0 = allocateDqword(); \
4018 const Dqword V0 Value0; \
4019 \
4020 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4021 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Immediate(Imm)); \
4022 \
4023 AssembledTest test = assemble(); \
4024 test.setDqwordTo(T0, V0); \
4025 test.run(); \
4026 \
4027 ASSERT_EQ(packedAs<Type##Size##_t>(V0) Op Imm, test.Dst<Dqword>()) \
4028 << TestString; \
4029 reset(); \
4030 } while (0)
4031
4032 #define TestPAndnXmmXmm(Dst, Value0, Src, Value1, Type, Size) \
4033 do { \
4034 static constexpr char TestString[] = \
4035 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", pandn, " #Type \
4036 ", " #Size ")"; \
4037 const uint32_t T0 = allocateDqword(); \
4038 const Dqword V0 Value0; \
4039 \
4040 const uint32_t T1 = allocateDqword(); \
4041 const Dqword V1 Value1; \
4042 \
4043 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4044 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4045 __ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4046 \
4047 AssembledTest test = assemble(); \
4048 test.setDqwordTo(T0, V0); \
4049 test.setDqwordTo(T1, V1); \
4050 test.run(); \
4051 \
4052 ASSERT_EQ(~(packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
4053 << TestString; \
4054 reset(); \
4055 } while (0)
4056
4057 #define TestPAndnXmmAddr(Dst, Value0, Value1, Type, Size) \
4058 do { \
4059 static constexpr char TestString[] = \
4060 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", pandn, " #Type ", " #Size \
4061 ")"; \
4062 const uint32_t T0 = allocateDqword(); \
4063 const Dqword V0 Value0; \
4064 \
4065 const uint32_t T1 = allocateDqword(); \
4066 const Dqword V1 Value1; \
4067 \
4068 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4069 __ pandn(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4070 \
4071 AssembledTest test = assemble(); \
4072 test.setDqwordTo(T0, V0); \
4073 test.setDqwordTo(T1, V1); \
4074 test.run(); \
4075 \
4076 ASSERT_EQ((~packedAs<Type##Size##_t>(V0)) & V1, test.Dst<Dqword>()) \
4077 << TestString; \
4078 reset(); \
4079 } while (0)
4080
4081 #define TestPArithSize(Dst, Src, Size) \
4082 do { \
4083 static_assert(Size == 8 || Size == 16 || Size == 32, "Invalid size."); \
4084 if (Size != 8) { \
4085 TestPArithXmmXmm( \
4086 Dst, \
4087 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4088 Src, (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
4089 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4090 uint64_t(0x8080404002020101ull)), \
4091 (uint64_t(3u), uint64_t(0u)), psra, >>, int, Size); \
4092 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4093 uint64_t(0x8080404002020101ull)), \
4094 3u, psra, >>, int, Size); \
4095 TestPArithXmmXmm( \
4096 Dst, \
4097 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4098 Src, (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
4099 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4100 uint64_t(0x8080404002020101ull)), \
4101 (uint64_t(3u), uint64_t(0u)), psrl, >>, uint, Size); \
4102 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4103 uint64_t(0x8080404002020101ull)), \
4104 3u, psrl, >>, uint, Size); \
4105 TestPArithXmmXmm( \
4106 Dst, \
4107 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4108 Src, (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
4109 TestPArithXmmAddr(Dst, (uint64_t(0x8040201008040201ull), \
4110 uint64_t(0x8080404002020101ull)), \
4111 (uint64_t(3u), uint64_t(0u)), psll, <<, uint, Size); \
4112 TestPArithXmmImm(Dst, (uint64_t(0x8040201008040201ull), \
4113 uint64_t(0x8080404002020101ull)), \
4114 3u, psll, <<, uint, Size); \
4115 \
4116 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4117 uint64_t(0x8080404002020101ull)), \
4118 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4119 uint64_t(0x0123456789ABCDEull)), \
4120 pmull, *, int, Size); \
4121 TestPArithXmmAddr( \
4122 Dst, \
4123 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4124 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4125 pmull, *, int, Size); \
4126 if (Size != 16) { \
4127 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4128 uint64_t(0x8080404002020101ull)), \
4129 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4130 uint64_t(0x0123456789ABCDEull)), \
4131 pmuludq, *, uint, Size); \
4132 TestPArithXmmAddr( \
4133 Dst, (uint64_t(0x8040201008040201ull), \
4134 uint64_t(0x8080404002020101ull)), \
4135 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4136 pmuludq, *, uint, Size); \
4137 } \
4138 } \
4139 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4140 uint64_t(0x8080404002020101ull)), \
4141 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4142 uint64_t(0x0123456789ABCDEull)), \
4143 padd, +, int, Size); \
4144 TestPArithXmmAddr( \
4145 Dst, \
4146 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4147 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4148 padd, +, int, Size); \
4149 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4150 uint64_t(0x8080404002020101ull)), \
4151 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4152 uint64_t(0x0123456789ABCDEull)), \
4153 psub, -, int, Size); \
4154 TestPArithXmmAddr( \
4155 Dst, \
4156 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4157 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4158 psub, -, int, Size); \
4159 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4160 uint64_t(0x8080404002020101ull)), \
4161 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4162 uint64_t(0x0123456789ABCDEull)), \
4163 pand, &, int, Size); \
4164 TestPArithXmmAddr( \
4165 Dst, \
4166 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4167 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4168 pand, &, int, Size); \
4169 \
4170 TestPAndnXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4171 uint64_t(0x8080404002020101ull)), \
4172 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4173 uint64_t(0x0123456789ABCDEull)), \
4174 int, Size); \
4175 TestPAndnXmmAddr( \
4176 Dst, \
4177 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4178 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4179 int, Size); \
4180 \
4181 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4182 uint64_t(0x8080404002020101ull)), \
4183 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4184 uint64_t(0x0123456789ABCDEull)), \
4185 por, |, int, Size); \
4186 TestPArithXmmAddr( \
4187 Dst, \
4188 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4189 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4190 por, |, int, Size); \
4191 TestPArithXmmXmm(Dst, (uint64_t(0x8040201008040201ull), \
4192 uint64_t(0x8080404002020101ull)), \
4193 Src, (uint64_t(0xFFFFFFFF00000000ull), \
4194 uint64_t(0x0123456789ABCDEull)), \
4195 pxor, ^, int, Size); \
4196 TestPArithXmmAddr( \
4197 Dst, \
4198 (uint64_t(0x8040201008040201ull), uint64_t(0x8080404002020101ull)), \
4199 (uint64_t(0xFFFFFFFF00000000ull), uint64_t(0x0123456789ABCDEull)), \
4200 pxor, ^, int, Size); \
4201 } while (0)
4202
4203 #define TestPArith(Src, Dst) \
4204 do { \
4205 TestPArithSize(Src, Dst, 8); \
4206 TestPArithSize(Src, Dst, 16); \
4207 TestPArithSize(Src, Dst, 32); \
4208 } while (0)
4209
4210 TestPArith(xmm0, xmm1);
4211 TestPArith(xmm1, xmm2);
4212 TestPArith(xmm2, xmm3);
4213 TestPArith(xmm3, xmm4);
4214 TestPArith(xmm4, xmm5);
4215 TestPArith(xmm5, xmm6);
4216 TestPArith(xmm6, xmm7);
4217 TestPArith(xmm7, xmm8);
4218 TestPArith(xmm8, xmm9);
4219 TestPArith(xmm9, xmm10);
4220 TestPArith(xmm10, xmm11);
4221 TestPArith(xmm11, xmm12);
4222 TestPArith(xmm12, xmm13);
4223 TestPArith(xmm13, xmm14);
4224 TestPArith(xmm14, xmm15);
4225 TestPArith(xmm15, xmm0);
4226
4227 #undef TestPArith
4228 #undef TestPArithSize
4229 #undef TestPAndnXmmAddr
4230 #undef TestPAndnXmmXmm
4231 #undef TestPArithXmmImm
4232 #undef TestPArithXmmAddr
4233 #undef TestPArithXmmXmm
4234 }
4235
4236 TEST_F(AssemblerX8664Test, ArithPS) {
4237 #define TestArithPSXmmXmm(Dst, Value0, Src, Value1, Inst, Op, Type) \
4238 do { \
4239 static constexpr char TestString[] = \
4240 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
4241 ", " #Type ")"; \
4242 const uint32_t T0 = allocateDqword(); \
4243 const Dqword V0 Value0; \
4244 const uint32_t T1 = allocateDqword(); \
4245 const Dqword V1 Value1; \
4246 \
4247 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4248 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4249 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4250 \
4251 AssembledTest test = assemble(); \
4252 test.setDqwordTo(T0, V0); \
4253 test.setDqwordTo(T1, V1); \
4254 test.run(); \
4255 \
4256 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4257 \
4258 reset(); \
4259 } while (0)
4260
4261 #define TestArithPSXmmXmmUntyped(Dst, Value0, Src, Value1, Inst, Op, Type) \
4262 do { \
4263 static constexpr char TestString[] = \
4264 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Op \
4265 ", " #Type ")"; \
4266 const uint32_t T0 = allocateDqword(); \
4267 const Dqword V0 Value0; \
4268 const uint32_t T1 = allocateDqword(); \
4269 const Dqword V1 Value1; \
4270 \
4271 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4272 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4273 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4274 \
4275 AssembledTest test = assemble(); \
4276 test.setDqwordTo(T0, V0); \
4277 test.setDqwordTo(T1, V1); \
4278 test.run(); \
4279 \
4280 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4281 \
4282 reset(); \
4283 } while (0)
4284
4285 #define TestArithPSXmmAddrUntyped(Dst, Value0, Value1, Inst, Op, Type) \
4286 do { \
4287 static constexpr char TestString[] = \
4288 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
4289 ", " #Type ")"; \
4290 const uint32_t T0 = allocateDqword(); \
4291 const Dqword V0 Value0; \
4292 const uint32_t T1 = allocateDqword(); \
4293 const Dqword V1 Value1; \
4294 \
4295 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4296 __ Inst(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4297 \
4298 AssembledTest test = assemble(); \
4299 test.setDqwordTo(T0, V0); \
4300 test.setDqwordTo(T1, V1); \
4301 test.run(); \
4302 \
4303 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4304 \
4305 reset(); \
4306 } while (0)
4307
4308 #define TestMinMaxPS(Dst, Value0, Src, Value1, Inst, Type) \
4309 do { \
4310 static constexpr char TestString[] = \
4311 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Inst ", " #Type \
4312 ")"; \
4313 const uint32_t T0 = allocateDqword(); \
4314 const Dqword V0 Value0; \
4315 const uint32_t T1 = allocateDqword(); \
4316 const Dqword V1 Value1; \
4317 \
4318 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4319 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4320 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4321 \
4322 AssembledTest test = assemble(); \
4323 test.setDqwordTo(T0, V0); \
4324 test.setDqwordTo(T1, V1); \
4325 test.run(); \
4326 \
4327 ASSERT_EQ(packedAs<Type>(V0).Inst(V1), test.Dst<Dqword>()) << TestString; \
4328 \
4329 reset(); \
4330 } while (0)
4331
4332 #define TestArithPSXmmAddr(Dst, Value0, Value1, Inst, Op, Type) \
4333 do { \
4334 static constexpr char TestString[] = \
4335 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Inst ", " #Op \
4336 ", " #Type ")"; \
4337 const uint32_t T0 = allocateDqword(); \
4338 const Dqword V0 Value0; \
4339 const uint32_t T1 = allocateDqword(); \
4340 const Dqword V1 Value1; \
4341 \
4342 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4343 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4344 \
4345 AssembledTest test = assemble(); \
4346 test.setDqwordTo(T0, V0); \
4347 test.setDqwordTo(T1, V1); \
4348 test.run(); \
4349 \
4350 ASSERT_EQ(packedAs<Type>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4351 \
4352 reset(); \
4353 } while (0)
4354
4355 #define TestArithPS(Dst, Src) \
4356 do { \
4357 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4358 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
4359 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4360 (0.55, 0.43, 0.23, 1.21), addps, +, float); \
4361 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4362 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
4363 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4364 (0.55, 0.43, 0.23, 1.21), subps, -, float); \
4365 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4366 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
4367 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4368 (0.55, 0.43, 0.23, 1.21), mulps, *, float); \
4369 TestArithPSXmmXmm(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4370 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
4371 TestArithPSXmmAddr(Dst, (1.0, 100.0, -1000.0, 20.0), \
4372 (0.55, 0.43, 0.23, 1.21), divps, /, float); \
4373 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4374 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
4375 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
4376 (0.55, 0.43, 0.23, 1.21), andps, &, float); \
4377 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), andpd, &, \
4378 double); \
4379 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), andpd, &, \
4380 double); \
4381 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4382 (0.55, 0.43, 0.23, 1.21), orps, |, float); \
4383 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), orpd, |, \
4384 double); \
4385 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4386 (0.55, 0.43, 0.23, 1.21), minps, float); \
4387 TestMinMaxPS(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4388 (0.55, 0.43, 0.23, 1.21), maxps, float); \
4389 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), minpd, double); \
4390 TestMinMaxPS(Dst, (1.0, -1000.0), Src, (0.55, 1.21), maxpd, double); \
4391 TestArithPSXmmXmmUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), Src, \
4392 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
4393 TestArithPSXmmAddrUntyped(Dst, (1.0, 100.0, -1000.0, 20.0), \
4394 (0.55, 0.43, 0.23, 1.21), xorps, ^, float); \
4395 TestArithPSXmmXmmUntyped(Dst, (1.0, -1000.0), Src, (0.55, 1.21), xorpd, ^, \
4396 double); \
4397 TestArithPSXmmAddrUntyped(Dst, (1.0, -1000.0), (0.55, 1.21), xorpd, ^, \
4398 double); \
4399 } while (0)
4400
4401 TestArithPS(xmm0, xmm1);
4402 TestArithPS(xmm1, xmm2);
4403 TestArithPS(xmm2, xmm3);
4404 TestArithPS(xmm3, xmm4);
4405 TestArithPS(xmm4, xmm5);
4406 TestArithPS(xmm5, xmm6);
4407 TestArithPS(xmm6, xmm7);
4408 TestArithPS(xmm7, xmm8);
4409 TestArithPS(xmm8, xmm9);
4410 TestArithPS(xmm9, xmm10);
4411 TestArithPS(xmm10, xmm11);
4412 TestArithPS(xmm11, xmm12);
4413 TestArithPS(xmm12, xmm13);
4414 TestArithPS(xmm13, xmm14);
4415 TestArithPS(xmm14, xmm15);
4416 TestArithPS(xmm15, xmm0);
4417
4418 #undef TestArithPs
4419 #undef TestMinMaxPS
4420 #undef TestArithPSXmmXmmUntyped
4421 #undef TestArithPSXmmAddr
4422 #undef TestArithPSXmmXmm
4423 }
4424
4425 TEST_F(AssemblerX8664Test, Blending) {
4426 using f32 = float;
4427 using i8 = uint8_t;
4428
4429 #define TestBlendingXmmXmm(Dst, Value0, Src, Value1, M /*ask*/, Inst, Type) \
4430 do { \
4431 static constexpr char TestString[] = \
4432 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #M ", " #Inst \
4433 ", " #Type ")"; \
4434 const uint32_t T0 = allocateDqword(); \
4435 const Dqword V0 Value0; \
4436 const uint32_t T1 = allocateDqword(); \
4437 const Dqword V1 Value1; \
4438 const uint32_t Mask = allocateDqword(); \
4439 const Dqword MaskValue M; \
4440 \
4441 __ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
4442 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4443 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4444 __ Inst(IceType_##Type, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4445 \
4446 AssembledTest test = assemble(); \
4447 test.setDqwordTo(T0, V0); \
4448 test.setDqwordTo(T1, V1); \
4449 test.setDqwordTo(Mask, MaskValue); \
4450 test.run(); \
4451 \
4452 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
4453 << TestString; \
4454 reset(); \
4455 } while (0)
4456
4457 #define TestBlendingXmmAddr(Dst, Value0, Value1, M /*ask*/, Inst, Type) \
4458 do { \
4459 static constexpr char TestString[] = \
4460 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #M ", " #Inst ", " #Type \
4461 ")"; \
4462 const uint32_t T0 = allocateDqword(); \
4463 const Dqword V0 Value0; \
4464 const uint32_t T1 = allocateDqword(); \
4465 const Dqword V1 Value1; \
4466 const uint32_t Mask = allocateDqword(); \
4467 const Dqword MaskValue M; \
4468 \
4469 __ movups(Encoded_Xmm_xmm0(), dwordAddress(Mask)); \
4470 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4471 __ Inst(IceType_##Type, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
4472 \
4473 AssembledTest test = assemble(); \
4474 test.setDqwordTo(T0, V0); \
4475 test.setDqwordTo(T1, V1); \
4476 test.setDqwordTo(Mask, MaskValue); \
4477 test.run(); \
4478 \
4479 ASSERT_EQ(packedAs<Type>(V0).blendWith(V1, MaskValue), test.Dst<Dqword>()) \
4480 << TestString; \
4481 reset(); \
4482 } while (0)
4483
4484 #define TestBlending(Src, Dst) \
4485 do { \
4486 TestBlendingXmmXmm( \
4487 Dst, (1.0, 2.0, 1.0, 2.0), Src, (-1.0, -2.0, -1.0, -2.0), \
4488 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
4489 blendvps, f32); \
4490 TestBlendingXmmAddr( \
4491 Dst, (1.0, 2.0, 1.0, 2.0), (-1.0, -2.0, -1.0, -2.0), \
4492 (uint64_t(0x8000000000000000ull), uint64_t(0x0000000080000000ull)), \
4493 blendvps, f32); \
4494 TestBlendingXmmXmm( \
4495 Dst, \
4496 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
4497 Src, \
4498 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
4499 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
4500 pblendvb, i8); \
4501 TestBlendingXmmAddr( \
4502 Dst, \
4503 (uint64_t(0xFFFFFFFFFFFFFFFFull), uint64_t(0xBBBBBBBBBBBBBBBBull)), \
4504 (uint64_t(0xAAAAAAAAAAAAAAAAull), uint64_t(0xEEEEEEEEEEEEEEEEull)), \
4505 (uint64_t(0x8000000000000080ull), uint64_t(0x8080808000000000ull)), \
4506 pblendvb, i8); \
4507 } while (0)
4508
4509 /* xmm0 is taken. It is the implicit mask . */
4510 TestBlending(xmm1, xmm2);
4511 TestBlending(xmm2, xmm3);
4512 TestBlending(xmm3, xmm4);
4513 TestBlending(xmm4, xmm5);
4514 TestBlending(xmm5, xmm6);
4515 TestBlending(xmm6, xmm7);
4516 TestBlending(xmm7, xmm8);
4517 TestBlending(xmm8, xmm9);
4518 TestBlending(xmm9, xmm10);
4519 TestBlending(xmm10, xmm11);
4520 TestBlending(xmm11, xmm12);
4521 TestBlending(xmm12, xmm13);
4522 TestBlending(xmm13, xmm14);
4523 TestBlending(xmm14, xmm15);
4524 TestBlending(xmm15, xmm1);
4525
4526 #undef TestBlending
4527 #undef TestBlendingXmmAddr
4528 #undef TestBlendingXmmXmm
4529 }
4530
4531 TEST_F(AssemblerX8664Test, Cmpps) {
4532 #define TestCmppsXmmXmm(Dst, Src, C, Op) \
4533 do { \
4534 static constexpr char TestString[] = \
4535 "(" #Src ", " #Dst ", " #C ", " #Op ")"; \
4536 const uint32_t T0 = allocateDqword(); \
4537 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
4538 const uint32_t T1 = allocateDqword(); \
4539 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
4540 \
4541 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4542 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4543 __ cmpps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Cond::Cmpps_##C); \
4544 \
4545 AssembledTest test = assemble(); \
4546 test.setDqwordTo(T0, V0); \
4547 test.setDqwordTo(T1, V1); \
4548 test.run(); \
4549 \
4550 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4551 ; \
4552 reset(); \
4553 } while (0)
4554
4555 #define TestCmppsXmmAddr(Dst, C, Op) \
4556 do { \
4557 static constexpr char TestString[] = "(" #Dst ", Addr, " #C ", " #Op ")"; \
4558 const uint32_t T0 = allocateDqword(); \
4559 const Dqword V0(-1.0, 1.0, 3.14, 1024.5); \
4560 const uint32_t T1 = allocateDqword(); \
4561 const Dqword V1(-1.0, 1.0, 3.14, 1024.5); \
4562 \
4563 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4564 __ cmpps(Encoded_Xmm_##Dst(), dwordAddress(T1), Cond::Cmpps_##C); \
4565 \
4566 AssembledTest test = assemble(); \
4567 test.setDqwordTo(T0, V0); \
4568 test.setDqwordTo(T1, V1); \
4569 test.run(); \
4570 \
4571 ASSERT_EQ(packedAs<float>(V0) Op V1, test.Dst<Dqword>()) << TestString; \
4572 ; \
4573 reset(); \
4574 } while (0)
4575
4576 #define TestCmppsOrdUnordXmmXmm(Dst, Src, C) \
4577 do { \
4578 static constexpr char TestString[] = "(" #Src ", " #Dst ", " #C ")"; \
4579 const uint32_t T0 = allocateDqword(); \
4580 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
4581 std::numeric_limits<float>::quiet_NaN()); \
4582 const uint32_t T1 = allocateDqword(); \
4583 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
4584 std::numeric_limits<float>::quiet_NaN()); \
4585 \
4586 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4587 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4588 __ cmpps(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Cond::Cmpps_##C); \
4589 \
4590 AssembledTest test = assemble(); \
4591 test.setDqwordTo(T0, V0); \
4592 test.setDqwordTo(T1, V1); \
4593 test.run(); \
4594 \
4595 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
4596 ; \
4597 reset(); \
4598 } while (0)
4599
4600 #define TestCmppsOrdUnordXmmAddr(Dst, C) \
4601 do { \
4602 static constexpr char TestString[] = "(" #Dst ", " #C ")"; \
4603 const uint32_t T0 = allocateDqword(); \
4604 const Dqword V0(1.0, 1.0, std::numeric_limits<float>::quiet_NaN(), \
4605 std::numeric_limits<float>::quiet_NaN()); \
4606 const uint32_t T1 = allocateDqword(); \
4607 const Dqword V1(1.0, std::numeric_limits<float>::quiet_NaN(), 1.0, \
4608 std::numeric_limits<float>::quiet_NaN()); \
4609 \
4610 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4611 __ cmpps(Encoded_Xmm_##Dst(), dwordAddress(T1), Cond::Cmpps_##C); \
4612 \
4613 AssembledTest test = assemble(); \
4614 test.setDqwordTo(T0, V0); \
4615 test.setDqwordTo(T1, V1); \
4616 test.run(); \
4617 \
4618 ASSERT_EQ(packedAs<float>(V0).C(V1), test.Dst<Dqword>()) << TestString; \
4619 ; \
4620 reset(); \
4621 } while (0)
4622
4623 #define TestCmpps(Dst, Src) \
4624 do { \
4625 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4626 TestCmppsXmmAddr(Dst, eq, == ); \
4627 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4628 TestCmppsXmmAddr(Dst, eq, == ); \
4629 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4630 TestCmppsXmmAddr(Dst, eq, == ); \
4631 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
4632 TestCmppsOrdUnordXmmAddr(Dst, unord); \
4633 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4634 TestCmppsXmmAddr(Dst, eq, == ); \
4635 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4636 TestCmppsXmmAddr(Dst, eq, == ); \
4637 TestCmppsXmmXmm(Dst, Src, eq, == ); \
4638 TestCmppsXmmAddr(Dst, eq, == ); \
4639 TestCmppsOrdUnordXmmXmm(Dst, Src, unord); \
4640 TestCmppsOrdUnordXmmAddr(Dst, unord); \
4641 } while (0)
4642
4643 TestCmpps(xmm0, xmm1);
4644 TestCmpps(xmm1, xmm2);
4645 TestCmpps(xmm2, xmm3);
4646 TestCmpps(xmm3, xmm4);
4647 TestCmpps(xmm4, xmm5);
4648 TestCmpps(xmm5, xmm6);
4649 TestCmpps(xmm6, xmm7);
4650 TestCmpps(xmm7, xmm8);
4651 TestCmpps(xmm8, xmm9);
4652 TestCmpps(xmm9, xmm10);
4653 TestCmpps(xmm10, xmm11);
4654 TestCmpps(xmm11, xmm12);
4655 TestCmpps(xmm12, xmm13);
4656 TestCmpps(xmm13, xmm14);
4657 TestCmpps(xmm14, xmm15);
4658 TestCmpps(xmm15, xmm0);
4659
4660 #undef TestCmpps
4661 #undef TestCmppsOrdUnordXmmAddr
4662 #undef TestCmppsOrdUnordXmmXmm
4663 #undef TestCmppsXmmAddr
4664 #undef TestCmppsXmmXmm
4665 }
4666
4667 TEST_F(AssemblerX8664Test, Sqrtps_Rsqrtps_Reciprocalps_Sqrtpd) {
4668 #define TestImplSingle(Dst, Inst, Expect) \
4669 do { \
4670 static constexpr char TestString[] = "(" #Dst ", " #Inst ")"; \
4671 const uint32_t T0 = allocateDqword(); \
4672 const Dqword V0(1.0, 4.0, 20.0, 3.14); \
4673 \
4674 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4675 __ Inst(Encoded_Xmm_##Dst()); \
4676 \
4677 AssembledTest test = assemble(); \
4678 test.setDqwordTo(T0, V0); \
4679 test.run(); \
4680 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
4681 reset(); \
4682 } while (0)
4683
4684 #define TestImpl(Dst) \
4685 do { \
4686 TestImplSingle(Dst, sqrtps, (uint64_t(0x400000003F800000ull), \
4687 uint64_t(0x3FE2D10B408F1BBDull))); \
4688 TestImplSingle(Dst, rsqrtps, (uint64_t(0x3EFFF0003F7FF000ull), \
4689 uint64_t(0x3F1078003E64F000ull))); \
4690 TestImplSingle(Dst, reciprocalps, (uint64_t(0x3E7FF0003F7FF000ull), \
4691 uint64_t(0x3EA310003D4CC000ull))); \
4692 \
4693 TestImplSingle(Dst, sqrtpd, (uint64_t(0x4036A09E9365F5F3ull), \
4694 uint64_t(0x401C42FAE40282A8ull))); \
4695 } while (0)
4696
4697 TestImpl(xmm0);
4698 TestImpl(xmm1);
4699 TestImpl(xmm2);
4700 TestImpl(xmm3);
4701 TestImpl(xmm4);
4702 TestImpl(xmm5);
4703 TestImpl(xmm6);
4704 TestImpl(xmm7);
4705 TestImpl(xmm8);
4706 TestImpl(xmm9);
4707 TestImpl(xmm10);
4708 TestImpl(xmm11);
4709 TestImpl(xmm12);
4710 TestImpl(xmm13);
4711 TestImpl(xmm14);
4712 TestImpl(xmm15);
4713
4714 #undef TestImpl
4715 #undef TestImplSingle
4716 }
4717
4718 TEST_F(AssemblerX8664Test, Movhlps_Movlhps) {
4719 #define TestImplSingle(Dst, Src, Inst, Expect) \
4720 do { \
4721 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4722 const uint32_t T0 = allocateDqword(); \
4723 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \
4724 uint64_t(0xCCCCCCCCDDDDDDDDull)); \
4725 const uint32_t T1 = allocateDqword(); \
4726 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \
4727 uint64_t(0x9999999988888888ull)); \
4728 \
4729 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4730 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4731 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4732 \
4733 AssembledTest test = assemble(); \
4734 test.setDqwordTo(T0, V0); \
4735 test.setDqwordTo(T1, V1); \
4736 test.run(); \
4737 \
4738 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \
4739 reset(); \
4740 } while (0)
4741
4742 #define TestImpl(Dst, Src) \
4743 do { \
4744 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \
4745 uint64_t(0xCCCCCCCCDDDDDDDDull))); \
4746 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \
4747 uint64_t(0xEEEEEEEEFFFFFFFFull))); \
4748 } while (0)
4749
4750 TestImpl(xmm0, xmm1);
4751 TestImpl(xmm1, xmm2);
4752 TestImpl(xmm2, xmm3);
4753 TestImpl(xmm3, xmm4);
4754 TestImpl(xmm4, xmm5);
4755 TestImpl(xmm5, xmm6);
4756 TestImpl(xmm6, xmm7);
4757 TestImpl(xmm7, xmm8);
4758 TestImpl(xmm8, xmm9);
4759 TestImpl(xmm9, xmm10);
4760 TestImpl(xmm10, xmm11);
4761 TestImpl(xmm11, xmm12);
4762 TestImpl(xmm12, xmm13);
4763 TestImpl(xmm13, xmm14);
4764 TestImpl(xmm14, xmm15);
4765 TestImpl(xmm15, xmm0);
4766
4767 #undef TestImpl
4768 #undef TestImplSingle
4769 }
4770
4771 TEST_F(AssemblerX8664Test, Unpck) {
4772 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull),
4773 uint64_t(0xCCCCCCCCDDDDDDDDull));
4774 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull),
4775 uint64_t(0x9999999988888888ull));
4776
4777 const Dqword unpcklpsExpected(uint64_t(0xFFFFFFFFBBBBBBBBull),
4778 uint64_t(0xEEEEEEEEAAAAAAAAull));
4779 const Dqword unpcklpdExpected(uint64_t(0xAAAAAAAABBBBBBBBull),
4780 uint64_t(0xEEEEEEEEFFFFFFFFull));
4781 const Dqword unpckhpsExpected(uint64_t(0x88888888DDDDDDDDull),
4782 uint64_t(0x99999999CCCCCCCCull));
4783 const Dqword unpckhpdExpected(uint64_t(0xCCCCCCCCDDDDDDDDull),
4784 uint64_t(0x9999999988888888ull));
4785
4786 #define TestImplSingle(Dst, Src, Inst) \
4787 do { \
4788 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4789 const uint32_t T0 = allocateDqword(); \
4790 const uint32_t T1 = allocateDqword(); \
4791 \
4792 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4793 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4794 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4795 \
4796 AssembledTest test = assemble(); \
4797 test.setDqwordTo(T0, V0); \
4798 test.setDqwordTo(T1, V1); \
4799 test.run(); \
4800 \
4801 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4802 reset(); \
4803 } while (0)
4804
4805 #define TestImpl(Dst, Src) \
4806 do { \
4807 TestImplSingle(Dst, Src, unpcklps); \
4808 TestImplSingle(Dst, Src, unpcklpd); \
4809 TestImplSingle(Dst, Src, unpckhps); \
4810 TestImplSingle(Dst, Src, unpckhpd); \
4811 } while (0)
4812
4813 TestImpl(xmm0, xmm1);
4814 TestImpl(xmm1, xmm2);
4815 TestImpl(xmm2, xmm3);
4816 TestImpl(xmm3, xmm4);
4817 TestImpl(xmm4, xmm5);
4818 TestImpl(xmm5, xmm6);
4819 TestImpl(xmm6, xmm7);
4820 TestImpl(xmm7, xmm8);
4821 TestImpl(xmm8, xmm9);
4822 TestImpl(xmm9, xmm10);
4823 TestImpl(xmm10, xmm11);
4824 TestImpl(xmm11, xmm12);
4825 TestImpl(xmm12, xmm13);
4826 TestImpl(xmm13, xmm14);
4827 TestImpl(xmm14, xmm15);
4828 TestImpl(xmm15, xmm0);
4829
4830 #undef TestImpl
4831 #undef TestImplSingle
4832 }
4833
4834 TEST_F(AssemblerX8664Test, Shufp) {
4835 const Dqword V0(uint64_t(0x1111111122222222ull),
4836 uint64_t(0x5555555577777777ull));
4837 const Dqword V1(uint64_t(0xAAAAAAAABBBBBBBBull),
4838 uint64_t(0xCCCCCCCCDDDDDDDDull));
4839
4840 const uint8_t pshufdImm = 0x63;
4841 const Dqword pshufdExpected(uint64_t(0xBBBBBBBBCCCCCCCCull),
4842 uint64_t(0xAAAAAAAADDDDDDDDull));
4843
4844 const uint8_t shufpsImm = 0xf9;
4845 const Dqword shufpsExpected(uint64_t(0x7777777711111111ull),
4846 uint64_t(0xCCCCCCCCCCCCCCCCull));
4847
4848 #define TestImplSingleXmmXmm(Dst, Src, Inst) \
4849 do { \
4850 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \
4851 const uint32_t T0 = allocateDqword(); \
4852 const uint32_t T1 = allocateDqword(); \
4853 \
4854 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4855 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4856 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
4857 Immediate(Inst##Imm)); \
4858 \
4859 AssembledTest test = assemble(); \
4860 test.setDqwordTo(T0, V0); \
4861 test.setDqwordTo(T1, V1); \
4862 test.run(); \
4863 \
4864 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4865 reset(); \
4866 } while (0)
4867
4868 #define TestImplSingleXmmAddr(Dst, Inst) \
4869 do { \
4870 static constexpr char TestString[] = "(" #Dst ", Addr, " #Inst ")"; \
4871 const uint32_t T0 = allocateDqword(); \
4872 const uint32_t T1 = allocateDqword(); \
4873 \
4874 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4875 __ Inst(IceType_f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
4876 Immediate(Inst##Imm)); \
4877 \
4878 AssembledTest test = assemble(); \
4879 test.setDqwordTo(T0, V0); \
4880 test.setDqwordTo(T1, V1); \
4881 test.run(); \
4882 \
4883 ASSERT_EQ(Inst##Expected, test.Dst<Dqword>()) << TestString; \
4884 reset(); \
4885 } while (0)
4886
4887 #define TestImplSingleXmmXmmUntyped(Dst, Src, Inst) \
4888 do { \
4889 static constexpr char TestString[] = \
4890 "(" #Dst ", " #Src ", " #Inst ", Untyped)"; \
4891 const uint32_t T0 = allocateDqword(); \
4892 const uint32_t T1 = allocateDqword(); \
4893 \
4894 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4895 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4896 __ Inst(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), Immediate(Inst##Imm)); \
4897 \
4898 AssembledTest test = assemble(); \
4899 test.setDqwordTo(T0, V0); \
4900 test.setDqwordTo(T1, V1); \
4901 test.run(); \
4902 \
4903 ASSERT_EQ(Inst##UntypedExpected, test.Dst<Dqword>()) << TestString; \
4904 reset(); \
4905 } while (0)
4906
4907 #define TestImpl(Dst, Src) \
4908 do { \
4909 TestImplSingleXmmXmm(Dst, Src, pshufd); \
4910 TestImplSingleXmmAddr(Dst, pshufd); \
4911 TestImplSingleXmmXmm(Dst, Src, shufps); \
4912 TestImplSingleXmmAddr(Dst, shufps); \
4913 } while (0)
4914
4915 TestImpl(xmm0, xmm1);
4916 TestImpl(xmm1, xmm2);
4917 TestImpl(xmm2, xmm3);
4918 TestImpl(xmm3, xmm4);
4919 TestImpl(xmm4, xmm5);
4920 TestImpl(xmm5, xmm6);
4921 TestImpl(xmm6, xmm7);
4922 TestImpl(xmm7, xmm8);
4923 TestImpl(xmm8, xmm9);
4924 TestImpl(xmm9, xmm10);
4925 TestImpl(xmm10, xmm11);
4926 TestImpl(xmm11, xmm12);
4927 TestImpl(xmm12, xmm13);
4928 TestImpl(xmm13, xmm14);
4929 TestImpl(xmm14, xmm15);
4930 TestImpl(xmm15, xmm0);
4931
4932 #undef TestImpl
4933 #undef TestImplSingleXmmXmmUntyped
4934 #undef TestImplSingleXmmAddr
4935 #undef TestImplSingleXmmXmm
4936 }
4937
4938 TEST_F(AssemblerX8664Test, Cvt) {
4939 const Dqword dq2ps32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4940 const Dqword dq2ps32SrcValue(-5, 3, 100, 200);
4941 const Dqword dq2ps32Expected(-5.0f, 3.0f, 100.0, 200.0);
4942
4943 const Dqword dq2ps64DstValue(0.0f, 0.0f, -1.0f, -1.0f);
4944 const Dqword dq2ps64SrcValue(-5, 3, 100, 200);
4945 const Dqword dq2ps64Expected(-5.0f, 3.0f, 100.0, 200.0);
4946
4947 const Dqword tps2dq32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4948 const Dqword tps2dq32SrcValue(-5.0f, 3.0f, 100.0, 200.0);
4949 const Dqword tps2dq32Expected(-5, 3, 100, 200);
4950
4951 const Dqword tps2dq64DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4952 const Dqword tps2dq64SrcValue(-5.0f, 3.0f, 100.0, 200.0);
4953 const Dqword tps2dq64Expected(-5, 3, 100, 200);
4954
4955 const Dqword si2ss32DstValue(-1.0f, -1.0f, -1.0f, -1.0f);
4956 const int32_t si2ss32SrcValue = 5;
4957 const Dqword si2ss32Expected(5.0f, -1.0f, -1.0f, -1.0f);
4958
4959 const Dqword si2ss64DstValue(-1.0, -1.0);
4960 const int32_t si2ss64SrcValue = 5;
4961 const Dqword si2ss64Expected(5.0, -1.0);
4962
4963 const int32_t tss2si32DstValue = 0xF00F0FF0;
4964 const Dqword tss2si32SrcValue(-5.0f, -1.0f, -1.0f, -1.0f);
4965 const int32_t tss2si32Expected = -5;
4966
4967 const int32_t tss2si64DstValue = 0xF00F0FF0;
4968 const Dqword tss2si64SrcValue(-5.0, -1.0);
4969 const int32_t tss2si64Expected = -5;
4970
4971 const Dqword float2float32DstValue(-1.0, -1.0);
4972 const Dqword float2float32SrcValue(-5.0, 3, 100, 200);
4973 const Dqword float2float32Expected(-5.0, -1.0);
4974
4975 const Dqword float2float64DstValue(-1.0, -1.0, -1.0, -1.0);
4976 const Dqword float2float64SrcValue(-5.0, 3.0);
4977 const Dqword float2float64Expected(-5.0, -1.0, -1.0, -1.0);
4978
4979 #define TestImplPXmmXmm(Dst, Src, Inst, Size) \
4980 do { \
4981 static constexpr char TestString[] = \
4982 "(" #Dst ", " #Src ", cvt" #Inst ", f" #Size ")"; \
4983 const uint32_t T0 = allocateDqword(); \
4984 const uint32_t T1 = allocateDqword(); \
4985 \
4986 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
4987 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
4988 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
4989 \
4990 AssembledTest test = assemble(); \
4991 test.setDqwordTo(T0, Inst##Size##DstValue); \
4992 test.setDqwordTo(T1, Inst##Size##SrcValue); \
4993 test.run(); \
4994 \
4995 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
4996 reset(); \
4997 } while (0)
4998
4999 #define TestImplSXmmReg(Dst, GPR, Inst, Size) \
5000 do { \
5001 static constexpr char TestString[] = \
5002 "(" #Dst ", " #GPR ", cvt" #Inst ", f" #Size ")"; \
5003 const uint32_t T0 = allocateDqword(); \
5004 \
5005 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5006 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##SrcValue)); \
5007 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_GPR_##GPR()); \
5008 \
5009 AssembledTest test = assemble(); \
5010 test.setDqwordTo(T0, Inst##Size##DstValue); \
5011 test.run(); \
5012 \
5013 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5014 reset(); \
5015 } while (0)
5016
5017 #define TestImplSRegXmm(GPR, Src, Inst, Size) \
5018 do { \
5019 static constexpr char TestString[] = \
5020 "(" #GPR ", " #Src ", cvt" #Inst ", f" #Size ")"; \
5021 const uint32_t T0 = allocateDqword(); \
5022 \
5023 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
5024 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5025 __ cvt##Inst(IceType_f##Size, Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \
5026 \
5027 AssembledTest test = assemble(); \
5028 test.setDqwordTo(T0, Inst##Size##SrcValue); \
5029 test.run(); \
5030 \
5031 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
5032 << TestString; \
5033 reset(); \
5034 } while (0)
5035
5036 #define TestImplPXmmAddr(Dst, Inst, Size) \
5037 do { \
5038 static constexpr char TestString[] = \
5039 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
5040 const uint32_t T0 = allocateDqword(); \
5041 const uint32_t T1 = allocateDqword(); \
5042 \
5043 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5044 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5045 \
5046 AssembledTest test = assemble(); \
5047 test.setDqwordTo(T0, Inst##Size##DstValue); \
5048 test.setDqwordTo(T1, Inst##Size##SrcValue); \
5049 test.run(); \
5050 \
5051 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5052 reset(); \
5053 } while (0)
5054
5055 #define TestImplSXmmAddr(Dst, Inst, Size) \
5056 do { \
5057 static constexpr char TestString[] = \
5058 "(" #Dst ", Addr, cvt" #Inst ", f" #Size ")"; \
5059 const uint32_t T0 = allocateDqword(); \
5060 const uint32_t T1 = allocateDword(); \
5061 \
5062 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5063 __ cvt##Inst(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5064 \
5065 AssembledTest test = assemble(); \
5066 test.setDqwordTo(T0, Inst##Size##DstValue); \
5067 test.setDwordTo(T1, Inst##Size##SrcValue); \
5068 test.run(); \
5069 \
5070 ASSERT_EQ(Inst##Size##Expected, test.Dst<Dqword>()) << TestString; \
5071 reset(); \
5072 } while (0)
5073
5074 #define TestImplSRegAddr(GPR, Inst, Size) \
5075 do { \
5076 static constexpr char TestString[] = \
5077 "(" #GPR ", Addr, cvt" #Inst ", f" #Size ")"; \
5078 const uint32_t T0 = allocateDqword(); \
5079 \
5080 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Inst##Size##DstValue)); \
5081 __ cvt##Inst(IceType_f##Size, Encoded_GPR_##GPR(), dwordAddress(T0)); \
5082 \
5083 AssembledTest test = assemble(); \
5084 test.setDqwordTo(T0, Inst##Size##SrcValue); \
5085 test.run(); \
5086 \
5087 ASSERT_EQ(static_cast<uint32_t>(Inst##Size##Expected), test.GPR()) \
5088 << TestString; \
5089 reset(); \
5090 } while (0)
5091
5092 #define TestImplSize(Dst, Src, GPR, Size) \
5093 do { \
5094 TestImplPXmmXmm(Dst, Src, dq2ps, Size); \
5095 TestImplPXmmAddr(Src, dq2ps, Size); \
5096 TestImplPXmmXmm(Dst, Src, tps2dq, Size); \
5097 TestImplPXmmAddr(Src, tps2dq, Size); \
5098 TestImplSXmmReg(Dst, GPR, si2ss, Size); \
5099 TestImplSXmmAddr(Dst, si2ss, Size); \
5100 TestImplSRegXmm(GPR, Src, tss2si, Size); \
5101 TestImplSRegAddr(GPR, tss2si, Size); \
5102 TestImplPXmmXmm(Dst, Src, float2float, Size); \
5103 TestImplPXmmAddr(Src, float2float, Size); \
5104 } while (0)
5105
5106 #define TestImpl(Dst, Src, GPR) \
5107 do { \
5108 TestImplSize(Dst, Src, GPR, 32); \
5109 TestImplSize(Dst, Src, GPR, 64); \
5110 } while (0)
5111
5112 TestImpl(xmm0, xmm1, r1);
5113 TestImpl(xmm1, xmm2, r2);
5114 TestImpl(xmm2, xmm3, r3);
5115 TestImpl(xmm3, xmm4, r4);
5116 TestImpl(xmm4, xmm5, r5);
5117 TestImpl(xmm5, xmm6, r6);
5118 TestImpl(xmm6, xmm7, r7);
5119 TestImpl(xmm7, xmm8, r8);
5120 TestImpl(xmm8, xmm9, r10);
5121 TestImpl(xmm9, xmm10, r11);
5122 TestImpl(xmm10, xmm11, r12);
5123 TestImpl(xmm11, xmm12, r13);
5124 TestImpl(xmm12, xmm13, r14);
5125 TestImpl(xmm13, xmm14, r15);
5126 TestImpl(xmm14, xmm15, r1);
5127 TestImpl(xmm15, xmm0, r2);
5128
5129 #undef TestImpl
5130 #undef TestImplSize
5131 #undef TestImplSRegAddr
5132 #undef TestImplSXmmAddr
5133 #undef TestImplPXmmAddr
5134 #undef TestImplSRegXmm
5135 #undef TestImplSXmmReg
5136 #undef TestImplPXmmXmm
5137 }
5138
5139 TEST_F(AssemblerX8664Test, Ucomiss) {
5140 static constexpr float qnan32 = std::numeric_limits<float>::quiet_NaN();
5141 static constexpr double qnan64 = std::numeric_limits<float>::quiet_NaN();
5142
5143 Dqword test32DstValue(0.0, qnan32, qnan32, qnan32);
5144 Dqword test32SrcValue(0.0, qnan32, qnan32, qnan32);
5145
5146 Dqword test64DstValue(0.0, qnan64);
5147 Dqword test64SrcValue(0.0, qnan64);
5148
5149 #define TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, \
5150 BOther) \
5151 do { \
5152 static constexpr char NearBranch = AssemblerX8664::kNearJump; \
5153 static constexpr char TestString[] = \
5154 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #CompType \
5155 ", " #BParity ", " #BOther ")"; \
5156 const uint32_t T0 = allocateDqword(); \
5157 test##Size##DstValue.F##Size[0] = Value0; \
5158 const uint32_t T1 = allocateDqword(); \
5159 test##Size##SrcValue.F##Size[0] = Value1; \
5160 const uint32_t ImmIfTrue = 0xBEEF; \
5161 const uint32_t ImmIfFalse = 0xC0FFE; \
5162 \
5163 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5164 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5165 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
5166 __ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5167 Label Done; \
5168 __ j(Cond::Br_##BParity, &Done, NearBranch); \
5169 __ j(Cond::Br_##BOther, &Done, NearBranch); \
5170 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
5171 __ bind(&Done); \
5172 \
5173 AssembledTest test = assemble(); \
5174 test.setDqwordTo(T0, test##Size##DstValue); \
5175 test.setDqwordTo(T1, test##Size##SrcValue); \
5176 test.run(); \
5177 \
5178 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
5179 reset(); \
5180 } while (0)
5181
5182 #define TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther) \
5183 do { \
5184 static constexpr char NearBranch = AssemblerX8664::kNearJump; \
5185 static constexpr char TestString[] = \
5186 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #CompType \
5187 ", " #BParity ", " #BOther ")"; \
5188 const uint32_t T0 = allocateDqword(); \
5189 test##Size##DstValue.F##Size[0] = Value0; \
5190 const uint32_t T1 = allocateDqword(); \
5191 test##Size##SrcValue.F##Size[0] = Value1; \
5192 const uint32_t ImmIfTrue = 0xBEEF; \
5193 const uint32_t ImmIfFalse = 0xC0FFE; \
5194 \
5195 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5196 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfFalse)); \
5197 __ ucomiss(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5198 Label Done; \
5199 __ j(Cond::Br_##BParity, &Done, NearBranch); \
5200 __ j(Cond::Br_##BOther, &Done, NearBranch); \
5201 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ImmIfTrue)); \
5202 __ bind(&Done); \
5203 \
5204 AssembledTest test = assemble(); \
5205 test.setDqwordTo(T0, test##Size##DstValue); \
5206 test.setDqwordTo(T1, test##Size##SrcValue); \
5207 test.run(); \
5208 \
5209 ASSERT_EQ(ImmIfTrue, test.eax()) << TestString; \
5210 reset(); \
5211 } while (0)
5212
5213 #define TestImplCond(Dst, Value0, Src, Value1, Size, CompType, BParity, \
5214 BOther) \
5215 do { \
5216 TestImplXmmXmm(Dst, Value0, Src, Value1, Size, CompType, BParity, BOther); \
5217 TestImplXmmAddr(Dst, Value0, Value1, Size, CompType, BParity, BOther); \
5218 } while (0)
5219
5220 #define TestImplSize(Dst, Src, Size) \
5221 do { \
5222 TestImplCond(Dst, 1.0, Src, 1.0, Size, isEq, p, ne); \
5223 TestImplCond(Dst, 1.0, Src, 2.0, Size, isNe, p, e); \
5224 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLe, p, a); \
5225 TestImplCond(Dst, 1.0, Src, 1.0, Size, isLe, p, a); \
5226 TestImplCond(Dst, 1.0, Src, 2.0, Size, isLt, p, ae); \
5227 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGe, p, b); \
5228 TestImplCond(Dst, 1.0, Src, 1.0, Size, isGe, p, b); \
5229 TestImplCond(Dst, 2.0, Src, 1.0, Size, isGt, p, be); \
5230 TestImplCond(Dst, qnan##Size, Src, 1.0, Size, isUnord, np, o); \
5231 TestImplCond(Dst, 1.0, Src, qnan##Size, Size, isUnord, np, s); \
5232 TestImplCond(Dst, qnan##Size, Src, qnan##Size, Size, isUnord, np, s); \
5233 } while (0)
5234
5235 #define TestImpl(Dst, Src) \
5236 do { \
5237 TestImplSize(Dst, Src, 32); \
5238 TestImplSize(Dst, Src, 64); \
5239 } while (0)
5240
5241 TestImpl(xmm0, xmm1);
5242 TestImpl(xmm1, xmm2);
5243 TestImpl(xmm2, xmm3);
5244 TestImpl(xmm3, xmm4);
5245 TestImpl(xmm4, xmm5);
5246 TestImpl(xmm5, xmm6);
5247 TestImpl(xmm6, xmm7);
5248 TestImpl(xmm7, xmm8);
5249 TestImpl(xmm8, xmm9);
5250 TestImpl(xmm9, xmm10);
5251 TestImpl(xmm10, xmm11);
5252 TestImpl(xmm11, xmm12);
5253 TestImpl(xmm12, xmm13);
5254 TestImpl(xmm13, xmm14);
5255 TestImpl(xmm14, xmm15);
5256 TestImpl(xmm15, xmm0);
5257
5258 #undef TestImpl
5259 #undef TestImplSize
5260 #undef TestImplCond
5261 #undef TestImplXmmAddr
5262 #undef TestImplXmmXmm
5263 }
5264
5265 TEST_F(AssemblerX8664Test, Movmsk) {
5266 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \
5267 do { \
5268 static constexpr char TestString[] = \
5269 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \
5270 const uint32_t T0 = allocateDqword(); \
5271 const Dqword V0 Value1; \
5272 \
5273 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5274 __ Inst(Encoded_GPR_##GPR(), Encoded_Xmm_##Src()); \
5275 \
5276 AssembledTest test = assemble(); \
5277 test.setDqwordTo(T0, V0); \
5278 test.run(); \
5279 \
5280 ASSERT_EQ(Expected, test.GPR()) << TestString; \
5281 reset(); \
5282 } while (0)
5283
5284 #define TestMovmsk(GPR, Src) \
5285 do { \
5286 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmskps); \
5287 TestMovmskGPRXmm(GPR, Src, (1.0, -1.0), 0x02ul, movmskpd); \
5288 } while (0)
5289
5290 TestMovmsk(r1, xmm0);
5291 TestMovmsk(r2, xmm1);
5292 TestMovmsk(r3, xmm2);
5293 TestMovmsk(r4, xmm3);
5294 TestMovmsk(r5, xmm4);
5295 TestMovmsk(r6, xmm5);
5296 TestMovmsk(r7, xmm6);
5297 TestMovmsk(r8, xmm7);
5298 TestMovmsk(r10, xmm8);
5299 TestMovmsk(r11, xmm9);
5300 TestMovmsk(r12, xmm10);
5301 TestMovmsk(r13, xmm11);
5302 TestMovmsk(r14, xmm12);
5303 TestMovmsk(r15, xmm13);
5304 TestMovmsk(r1, xmm14);
5305 TestMovmsk(r2, xmm15);
5306
5307 #undef TestMovmskGPRXmm
5308 #undef TestMovmsk
5309 }
5310
5311 TEST_F(AssemblerX8664Test, Sqrtss) {
5312 Dqword test32SrcValue(-100.0, -100.0, -100.0, -100.0);
5313 Dqword test32DstValue(-1.0, -1.0, -1.0, -1.0);
5314
5315 Dqword test64SrcValue(-100.0, -100.0);
5316 Dqword test64DstValue(-1.0, -1.0);
5317
5318 #define TestSqrtssXmmXmm(Dst, Src, Value1, Result, Size) \
5319 do { \
5320 static constexpr char TestString[] = \
5321 "(" #Dst ", " #Src ", " #Value1 ", " #Result ", " #Size ")"; \
5322 const uint32_t T0 = allocateDqword(); \
5323 test##Size##SrcValue.F##Size[0] = Value1; \
5324 const uint32_t T1 = allocateDqword(); \
5325 \
5326 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5327 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5328 __ sqrtss(IceType_f##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5329 \
5330 AssembledTest test = assemble(); \
5331 test.setDqwordTo(T0, test##Size##SrcValue); \
5332 test.setDqwordTo(T1, test##Size##DstValue); \
5333 test.run(); \
5334 \
5335 Dqword Expected = test##Size##DstValue; \
5336 Expected.F##Size[0] = Result; \
5337 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5338 reset(); \
5339 } while (0)
5340
5341 #define TestSqrtssXmmAddr(Dst, Value1, Result, Size) \
5342 do { \
5343 static constexpr char TestString[] = \
5344 "(" #Dst ", Addr, " #Value1 ", " #Result ", " #Size ")"; \
5345 const uint32_t T0 = allocateDqword(); \
5346 test##Size##SrcValue.F##Size[0] = Value1; \
5347 const uint32_t T1 = allocateDqword(); \
5348 \
5349 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5350 __ sqrtss(IceType_f##Size, Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5351 \
5352 AssembledTest test = assemble(); \
5353 test.setDqwordTo(T0, test##Size##SrcValue); \
5354 test.setDqwordTo(T1, test##Size##DstValue); \
5355 test.run(); \
5356 \
5357 Dqword Expected = test##Size##DstValue; \
5358 Expected.F##Size[0] = Result; \
5359 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5360 reset(); \
5361 } while (0)
5362
5363 #define TestSqrtssSize(Dst, Src, Size) \
5364 do { \
5365 TestSqrtssXmmXmm(Dst, Src, 4.0, 2.0, Size); \
5366 TestSqrtssXmmAddr(Dst, 4.0, 2.0, Size); \
5367 TestSqrtssXmmXmm(Dst, Src, 9.0, 3.0, Size); \
5368 TestSqrtssXmmAddr(Dst, 9.0, 3.0, Size); \
5369 TestSqrtssXmmXmm(Dst, Src, 100.0, 10.0, Size); \
5370 TestSqrtssXmmAddr(Dst, 100.0, 10.0, Size); \
5371 } while (0)
5372
5373 #define TestSqrtss(Dst, Src) \
5374 do { \
5375 TestSqrtssSize(Dst, Src, 32); \
5376 TestSqrtssSize(Dst, Src, 64); \
5377 } while (0)
5378
5379 TestSqrtss(xmm0, xmm1);
5380 TestSqrtss(xmm1, xmm2);
5381 TestSqrtss(xmm2, xmm3);
5382 TestSqrtss(xmm3, xmm4);
5383 TestSqrtss(xmm4, xmm5);
5384 TestSqrtss(xmm5, xmm6);
5385 TestSqrtss(xmm6, xmm7);
5386 TestSqrtss(xmm7, xmm8);
5387 TestSqrtss(xmm8, xmm9);
5388 TestSqrtss(xmm9, xmm10);
5389 TestSqrtss(xmm10, xmm11);
5390 TestSqrtss(xmm11, xmm12);
5391 TestSqrtss(xmm12, xmm13);
5392 TestSqrtss(xmm13, xmm14);
5393 TestSqrtss(xmm14, xmm15);
5394 TestSqrtss(xmm15, xmm0);
5395
5396 #undef TestSqrtss
5397 #undef TestSqrtssSize
5398 #undef TestSqrtssXmmAddr
5399 #undef TestSqrtssXmmXmm
5400 }
5401
5402 TEST_F(AssemblerX8664Test, Insertps) {
5403 #define TestInsertpsXmmXmmImm(Dst, Value0, Src, Value1, Imm, Expected) \
5404 do { \
5405 static constexpr char TestString[] = \
5406 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Imm ", " #Expected \
5407 ")"; \
5408 const uint32_t T0 = allocateDqword(); \
5409 const Dqword V0 Value0; \
5410 const uint32_t T1 = allocateDqword(); \
5411 const Dqword V1 Value1; \
5412 \
5413 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5414 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5415 __ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
5416 Immediate(Imm)); \
5417 \
5418 AssembledTest test = assemble(); \
5419 test.setDqwordTo(T0, V0); \
5420 test.setDqwordTo(T1, V1); \
5421 test.run(); \
5422 \
5423 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
5424 reset(); \
5425 } while (0)
5426
5427 #define TestInsertpsXmmAddrImm(Dst, Value0, Value1, Imm, Expected) \
5428 do { \
5429 static constexpr char TestString[] = \
5430 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Expected ")"; \
5431 const uint32_t T0 = allocateDqword(); \
5432 const Dqword V0 Value0; \
5433 const uint32_t T1 = allocateDqword(); \
5434 const Dqword V1 Value1; \
5435 \
5436 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5437 __ insertps(IceType_v4f32, Encoded_Xmm_##Dst(), dwordAddress(T1), \
5438 Immediate(Imm)); \
5439 \
5440 AssembledTest test = assemble(); \
5441 test.setDqwordTo(T0, V0); \
5442 test.setDqwordTo(T1, V1); \
5443 test.run(); \
5444 \
5445 ASSERT_EQ(Dqword Expected, test.Dst<Dqword>()) << TestString; \
5446 reset(); \
5447 } while (0)
5448
5449 #define TestInsertps(Dst, Src) \
5450 do { \
5451 TestInsertpsXmmXmmImm( \
5452 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
5453 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5454 0x99, \
5455 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
5456 TestInsertpsXmmAddrImm( \
5457 Dst, (uint64_t(-1), uint64_t(-1)), \
5458 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5459 0x99, \
5460 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x00000000FFFFFFFFull))); \
5461 TestInsertpsXmmXmmImm( \
5462 Dst, (uint64_t(-1), uint64_t(-1)), Src, \
5463 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5464 0x9D, \
5465 (uint64_t(0xDDDDDDDD00000000ull), uint64_t(0x0000000000000000ull))); \
5466 TestInsertpsXmmAddrImm( \
5467 Dst, (uint64_t(-1), uint64_t(-1)), \
5468 (uint64_t(0xAAAAAAAABBBBBBBBull), uint64_t(0xCCCCCCCCDDDDDDDDull)), \
5469 0x9D, \
5470 (uint64_t(0xBBBBBBBB00000000ull), uint64_t(0x0000000000000000ull))); \
5471 } while (0)
5472
5473 TestInsertps(xmm0, xmm1);
5474 TestInsertps(xmm1, xmm2);
5475 TestInsertps(xmm2, xmm3);
5476 TestInsertps(xmm3, xmm4);
5477 TestInsertps(xmm4, xmm5);
5478 TestInsertps(xmm5, xmm6);
5479 TestInsertps(xmm6, xmm7);
5480 TestInsertps(xmm7, xmm8);
5481 TestInsertps(xmm8, xmm9);
5482 TestInsertps(xmm9, xmm10);
5483 TestInsertps(xmm10, xmm11);
5484 TestInsertps(xmm11, xmm12);
5485 TestInsertps(xmm12, xmm13);
5486 TestInsertps(xmm13, xmm14);
5487 TestInsertps(xmm14, xmm15);
5488 TestInsertps(xmm15, xmm0);
5489
5490 #undef TestInsertps
5491 #undef TestInsertpsXmmXmmAddr
5492 #undef TestInsertpsXmmXmmImm
5493 }
5494
5495 TEST_F(AssemblerX8664Test, Pinsr) {
5496 static constexpr uint8_t Mask32 = 0x03;
5497 static constexpr uint8_t Mask16 = 0x07;
5498 static constexpr uint8_t Mask8 = 0x0F;
5499
5500 #define TestPinsrXmmGPRImm(Dst, Value0, GPR, Value1, Imm, Size) \
5501 do { \
5502 static constexpr char TestString[] = \
5503 "(" #Dst ", " #Value0 ", " #GPR ", " #Value1 ", " #Imm ", " #Size ")"; \
5504 const uint32_t T0 = allocateDqword(); \
5505 const Dqword V0 Value0; \
5506 \
5507 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5508 __ mov(IceType_i32, Encoded_GPR_##GPR(), Immediate(Value1)); \
5509 __ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_GPR_##GPR(), \
5510 Immediate(Imm)); \
5511 \
5512 AssembledTest test = assemble(); \
5513 test.setDqwordTo(T0, V0); \
5514 test.run(); \
5515 \
5516 constexpr uint8_t sel = (Imm)&Mask##Size; \
5517 Dqword Expected = V0; \
5518 Expected.U##Size[sel] = Value1; \
5519 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5520 reset(); \
5521 } while (0)
5522
5523 #define TestPinsrXmmAddrImm(Dst, Value0, Value1, Imm, Size) \
5524 do { \
5525 static constexpr char TestString[] = \
5526 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Imm ", " #Size ")"; \
5527 const uint32_t T0 = allocateDqword(); \
5528 const Dqword V0 Value0; \
5529 const uint32_t T1 = allocateDword(); \
5530 const uint32_t V1 = Value1; \
5531 \
5532 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5533 __ pinsr(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1), \
5534 Immediate(Imm)); \
5535 \
5536 AssembledTest test = assemble(); \
5537 test.setDqwordTo(T0, V0); \
5538 test.setDwordTo(T1, V1); \
5539 test.run(); \
5540 \
5541 constexpr uint8_t sel = (Imm)&Mask##Size; \
5542 Dqword Expected = V0; \
5543 Expected.U##Size[sel] = Value1; \
5544 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5545 reset(); \
5546 } while (0)
5547
5548 #define TestPinsrSize(Dst, GPR, Value1, Imm, Size) \
5549 do { \
5550 TestPinsrXmmGPRImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5551 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5552 GPR, Value1, Imm, Size); \
5553 TestPinsrXmmAddrImm(Dst, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5554 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5555 Value1, Imm, Size); \
5556 } while (0)
5557
5558 #define TestPinsr(Src, Dst) \
5559 do { \
5560 TestPinsrSize(Src, Dst, 0xEE, 0x03, 8); \
5561 TestPinsrSize(Src, Dst, 0xFFEE, 0x03, 16); \
5562 TestPinsrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
5563 } while (0)
5564
5565 TestPinsr(xmm0, r1);
5566 TestPinsr(xmm1, r2);
5567 TestPinsr(xmm2, r3);
5568 TestPinsr(xmm3, r4);
5569 TestPinsr(xmm4, r5);
5570 TestPinsr(xmm5, r6);
5571 TestPinsr(xmm6, r7);
5572 TestPinsr(xmm7, r8);
5573 TestPinsr(xmm8, r10);
5574 TestPinsr(xmm9, r11);
5575 TestPinsr(xmm10, r12);
5576 TestPinsr(xmm11, r13);
5577 TestPinsr(xmm12, r14);
5578 TestPinsr(xmm13, r15);
5579 TestPinsr(xmm14, r1);
5580 TestPinsr(xmm15, r2);
5581
5582 #undef TestPinsr
5583 #undef TestPinsrSize
5584 #undef TestPinsrXmmAddrImm
5585 #undef TestPinsrXmmGPRImm
5586 }
5587
5588 TEST_F(AssemblerX8664Test, Pextr) {
5589 static constexpr uint8_t Mask32 = 0x03;
5590 static constexpr uint8_t Mask16 = 0x07;
5591 static constexpr uint8_t Mask8 = 0x0F;
5592
5593 #define TestPextrGPRXmmImm(GPR, Src, Value1, Imm, Size) \
5594 do { \
5595 static constexpr char TestString[] = \
5596 "(" #GPR ", " #Src ", " #Value1 ", " #Imm ", " #Size ")"; \
5597 const uint32_t T0 = allocateDqword(); \
5598 const Dqword V0 Value1; \
5599 \
5600 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5601 __ pextr(IceType_i##Size, Encoded_GPR_##GPR(), Encoded_Xmm_##Src(), \
5602 Immediate(Imm)); \
5603 \
5604 AssembledTest test = assemble(); \
5605 test.setDqwordTo(T0, V0); \
5606 test.run(); \
5607 \
5608 constexpr uint8_t sel = (Imm)&Mask##Size; \
5609 ASSERT_EQ(V0.U##Size[sel], test.GPR()) << TestString; \
5610 reset(); \
5611 } while (0)
5612
5613 #define TestPextrSize(GPR, Src, Value1, Imm, Size) \
5614 do { \
5615 TestPextrGPRXmmImm(GPR, Src, (uint64_t(0xAAAAAAAABBBBBBBBull), \
5616 uint64_t(0xFFFFFFFFDDDDDDDDull)), \
5617 Imm, Size); \
5618 } while (0)
5619
5620 #define TestPextr(Src, Dst) \
5621 do { \
5622 TestPextrSize(Src, Dst, 0xEE, 0x03, 8); \
5623 TestPextrSize(Src, Dst, 0xFFEE, 0x03, 16); \
5624 TestPextrSize(Src, Dst, 0xC0FFEE, 0x03, 32); \
5625 } while (0)
5626
5627 TestPextr(r1, xmm0);
5628 TestPextr(r2, xmm1);
5629 TestPextr(r3, xmm2);
5630 TestPextr(r4, xmm3);
5631 TestPextr(r5, xmm4);
5632 TestPextr(r6, xmm5);
5633 TestPextr(r7, xmm6);
5634 TestPextr(r8, xmm7);
5635 TestPextr(r10, xmm8);
5636 TestPextr(r11, xmm9);
5637 TestPextr(r12, xmm10);
5638 TestPextr(r13, xmm11);
5639 TestPextr(r14, xmm12);
5640 TestPextr(r15, xmm13);
5641 TestPextr(r1, xmm14);
5642 TestPextr(r2, xmm15);
5643
5644 #undef TestPextr
5645 #undef TestPextrSize
5646 #undef TestPextrXmmGPRImm
5647 }
5648
5649 TEST_F(AssemblerX8664Test, Pmovsxdq) {
5650 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \
5651 do { \
5652 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \
5653 const uint32_t T0 = allocateDqword(); \
5654 const Dqword V0 Value1; \
5655 const uint32_t T1 = allocateDqword(); \
5656 const Dqword V1(uint64_t(0), uint64_t(0)); \
5657 \
5658 __ movups(Encoded_Xmm_##Src(), dwordAddress(T0)); \
5659 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5660 __ pmovsxdq(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5661 \
5662 AssembledTest test = assemble(); \
5663 test.setDqwordTo(T0, V0); \
5664 test.setDqwordTo(T1, V1); \
5665 test.run(); \
5666 \
5667 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \
5668 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5669 reset(); \
5670 } while (0)
5671
5672 #define TestPmovsxdq(Dst, Src) \
5673 do { \
5674 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \
5675 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5676 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \
5677 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5678 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \
5679 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5680 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \
5681 uint64_t(0xAAAAAAAAEEEEEEEEull))); \
5682 } while (0)
5683
5684 TestPmovsxdq(xmm0, xmm1);
5685 TestPmovsxdq(xmm1, xmm2);
5686 TestPmovsxdq(xmm2, xmm3);
5687 TestPmovsxdq(xmm3, xmm4);
5688 TestPmovsxdq(xmm4, xmm5);
5689 TestPmovsxdq(xmm5, xmm6);
5690 TestPmovsxdq(xmm6, xmm7);
5691 TestPmovsxdq(xmm7, xmm8);
5692 TestPmovsxdq(xmm8, xmm9);
5693 TestPmovsxdq(xmm9, xmm10);
5694 TestPmovsxdq(xmm10, xmm11);
5695 TestPmovsxdq(xmm11, xmm12);
5696 TestPmovsxdq(xmm12, xmm13);
5697 TestPmovsxdq(xmm13, xmm14);
5698 TestPmovsxdq(xmm14, xmm15);
5699 TestPmovsxdq(xmm15, xmm0);
5700
5701 #undef TestPmovsxdq
5702 #undef TestPmovsxdqXmmXmm
5703 }
5704
5705 TEST_F(AssemblerX8664Test, Pcmpeq_Pcmpgt) {
5706 #define TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, Inst, Op) \
5707 do { \
5708 static constexpr char TestString[] = \
5709 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ", " #Op ")"; \
5710 const uint32_t T0 = allocateDqword(); \
5711 const Dqword V0 Value0; \
5712 const uint32_t T1 = allocateDqword(); \
5713 const Dqword V1 Value1; \
5714 \
5715 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5716 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5717 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), Encoded_Xmm_##Src()); \
5718 \
5719 AssembledTest test = assemble(); \
5720 test.setDqwordTo(T0, V0); \
5721 test.setDqwordTo(T1, V1); \
5722 test.run(); \
5723 \
5724 Dqword Expected(uint64_t(0), uint64_t(0)); \
5725 static constexpr uint8_t ArraySize = \
5726 sizeof(Dqword) / sizeof(uint##Size##_t); \
5727 for (uint8_t i = 0; i < ArraySize; ++i) { \
5728 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
5729 } \
5730 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5731 reset(); \
5732 } while (0)
5733
5734 #define TestPcmpXmmAddr(Dst, Value0, Value1, Size, Inst, Op) \
5735 do { \
5736 static constexpr char TestString[] = \
5737 "(" #Dst ", " #Value0 ", Addr, " #Value1 ", " #Size ", " #Op ")"; \
5738 const uint32_t T0 = allocateDqword(); \
5739 const Dqword V0 Value0; \
5740 const uint32_t T1 = allocateDqword(); \
5741 const Dqword V1 Value1; \
5742 \
5743 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5744 __ Inst(IceType_i##Size, Encoded_Xmm_##Dst(), dwordAddress(T1)); \
5745 \
5746 AssembledTest test = assemble(); \
5747 test.setDqwordTo(T0, V0); \
5748 test.setDqwordTo(T1, V1); \
5749 test.run(); \
5750 \
5751 Dqword Expected(uint64_t(0), uint64_t(0)); \
5752 static constexpr uint8_t ArraySize = \
5753 sizeof(Dqword) / sizeof(uint##Size##_t); \
5754 for (uint8_t i = 0; i < ArraySize; ++i) { \
5755 Expected.I##Size[i] = (V1.I##Size[i] Op V0.I##Size[i]) ? -1 : 0; \
5756 } \
5757 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5758 reset(); \
5759 } while (0)
5760
5761 #define TestPcmpValues(Dst, Value0, Src, Value1, Size) \
5762 do { \
5763 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpeq, == ); \
5764 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpeq, == ); \
5765 TestPcmpXmmXmm(Dst, Value0, Src, Value1, Size, pcmpgt, < ); \
5766 TestPcmpXmmAddr(Dst, Value0, Value1, Size, pcmpgt, < ); \
5767 } while (0)
5768
5769 #define TestPcmpSize(Dst, Src, Size) \
5770 do { \
5771 TestPcmpValues(Dst, (uint64_t(0x8888888888888888ull), \
5772 uint64_t(0x0000000000000000ull)), \
5773 Src, (uint64_t(0x0000008800008800ull), \
5774 uint64_t(0xFFFFFFFFFFFFFFFFull)), \
5775 Size); \
5776 TestPcmpValues(Dst, (uint64_t(0x123567ABAB55DE01ull), \
5777 uint64_t(0x12345abcde12345Aull)), \
5778 Src, (uint64_t(0x0000008800008800ull), \
5779 uint64_t(0xAABBCCDD1234321Aull)), \
5780 Size); \
5781 } while (0)
5782
5783 #define TestPcmp(Dst, Src) \
5784 do { \
5785 TestPcmpSize(xmm0, xmm1, 8); \
5786 TestPcmpSize(xmm0, xmm1, 16); \
5787 TestPcmpSize(xmm0, xmm1, 32); \
5788 } while (0)
5789
5790 TestPcmp(xmm0, xmm1);
5791 TestPcmp(xmm1, xmm2);
5792 TestPcmp(xmm2, xmm3);
5793 TestPcmp(xmm3, xmm4);
5794 TestPcmp(xmm4, xmm5);
5795 TestPcmp(xmm5, xmm6);
5796 TestPcmp(xmm6, xmm7);
5797 TestPcmp(xmm7, xmm8);
5798 TestPcmp(xmm8, xmm9);
5799 TestPcmp(xmm9, xmm10);
5800 TestPcmp(xmm10, xmm11);
5801 TestPcmp(xmm11, xmm12);
5802 TestPcmp(xmm12, xmm13);
5803 TestPcmp(xmm13, xmm14);
5804 TestPcmp(xmm14, xmm15);
5805 TestPcmp(xmm15, xmm0);
5806
5807 #undef TestPcmp
5808 #undef TestPcmpSize
5809 #undef TestPcmpValues
5810 #undef TestPcmpXmmAddr
5811 #undef TestPcmpXmmXmm
5812 }
5813
5814 TEST_F(AssemblerX8664Test, Roundsd) {
5815 #define TestRoundsdXmmXmm(Dst, Src, Mode, Input, RN) \
5816 do { \
5817 static constexpr char TestString[] = \
5818 "(" #Dst ", " #Src ", " #Mode ", " #Input ", " #RN ")"; \
5819 const uint32_t T0 = allocateDqword(); \
5820 const Dqword V0(-3.0, -3.0); \
5821 const uint32_t T1 = allocateDqword(); \
5822 const Dqword V1(double(Input), -123.4); \
5823 \
5824 __ movups(Encoded_Xmm_##Dst(), dwordAddress(T0)); \
5825 __ movups(Encoded_Xmm_##Src(), dwordAddress(T1)); \
5826 __ roundsd(Encoded_Xmm_##Dst(), Encoded_Xmm_##Src(), \
5827 AssemblerX8664::k##Mode); \
5828 \
5829 AssembledTest test = assemble(); \
5830 test.setDqwordTo(T0, V0); \
5831 test.setDqwordTo(T1, V1); \
5832 test.run(); \
5833 \
5834 const Dqword Expected(double(RN), -3.0); \
5835 EXPECT_EQ(Expected, test.Dst<Dqword>()) << TestString; \
5836 reset(); \
5837 } while (0)
5838
5839 #define TestRoundsd(Dst, Src) \
5840 do { \
5841 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.51, 6); \
5842 TestRoundsdXmmXmm(Dst, Src, RoundToNearest, 5.49, 5); \
5843 TestRoundsdXmmXmm(Dst, Src, RoundDown, 5.51, 5); \
5844 TestRoundsdXmmXmm(Dst, Src, RoundUp, 5.49, 6); \
5845 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.49, 5); \
5846 TestRoundsdXmmXmm(Dst, Src, RoundToZero, 5.51, 5); \
5847 } while (0)
5848
5849 TestRoundsd(xmm0, xmm1);
5850 TestRoundsd(xmm1, xmm2);
5851 TestRoundsd(xmm2, xmm3);
5852 TestRoundsd(xmm3, xmm4);
5853 TestRoundsd(xmm4, xmm5);
5854 TestRoundsd(xmm5, xmm6);
5855 TestRoundsd(xmm6, xmm7);
5856 TestRoundsd(xmm7, xmm8);
5857 TestRoundsd(xmm8, xmm9);
5858 TestRoundsd(xmm9, xmm10);
5859 TestRoundsd(xmm10, xmm11);
5860 TestRoundsd(xmm11, xmm12);
5861 TestRoundsd(xmm12, xmm13);
5862 TestRoundsd(xmm13, xmm14);
5863 TestRoundsd(xmm14, xmm15);
5864 TestRoundsd(xmm15, xmm0);
5865
5866 #undef TestRoundsd
5867 #undef TestRoundsdXmmXmm
5868 }
5869
5870 TEST_F(AssemblerX8664Test, Test) {
5871 static constexpr uint32_t Mask8 = 0xFF;
5872 static constexpr uint32_t Mask16 = 0xFFFF;
5873 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
5874
5875 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
5876 do { \
5877 static constexpr bool NearJump = true; \
5878 static constexpr char TestString[] = \
5879 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
5880 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5881 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5882 \
5883 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
5884 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
5885 __ test(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
5886 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
5887 Label Done; \
5888 __ j(Cond::Br_e, &Done, NearJump); \
5889 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
5890 __ bind(&Done); \
5891 \
5892 AssembledTest test = assemble(); \
5893 test.run(); \
5894 \
5895 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5896 : ValueIfFalse, \
5897 test.Dst()) \
5898 << TestString; \
5899 reset(); \
5900 } while (0)
5901
5902 #define TestImplRegImm(Dst, Value0, Imm, Size) \
5903 do { \
5904 static constexpr bool NearJump = true; \
5905 static constexpr char TestString[] = \
5906 "(" #Dst ", " #Value0 ", " #Imm ", " #Size ")"; \
5907 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5908 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5909 \
5910 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
5911 __ test(IceType_i##Size, Encoded_GPR_##Dst(), \
5912 Immediate((Imm)&Mask##Size)); \
5913 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
5914 Label Done; \
5915 __ j(Cond::Br_e, &Done, NearJump); \
5916 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
5917 __ bind(&Done); \
5918 \
5919 AssembledTest test = assemble(); \
5920 test.run(); \
5921 \
5922 ASSERT_EQ(((Value0)&Mask##Size) & ((Imm)&Mask##Size) ? ValueIfTrue \
5923 : ValueIfFalse, \
5924 test.Dst()) \
5925 << TestString; \
5926 reset(); \
5927 } while (0)
5928
5929 #define TestImplAddrReg(Value0, Src, Value1, Size) \
5930 do { \
5931 static constexpr bool NearJump = true; \
5932 static constexpr char TestString[] = \
5933 "(Addr, " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
5934 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5935 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5936 const uint32_t T0 = allocateDword(); \
5937 \
5938 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
5939 __ test(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
5940 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
5941 Label Done; \
5942 __ j(Cond::Br_e, &Done, NearJump); \
5943 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
5944 __ bind(&Done); \
5945 \
5946 AssembledTest test = assemble(); \
5947 test.setDwordTo(T0, uint32_t(Value0)); \
5948 test.run(); \
5949 \
5950 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5951 : ValueIfFalse, \
5952 test.contentsOfDword(T0)) \
5953 << TestString; \
5954 reset(); \
5955 } while (0)
5956
5957 #define TestImplAddrImm(Value0, Value1, Size) \
5958 do { \
5959 static constexpr bool NearJump = true; \
5960 static constexpr char TestString[] = \
5961 "(Addr, " #Value0 ", " #Value1 ", " #Size ")"; \
5962 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
5963 static constexpr uint32_t ValueIfFalse = 0x11111111; \
5964 const uint32_t T0 = allocateDword(); \
5965 \
5966 __ test(IceType_i##Size, dwordAddress(T0), \
5967 Immediate((Value1)&Mask##Size)); \
5968 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
5969 Label Done; \
5970 __ j(Cond::Br_e, &Done, NearJump); \
5971 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
5972 __ bind(&Done); \
5973 \
5974 AssembledTest test = assemble(); \
5975 test.setDwordTo(T0, uint32_t(Value0)); \
5976 test.run(); \
5977 \
5978 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
5979 : ValueIfFalse, \
5980 test.contentsOfDword(T0)) \
5981 << TestString; \
5982 reset(); \
5983 } while (0)
5984
5985 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
5986 do { \
5987 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
5988 TestImplRegImm(Dst, Value0, Value1, Size); \
5989 TestImplAddrReg(Value0, Src, Value1, Size); \
5990 TestImplAddrImm(Value0, Value1, Size); \
5991 } while (0)
5992
5993 #define TestImplSize(Dst, Src, Size) \
5994 do { \
5995 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
5996 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
5997 TestImplValues(Dst, 0x0F00000F, Src, 0xF00000F0, Size); \
5998 } while (0)
5999
6000 #define TestImpl(Dst, Src) \
6001 do { \
6002 TestImplSize(Dst, Src, 8); \
6003 TestImplSize(Dst, Src, 16); \
6004 TestImplSize(Dst, Src, 32); \
6005 } while (0)
6006
6007 TestImpl(r1, r2);
6008 TestImpl(r2, r3);
6009 TestImpl(r3, r4);
6010 TestImpl(r4, r5);
6011 TestImpl(r5, r6);
6012 TestImpl(r6, r7);
6013 TestImpl(r7, r8);
6014 TestImpl(r8, r10);
6015 TestImpl(r10, r11);
6016 TestImpl(r11, r12);
6017 TestImpl(r12, r13);
6018 TestImpl(r13, r14);
6019 TestImpl(r14, r15);
6020 TestImpl(r15, r1);
6021
6022 #undef TestImpl
6023 #undef TestImplSize
6024 #undef TestImplValues
6025 #undef TestImplAddrImm
6026 #undef TestImplAddrReg
6027 #undef TestImplRegImm
6028 #undef TestImplRegReg
6029 }
6030
6031 // No mull/div because x86.
6032 // No shift because x86.
6033 TEST_F(AssemblerX8664Test, Arith_most) {
6034 static constexpr uint32_t Mask8 = 0xFF;
6035 static constexpr uint32_t Mask16 = 0xFFFF;
6036 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6037
6038 #define TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
6039 do { \
6040 static constexpr char TestString[] = \
6041 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
6042 ", " #Type #Size "_t, " #Op ")"; \
6043 \
6044 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6045 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
6046 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6047 \
6048 AssembledTest test = assemble(); \
6049 test.run(); \
6050 \
6051 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6052 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6053 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6054 Mask##Size &test.Dst()) \
6055 << TestString; \
6056 reset(); \
6057 } while (0)
6058
6059 #define TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op) \
6060 do { \
6061 static constexpr char TestString[] = \
6062 "(" #Inst ", " #Dst ", " #Value0 ", Addr, " #Value1 ", " #Type #Size \
6063 "_t, " #Op ")"; \
6064 const uint32_t T0 = allocateDword(); \
6065 const uint32_t V0 = Value1; \
6066 \
6067 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6068 __ mov(IceType_i##Size, dwordAddress(T0), Immediate(Value1)); \
6069 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
6070 \
6071 AssembledTest test = assemble(); \
6072 test.setDwordTo(T0, V0); \
6073 test.run(); \
6074 \
6075 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6076 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6077 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6078 Mask##Size &test.Dst()) \
6079 << TestString; \
6080 reset(); \
6081 } while (0)
6082
6083 #define TestImplRegImm(Inst, Dst, Value0, Imm, Type, Size, Op) \
6084 do { \
6085 static constexpr char TestString[] = \
6086 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Type #Size \
6087 "_t, " #Op ")"; \
6088 \
6089 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
6090 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
6091 Immediate((Imm)&Mask##Size)); \
6092 \
6093 AssembledTest test = assemble(); \
6094 test.run(); \
6095 \
6096 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6097 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6098 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
6099 Mask##Size &test.Dst()) \
6100 << TestString; \
6101 reset(); \
6102 } while (0)
6103
6104 #define TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op) \
6105 do { \
6106 static constexpr char TestString[] = \
6107 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Type #Size \
6108 "_t, " #Op ")"; \
6109 const uint32_t T0 = allocateDword(); \
6110 const uint32_t V0 = Value0; \
6111 \
6112 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
6113 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
6114 \
6115 AssembledTest test = assemble(); \
6116 test.setDwordTo(T0, V0); \
6117 test.run(); \
6118 \
6119 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6120 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6121 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
6122 Mask##Size &test.contentsOfDword(T0)) \
6123 << TestString; \
6124 reset(); \
6125 } while (0)
6126
6127 #define TestImplAddrImm(Inst, Value0, Imm, Type, Size, Op) \
6128 do { \
6129 static constexpr char TestString[] = \
6130 "(" #Inst ", Addr, " #Value0 ", Imm, " #Imm ", " #Type #Size \
6131 "_t, " #Op ")"; \
6132 const uint32_t T0 = allocateDword(); \
6133 const uint32_t V0 = Value0; \
6134 \
6135 __ Inst(IceType_i##Size, dwordAddress(T0), Immediate((Imm)&Mask##Size)); \
6136 \
6137 AssembledTest test = assemble(); \
6138 test.setDwordTo(T0, V0); \
6139 test.run(); \
6140 \
6141 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
6142 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
6143 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
6144 Mask##Size &test.contentsOfDword(T0)) \
6145 << TestString; \
6146 reset(); \
6147 } while (0)
6148
6149 #define TestImplOp(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
6150 do { \
6151 TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op); \
6152 TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op); \
6153 TestImplRegImm(Inst, Dst, Value0, Value1, Type, Size, Op); \
6154 TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op); \
6155 TestImplAddrImm(Inst, Value0, Value1, Type, Size, Op); \
6156 } while (0)
6157
6158 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
6159 do { \
6160 TestImplOp(And, Dst, Value0, Src, Value1, int, Size, &); \
6161 TestImplOp(And, Dst, Value0, Src, Value1, uint, Size, &); \
6162 TestImplOp(Or, Dst, Value0, Src, Value1, int, Size, | ); \
6163 TestImplOp(Or, Dst, Value0, Src, Value1, uint, Size, | ); \
6164 TestImplOp(Xor, Dst, Value0, Src, Value1, int, Size, ^); \
6165 TestImplOp(Xor, Dst, Value0, Src, Value1, uint, Size, ^); \
6166 TestImplOp(add, Dst, Value0, Src, Value1, int, Size, +); \
6167 TestImplOp(add, Dst, Value0, Src, Value1, uint, Size, +); \
6168 TestImplOp(sub, Dst, Value0, Src, Value1, int, Size, -); \
6169 TestImplOp(sub, Dst, Value0, Src, Value1, uint, Size, -); \
6170 } while (0)
6171
6172 #define TestImplSize(Dst, Src, Size) \
6173 do { \
6174 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
6175 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
6176 TestImplValues(Dst, 0x0F00000F, Src, 0xF0000070, Size); \
6177 TestImplValues(Dst, 0x0F00F00F, Src, 0xF000F070, Size); \
6178 } while (0)
6179
6180 #define TestImpl(Dst, Src) \
6181 do { \
6182 TestImplSize(Dst, Src, 8); \
6183 TestImplSize(Dst, Src, 16); \
6184 TestImplSize(Dst, Src, 32); \
6185 } while (0)
6186
6187 TestImpl(r1, r2);
6188 TestImpl(r2, r3);
6189 TestImpl(r3, r4);
6190 TestImpl(r4, r5);
6191 TestImpl(r5, r6);
6192 TestImpl(r6, r7);
6193 TestImpl(r7, r8);
6194 TestImpl(r8, r10);
6195 TestImpl(r10, r11);
6196 TestImpl(r11, r12);
6197 TestImpl(r12, r13);
6198 TestImpl(r13, r14);
6199 TestImpl(r14, r15);
6200 TestImpl(r15, r1);
6201
6202 #undef TestImpl
6203 #undef TestImplSize
6204 #undef TestImplValues
6205 #undef TestImplOp
6206 #undef TestImplAddrImm
6207 #undef TestImplAddrReg
6208 #undef TestImplRegImm
6209 #undef TestImplRegAddr
6210 #undef TestImplRegReg
6211 }
6212
6213 TEST_F(AssemblerX8664Test, Arith_BorrowNCarry) {
6214 const uint32_t Mask8 = 0x000000FF;
6215 const uint32_t Mask16 = 0x0000FFFF;
6216 const uint32_t Mask32 = 0xFFFFFFFF;
6217
6218 const uint64_t ResultMask8 = 0x000000000000FFFFull;
6219 const uint64_t ResultMask16 = 0x00000000FFFFFFFFull;
6220 const uint64_t ResultMask32 = 0xFFFFFFFFFFFFFFFFull;
6221
6222 #define TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, \
6223 Op, Size) \
6224 do { \
6225 static_assert(Size == 8 || Size == 16 || Size == 32, \
6226 "Invalid size " #Size); \
6227 static constexpr char TestString[] = \
6228 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 ", " #Src0 \
6229 ", " #Src1 ", " #Value1 ", " #Op ", " #Size ")"; \
6230 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6231 Immediate(uint64_t(Value0) & Mask##Size)); \
6232 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6233 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6234 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
6235 Immediate(uint64_t(Value1) & Mask##Size)); \
6236 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
6237 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
6238 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), Encoded_GPR_##Src0()); \
6239 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), Encoded_GPR_##Src1()); \
6240 \
6241 AssembledTest test = assemble(); \
6242 test.run(); \
6243 \
6244 static constexpr uint64_t Result = \
6245 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6246 ResultMask##Size); \
6247 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6248 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6249 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6250 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6251 reset(); \
6252 } while (0)
6253
6254 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size) \
6255 do { \
6256 static_assert(Size == 8 || Size == 16 || Size == 32, \
6257 "Invalid size " #Size); \
6258 static constexpr char TestString[] = \
6259 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
6260 ", Addr, " #Value1 ", " #Op ", " #Size ")"; \
6261 const uint32_t T0 = allocateDword(); \
6262 const uint32_t V0 = uint64_t(Value1) & Mask##Size; \
6263 const uint32_t T1 = allocateDword(); \
6264 const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size; \
6265 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6266 Immediate(uint64_t(Value0) & Mask##Size)); \
6267 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6268 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6269 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), dwordAddress(T0)); \
6270 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), dwordAddress(T1)); \
6271 \
6272 AssembledTest test = assemble(); \
6273 test.setDwordTo(T0, V0); \
6274 test.setDwordTo(T1, V1); \
6275 test.run(); \
6276 \
6277 static constexpr uint64_t Result = \
6278 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6279 ResultMask##Size); \
6280 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6281 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6282 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6283 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6284 reset(); \
6285 } while (0)
6286
6287 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size) \
6288 do { \
6289 static_assert(Size == 8 || Size == 16 || Size == 32, \
6290 "Invalid size " #Size); \
6291 static constexpr char TestString[] = \
6292 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
6293 ", Imm(" #Imm "), " #Op ", " #Size ")"; \
6294 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
6295 Immediate(uint64_t(Value0) & Mask##Size)); \
6296 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
6297 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
6298 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), \
6299 Immediate(uint64_t(Imm) & Mask##Size)); \
6300 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), \
6301 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
6302 \
6303 AssembledTest test = assemble(); \
6304 test.run(); \
6305 \
6306 static constexpr uint64_t Result = \
6307 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
6308 ResultMask##Size); \
6309 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6310 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6311 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
6312 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
6313 reset(); \
6314 } while (0)
6315
6316 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size) \
6317 do { \
6318 static_assert(Size == 8 || Size == 16 || Size == 32, \
6319 "Invalid size " #Size); \
6320 static constexpr char TestString[] = \
6321 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1 \
6322 ", " #Value1 ", " #Op ", " #Size ")"; \
6323 const uint32_t T0 = allocateDword(); \
6324 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
6325 const uint32_t T1 = allocateDword(); \
6326 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
6327 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
6328 Immediate(uint64_t(Value1) & Mask##Size)); \
6329 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
6330 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
6331 __ Inst0(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src0()); \
6332 __ Inst1(IceType_i##Size, dwordAddress(T1), Encoded_GPR_##Src1()); \
6333 \
6334 AssembledTest test = assemble(); \
6335 test.setDwordTo(T0, V0); \
6336 test.setDwordTo(T1, V1); \
6337 test.run(); \
6338 \
6339 static constexpr uint64_t Result = \
6340 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
6341 ResultMask##Size); \
6342 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6343 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6344 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
6345 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
6346 reset(); \
6347 } while (0)
6348
6349 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size) \
6350 do { \
6351 static_assert(Size == 8 || Size == 16 || Size == 32, \
6352 "Invalid size " #Size); \
6353 static constexpr char TestString[] = \
6354 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op \
6355 ", " #Size ")"; \
6356 const uint32_t T0 = allocateDword(); \
6357 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
6358 const uint32_t T1 = allocateDword(); \
6359 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
6360 __ Inst0(IceType_i##Size, dwordAddress(T0), \
6361 Immediate(uint64_t(Imm) & Mask##Size)); \
6362 __ Inst1(IceType_i##Size, dwordAddress(T1), \
6363 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
6364 \
6365 AssembledTest test = assemble(); \
6366 test.setDwordTo(T0, V0); \
6367 test.setDwordTo(T1, V1); \
6368 test.run(); \
6369 \
6370 static constexpr uint64_t Result = \
6371 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
6372 ResultMask##Size); \
6373 static constexpr uint32_t Expected0 = Result & Mask##Size; \
6374 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
6375 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
6376 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
6377 reset(); \
6378 } while (0)
6379
6380 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
6381 Size) \
6382 do { \
6383 TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
6384 Size); \
6385 TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
6386 TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
6387 TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size); \
6388 TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size); \
6389 } while (0)
6390
6391 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size) \
6392 do { \
6393 TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size); \
6394 TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size); \
6395 } while (0)
6396
6397 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size) \
6398 do { \
6399 TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1, \
6400 0xFFFFFFFF0000017Full, Size); \
6401 } while (0)
6402
6403 #define TestImpl(Dst0, Dst1, Src0, Src1) \
6404 do { \
6405 TestImplSize(Dst0, Dst1, Src0, Src1, 8); \
6406 TestImplSize(Dst0, Dst1, Src0, Src1, 16); \
6407 TestImplSize(Dst0, Dst1, Src0, Src1, 32); \
6408 } while (0)
6409
6410 TestImpl(r1, r2, r3, r5);
6411 TestImpl(r2, r3, r4, r6);
6412 TestImpl(r3, r4, r5, r7);
6413 TestImpl(r4, r5, r6, r8);
6414 TestImpl(r5, r6, r7, r10);
6415 TestImpl(r6, r7, r8, r11);
6416 TestImpl(r7, r8, r10, r12);
6417 TestImpl(r8, r10, r11, r13);
6418 TestImpl(r10, r11, r12, r14);
6419 TestImpl(r11, r12, r13, r15);
6420 TestImpl(r12, r13, r14, r1);
6421 TestImpl(r13, r14, r15, r2);
6422 TestImpl(r14, r15, r1, r3);
6423 TestImpl(r15, r1, r2, r4);
6424
6425 #undef TestImpl
6426 #undef TestImplSize
6427 #undef TestImplValues
6428 #undef TestImplOp
6429 #undef TestImplAddrImm
6430 #undef TestImplAddrReg
6431 #undef TestImplRegImm
6432 #undef TestImplRegAddr
6433 #undef TestImplRegReg
6434 }
6435
6436 TEST_F(AssemblerX8664LowLevelTest, Cbw_Cwd_Cdq) {
6437 #define TestImpl(Inst, BytesSize, ...) \
6438 do { \
6439 __ Inst(); \
6440 ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst; \
6441 ASSERT_TRUE(verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__)); \
6442 reset(); \
6443 } while (0)
6444
6445 TestImpl(cbw, 2u, 0x66, 0x98);
6446 TestImpl(cwd, 2u, 0x66, 0x99);
6447 TestImpl(cdq, 1u, 0x99);
6448
6449 #undef TestImpl
6450 }
6451
6452 TEST_F(AssemblerX8664Test, SingleOperandMul) {
6453 static constexpr uint32_t Mask8 = 0x000000FF;
6454 static constexpr uint32_t Mask16 = 0x0000FFFF;
6455 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6456
6457 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
6458 do { \
6459 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
6460 "eax can not be src1."); \
6461 \
6462 static constexpr char TestString[] = \
6463 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
6464 ")"; \
6465 static constexpr Type##64_t OperandEax = \
6466 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
6467 static constexpr Type##64_t OperandOther = \
6468 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
6469 static constexpr uint32_t ExpectedEax = \
6470 Mask##Size & (OperandEax * OperandOther); \
6471 static constexpr uint32_t ExpectedEdx = \
6472 Mask##Size & ((OperandEax * OperandOther) >> Size); \
6473 \
6474 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
6475 Immediate((Value0)&Mask##Size)); \
6476 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6477 Immediate((Value1)&Mask##Size)); \
6478 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
6479 \
6480 if (Size == 8) { \
6481 /* mov %ah, %dl */ \
6482 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6483 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6484 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6485 } \
6486 \
6487 AssembledTest test = assemble(); \
6488 test.run(); \
6489 \
6490 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
6491 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
6492 reset(); \
6493 } while (0)
6494
6495 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
6496 do { \
6497 static constexpr char TestString[] = \
6498 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
6499 static const uint32_t T0 = allocateDword(); \
6500 static constexpr uint32_t V0 = Value1; \
6501 static constexpr Type##64_t OperandEax = \
6502 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
6503 static constexpr Type##64_t OperandOther = \
6504 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
6505 static constexpr uint32_t ExpectedEax = \
6506 Mask##Size & (OperandEax * OperandOther); \
6507 static constexpr uint32_t ExpectedEdx = \
6508 Mask##Size & ((OperandEax * OperandOther) >> Size); \
6509 \
6510 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
6511 Immediate((Value0)&Mask##Size)); \
6512 __ Inst(IceType_i##Size, dwordAddress(T0)); \
6513 \
6514 if (Size == 8) { \
6515 /* mov %ah, %dl */ \
6516 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6517 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6518 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6519 } \
6520 \
6521 AssembledTest test = assemble(); \
6522 test.setDwordTo(T0, V0); \
6523 test.run(); \
6524 \
6525 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
6526 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
6527 reset(); \
6528 } while (0)
6529
6530 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
6531 do { \
6532 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
6533 TestImplAddr(Inst, Value0, Value1, Type, Size); \
6534 } while (0)
6535
6536 #define TestImplValue(Value0, Src, Value1, Size) \
6537 do { \
6538 TestImplOp(mul, Value0, Src, Value1, uint, Size); \
6539 TestImplOp(imul, Value0, Src, Value1, int, Size); \
6540 } while (0)
6541
6542 #define TestImplSize(Src, Size) \
6543 do { \
6544 TestImplValue(10, Src, 1, Size); \
6545 TestImplValue(10, Src, -1, Size); \
6546 TestImplValue(-10, Src, 37, Size); \
6547 TestImplValue(-10, Src, -15, Size); \
6548 } while (0)
6549
6550 #define TestImpl(Src) \
6551 do { \
6552 TestImplSize(Src, 8); \
6553 TestImplSize(Src, 16); \
6554 TestImplSize(Src, 32); \
6555 } while (0)
6556
6557 TestImpl(r2);
6558 TestImpl(r3);
6559 TestImpl(r4);
6560 TestImpl(r5);
6561 TestImpl(r6);
6562 TestImpl(r7);
6563 TestImpl(r8);
6564 TestImpl(r10);
6565 TestImpl(r11);
6566 TestImpl(r12);
6567 TestImpl(r13);
6568 TestImpl(r14);
6569 TestImpl(r15);
6570
6571 #undef TestImpl
6572 #undef TestImplSize
6573 #undef TestImplValue
6574 #undef TestImplOp
6575 #undef TestImplAddr
6576 #undef TestImplReg
6577 }
6578
6579 TEST_F(AssemblerX8664Test, TwoOperandImul) {
6580 static constexpr uint32_t Mask16 = 0x0000FFFF;
6581 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6582
6583 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
6584 do { \
6585 static constexpr char TestString[] = \
6586 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
6587 static constexpr int64_t Operand0 = \
6588 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6589 static constexpr int64_t Operand1 = \
6590 static_cast<int##Size##_t>((Value1)&Mask##Size); \
6591 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6592 \
6593 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6594 Immediate((Value0)&Mask##Size)); \
6595 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6596 Immediate((Value1)&Mask##Size)); \
6597 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6598 \
6599 if (Size == 8) { \
6600 /* mov %ah, %dl */ \
6601 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6602 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6603 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6604 } \
6605 \
6606 AssembledTest test = assemble(); \
6607 test.run(); \
6608 \
6609 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6610 reset(); \
6611 } while (0)
6612
6613 #define TestImplRegImm(Dst, Value0, Imm, Size) \
6614 do { \
6615 static constexpr char TestString[] = \
6616 "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")"; \
6617 static constexpr int64_t Operand0 = \
6618 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6619 static constexpr int64_t Operand1 = \
6620 static_cast<int##Size##_t>((Imm)&Mask##Size); \
6621 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6622 \
6623 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6624 Immediate((Value0)&Mask##Size)); \
6625 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Imm)); \
6626 \
6627 if (Size == 8) { \
6628 /* mov %ah, %dl */ \
6629 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6630 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6631 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6632 } \
6633 \
6634 AssembledTest test = assemble(); \
6635 test.run(); \
6636 \
6637 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6638 reset(); \
6639 } while (0)
6640
6641 #define TestImplRegAddr(Dst, Value0, Value1, Size) \
6642 do { \
6643 static constexpr char TestString[] = \
6644 "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")"; \
6645 static constexpr int64_t Operand0 = \
6646 static_cast<int##Size##_t>((Value0)&Mask##Size); \
6647 static constexpr int64_t Operand1 = \
6648 static_cast<int##Size##_t>((Value1)&Mask##Size); \
6649 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
6650 const uint32_t T0 = allocateDword(); \
6651 \
6652 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6653 Immediate((Value0)&Mask##Size)); \
6654 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
6655 \
6656 if (Size == 8) { \
6657 /* mov %ah, %dl */ \
6658 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6659 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6660 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
6661 } \
6662 \
6663 AssembledTest test = assemble(); \
6664 test.setDwordTo(T0, static_cast<uint32_t>(Operand1)); \
6665 test.run(); \
6666 \
6667 ASSERT_EQ(Expected, test.Dst()) << TestString; \
6668 reset(); \
6669 } while (0)
6670
6671 #define TestImplValue(Dst, Value0, Src, Value1, Size) \
6672 do { \
6673 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
6674 TestImplRegImm(Dst, Value0, Value1, Size); \
6675 TestImplRegAddr(Dst, Value0, Value1, Size); \
6676 } while (0)
6677
6678 #define TestImplSize(Dst, Src, Size) \
6679 do { \
6680 TestImplValue(Dst, 1, Src, 1, Size); \
6681 TestImplValue(Dst, -10, Src, 0x4050AA20, Size); \
6682 TestImplValue(Dst, -2, Src, -55, Size); \
6683 } while (0)
6684
6685 #define TestImpl(Dst, Src) \
6686 do { \
6687 TestImplSize(Dst, Src, 16); \
6688 TestImplSize(Dst, Src, 32); \
6689 } while (0)
6690
6691 TestImpl(r1, r2);
6692 TestImpl(r2, r3);
6693 TestImpl(r3, r4);
6694 TestImpl(r4, r5);
6695 TestImpl(r5, r6);
6696 TestImpl(r6, r7);
6697 TestImpl(r7, r8);
6698 TestImpl(r8, r10);
6699 TestImpl(r10, r11);
6700 TestImpl(r11, r12);
6701 TestImpl(r12, r13);
6702 TestImpl(r13, r14);
6703 TestImpl(r14, r15);
6704 TestImpl(r15, r1);
6705
6706 #undef TestImpl
6707 #undef TestImplSize
6708 #undef TestImplValue
6709 #undef TestImplRegAddr
6710 #undef TestImplRegImm
6711 #undef TestImplRegReg
6712 }
6713
6714 TEST_F(AssemblerX8664Test, Div) {
6715 static constexpr uint32_t Mask8 = 0x000000FF;
6716 static constexpr uint32_t Mask16 = 0x0000FFFF;
6717 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6718
6719 static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull;
6720 static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull;
6721 static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull;
6722
6723 using Operand0Type_int8 = int16_t;
6724 using Operand0Type_uint8 = uint16_t;
6725 using Operand0Type_int16 = int32_t;
6726 using Operand0Type_uint16 = uint32_t;
6727 using Operand0Type_int32 = int64_t;
6728 using Operand0Type_uint32 = uint64_t;
6729
6730 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
6731 do { \
6732 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
6733 "eax can not be src1."); \
6734 static_assert(Encoded_GPR_edx() != Encoded_GPR_##Src(), \
6735 "edx can not be src1."); \
6736 \
6737 static constexpr char TestString[] = \
6738 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
6739 ")"; \
6740 static constexpr Operand0Type_##Type##Size Operand0 = \
6741 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
6742 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
6743 static constexpr Type##Size##_t Operand0Hi = \
6744 (Operand0 >> Size) & Mask##Size; \
6745 static constexpr Type##Size##_t Operand1 = \
6746 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
6747 if (Size == 8) { \
6748 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
6749 __ mov( \
6750 IceType_i16, Encoded_GPR_eax(), \
6751 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
6752 } else { \
6753 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
6754 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
6755 } \
6756 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Operand1)); \
6757 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
6758 if (Size == 8) { \
6759 /* mov %ah, %dl */ \
6760 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6761 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6762 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
6763 if (Encoded_GPR_##Src() == Encoded_GPR_esi()) { \
6764 __ And(IceType_i16, Encoded_GPR_edx(), Immediate(0x00FF)); \
6765 } \
6766 } \
6767 \
6768 AssembledTest test = assemble(); \
6769 test.run(); \
6770 \
6771 static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size; \
6772 static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size; \
6773 ASSERT_EQ(Quocient, test.eax()) << TestString; \
6774 ASSERT_EQ(Reminder, test.edx()) << TestString; \
6775 reset(); \
6776 } while (0)
6777
6778 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
6779 do { \
6780 static constexpr char TestString[] = \
6781 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
6782 static constexpr Operand0Type_##Type##Size Operand0 = \
6783 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
6784 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
6785 static constexpr Type##Size##_t Operand0Hi = \
6786 (Operand0 >> Size) & Mask##Size; \
6787 const uint32_t T0 = allocateDword(); \
6788 static constexpr Type##Size##_t V0 = \
6789 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
6790 if (Size == 8) { \
6791 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
6792 __ mov( \
6793 IceType_i16, Encoded_GPR_eax(), \
6794 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
6795 } else { \
6796 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
6797 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
6798 } \
6799 __ Inst(IceType_i##Size, dwordAddress(T0)); \
6800 if (Size == 8) { \
6801 /* mov %ah, %dl */ \
6802 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
6803 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
6804 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
6805 } \
6806 \
6807 AssembledTest test = assemble(); \
6808 test.setDwordTo(T0, static_cast<uint32_t>(V0)); \
6809 test.run(); \
6810 \
6811 static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size; \
6812 static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size; \
6813 ASSERT_EQ(Quocient, test.eax()) << TestString; \
6814 ASSERT_EQ(Reminder, test.edx()) << TestString; \
6815 reset(); \
6816 } while (0)
6817
6818 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
6819 do { \
6820 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
6821 TestImplAddr(Inst, Value0, Value1, Type, Size); \
6822 } while (0)
6823
6824 #define TestImplValue(Value0, Src, Value1, Size) \
6825 do { \
6826 TestImplOp(div, Value0, Src, Value1, uint, Size); \
6827 TestImplOp(idiv, Value0, Src, Value1, int, Size); \
6828 } while (0)
6829
6830 #define TestImplSize(Src, Size) \
6831 do { \
6832 TestImplValue(10, Src, 1, Size); \
6833 TestImplValue(10, Src, -1, Size); \
6834 } while (0)
6835
6836 #define TestImpl(Src) \
6837 do { \
6838 TestImplSize(Src, 8); \
6839 TestImplSize(Src, 16); \
6840 TestImplSize(Src, 32); \
6841 } while (0)
6842
6843 TestImpl(r2);
6844 TestImpl(r3);
6845 TestImpl(r5);
6846 TestImpl(r6);
6847 TestImpl(r7);
6848 TestImpl(r8);
6849 TestImpl(r10);
6850 TestImpl(r11);
6851 TestImpl(r12);
6852 TestImpl(r13);
6853 TestImpl(r14);
6854 TestImpl(r15);
6855
6856 #undef TestImpl
6857 #undef TestImplSize
6858 #undef TestImplValue
6859 #undef TestImplOp
6860 #undef TestImplAddr
6861 #undef TestImplReg
6862 }
6863
6864 TEST_F(AssemblerX8664Test, Incl_Decl_Addr) {
6865 #define TestImpl(Inst, Value0) \
6866 do { \
6867 const bool IsInc = std::string(#Inst).find("incl") != std::string::npos; \
6868 const uint32_t T0 = allocateDword(); \
6869 const uint32_t V0 = Value0; \
6870 \
6871 __ Inst(dwordAddress(T0)); \
6872 \
6873 AssembledTest test = assemble(); \
6874 test.setDwordTo(T0, V0); \
6875 test.run(); \
6876 \
6877 ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)), \
6878 test.contentsOfDword(T0)); \
6879 reset(); \
6880 } while (0)
6881
6882 #define TestInc(Value0) \
6883 do { \
6884 TestImpl(incl, Value0); \
6885 } while (0)
6886
6887 #define TestDec(Value0) \
6888 do { \
6889 TestImpl(decl, Value0); \
6890 } while (0)
6891
6892 TestInc(230);
6893
6894 TestDec(30);
6895
6896 #undef TestInc
6897 #undef TestDec
6898 #undef TestImpl
6899 }
6900
6901 TEST_F(AssemblerX8664Test, Shifts) {
6902 static constexpr uint32_t Mask8 = 0x000000FF;
6903 static constexpr uint32_t Mask16 = 0x0000FFFF;
6904 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
6905
6906 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size) \
6907 do { \
6908 static constexpr char TestString[] = \
6909 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type \
6910 ", " #Size ")"; \
6911 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
6912 const uint##Size##_t Expected = \
6913 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) | \
6914 (!IsRol ? 0 : (Value0) >> (Size - Imm))); \
6915 \
6916 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6917 Immediate((Value0)&Mask##Size)); \
6918 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
6919 Immediate((Imm)&Mask##Size)); \
6920 \
6921 AssembledTest test = assemble(); \
6922 test.run(); \
6923 \
6924 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6925 reset(); \
6926 } while (0)
6927
6928 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
6929 Type, Size) \
6930 do { \
6931 static constexpr char TestString[] = \
6932 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
6933 ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
6934 const uint##Size##_t Expected = \
6935 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
6936 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
6937 \
6938 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6939 Immediate((Value0)&Mask##Size)); \
6940 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6941 Immediate((Value1)&Mask##Size)); \
6942 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src(), \
6943 Immediate(Count)); \
6944 \
6945 AssembledTest test = assemble(); \
6946 test.run(); \
6947 \
6948 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6949 reset(); \
6950 } while (0)
6951
6952 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size) \
6953 do { \
6954 static constexpr char TestString[] = \
6955 "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type \
6956 ", " #Size ")"; \
6957 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
6958 const uint##Size##_t Expected = \
6959 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
6960 (!IsRol ? 0 : Value0 >> (Size - Count))); \
6961 \
6962 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6963 Immediate((Value0)&Mask##Size)); \
6964 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
6965 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_ecx()); \
6966 \
6967 AssembledTest test = assemble(); \
6968 test.run(); \
6969 \
6970 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6971 reset(); \
6972 } while (0)
6973
6974 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
6975 Type, Size) \
6976 do { \
6977 static constexpr char TestString[] = \
6978 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count \
6979 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
6980 const uint##Size##_t Expected = \
6981 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
6982 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
6983 \
6984 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
6985 Immediate((Value0)&Mask##Size)); \
6986 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
6987 Immediate((Value1)&Mask##Size)); \
6988 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
6989 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
6990 \
6991 AssembledTest test = assemble(); \
6992 test.run(); \
6993 \
6994 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
6995 reset(); \
6996 } while (0)
6997
6998 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size) \
6999 do { \
7000 static constexpr char TestString[] = \
7001 "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type \
7002 ", " #Size ")"; \
7003 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
7004 const uint##Size##_t Expected = \
7005 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
7006 (!IsRol ? 0 : Value0 >> (Size - Count))); \
7007 const uint32_t T0 = allocateDword(); \
7008 const uint32_t V0 = Value0; \
7009 \
7010 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
7011 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_ecx()); \
7012 \
7013 AssembledTest test = assemble(); \
7014 test.setDwordTo(T0, V0); \
7015 test.run(); \
7016 \
7017 ASSERT_EQ(static_cast<uint32_t>(Expected), \
7018 Mask##Size &test.contentsOfDword(T0)) \
7019 << TestString; \
7020 reset(); \
7021 } while (0)
7022
7023 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7024 Size) \
7025 do { \
7026 static constexpr char TestString[] = \
7027 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count \
7028 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
7029 const uint##Size##_t Expected = \
7030 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
7031 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
7032 const uint32_t T0 = allocateDword(); \
7033 \
7034 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
7035 Immediate((Value1)&Mask##Size)); \
7036 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
7037 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
7038 \
7039 AssembledTest test = assemble(); \
7040 test.setDwordTo(T0, static_cast<uint32_t>(Value0)); \
7041 test.run(); \
7042 \
7043 ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0)) \
7044 << TestString; \
7045 reset(); \
7046 } while (0)
7047
7048 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size) \
7049 do { \
7050 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
7051 "ecx should not be specified as Dst"); \
7052 TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size); \
7053 TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size); \
7054 TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size); \
7055 TestImplAddrCl(Inst, Value0, Count, Op, Type, Size); \
7056 } while (0)
7057
7058 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0, \
7059 Op1, Type, Size) \
7060 do { \
7061 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
7062 "ecx should not be specified as Dst"); \
7063 static_assert(Encoded_GPR_##Src() != Encoded_GPR_ecx(), \
7064 "ecx should not be specified as Src"); \
7065 TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7066 Size); \
7067 TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
7068 Size); \
7069 TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \
7070 } while (0)
7071
7072 #define TestImplValue(Dst, Value0, Count, Size) \
7073 do { \
7074 TestImplOp(rol, Dst, Value0, Count, <<, uint, Size); \
7075 TestImplOp(shl, Dst, Value0, Count, <<, uint, Size); \
7076 TestImplOp(shr, Dst, Value0, Count, >>, uint, Size); \
7077 TestImplOp(sar, Dst, Value0, Count, >>, int, Size); \
7078 } while (0)
7079
7080 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size) \
7081 do { \
7082 TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>, \
7083 uint, Size); \
7084 TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<, \
7085 uint, Size); \
7086 } while (0)
7087
7088 #define TestImplSize(Dst, Size) \
7089 do { \
7090 TestImplValue(Dst, 0x8F, 3, Size); \
7091 TestImplValue(Dst, 0x8FFF, 7, Size); \
7092 TestImplValue(Dst, 0x8FFFF, 7, Size); \
7093 } while (0)
7094
7095 #define TestImplThreeOperandSize(Dst, Src, Size) \
7096 do { \
7097 TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size); \
7098 } while (0)
7099
7100 #define TestImpl(Dst, Src) \
7101 do { \
7102 TestImplSize(Dst, 8); \
7103 TestImplSize(Dst, 16); \
7104 TestImplThreeOperandSize(Dst, Src, 16); \
7105 TestImplSize(Dst, 32); \
7106 TestImplThreeOperandSize(Dst, Src, 32); \
7107 } while (0)
7108
7109 TestImpl(r1, r2);
7110 TestImpl(r2, r4);
7111 TestImpl(r4, r5);
7112 TestImpl(r5, r6);
7113 TestImpl(r6, r7);
7114 TestImpl(r7, r8);
7115 TestImpl(r8, r10);
7116 TestImpl(r10, r11);
7117 TestImpl(r11, r12);
7118 TestImpl(r12, r13);
7119 TestImpl(r13, r14);
7120 TestImpl(r14, r15);
7121 TestImpl(r15, r1);
7122
7123 #undef TestImpl
7124 #undef TestImplThreeOperandSize
7125 #undef TestImplSize
7126 #undef TestImplValue
7127 #undef TestImplThreeOperandValue
7128 #undef TestImplOp
7129 #undef TestImplThreeOperandOp
7130 #undef TestImplAddrCl
7131 #undef TestImplRegRegCl
7132 #undef TestImplRegCl
7133 #undef TestImplRegRegImm
7134 #undef TestImplRegImm
7135 }
7136
7137 TEST_F(AssemblerX8664Test, Neg) {
7138 static constexpr uint32_t Mask8 = 0x000000ff;
7139 static constexpr uint32_t Mask16 = 0x0000ffff;
7140 static constexpr uint32_t Mask32 = 0xffffffff;
7141
7142 #define TestImplReg(Dst, Size) \
7143 do { \
7144 static constexpr int32_t Value = 0xFF00A543; \
7145 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
7146 Immediate(static_cast<int##Size##_t>(Value) & Mask##Size)); \
7147 __ neg(IceType_i##Size, Encoded_GPR_##Dst()); \
7148 __ mov(IceType_i##Size, Encoded_GPR_eax(), Encoded_GPR_##Dst()); \
7149 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(Mask##Size)); \
7150 \
7151 AssembledTest test = assemble(); \
7152 test.run(); \
7153 \
7154 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
7155 test.eax()) \
7156 << "(" #Dst ", " #Size ")"; \
7157 reset(); \
7158 } while (0)
7159
7160 #define TestImplAddr(Size) \
7161 do { \
7162 static constexpr int32_t Value = 0xFF00A543; \
7163 const uint32_t T0 = allocateDword(); \
7164 __ neg(IceType_i##Size, dwordAddress(T0)); \
7165 \
7166 AssembledTest test = assemble(); \
7167 test.setDwordTo(T0, Value &Mask##Size); \
7168 test.run(); \
7169 \
7170 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
7171 test.contentsOfDword(T0)) \
7172 << "(Addr, " #Size ")"; \
7173 reset(); \
7174 } while (0)
7175
7176 #define TestImpl(Size) \
7177 do { \
7178 TestImplAddr(Size); \
7179 TestImplReg(r1, Size); \
7180 TestImplReg(r2, Size); \
7181 TestImplReg(r3, Size); \
7182 TestImplReg(r4, Size); \
7183 TestImplReg(r5, Size); \
7184 TestImplReg(r6, Size); \
7185 TestImplReg(r7, Size); \
7186 TestImplReg(r8, Size); \
7187 TestImplReg(r10, Size); \
7188 TestImplReg(r11, Size); \
7189 TestImplReg(r12, Size); \
7190 TestImplReg(r13, Size); \
7191 TestImplReg(r14, Size); \
7192 TestImplReg(r15, Size); \
7193 } while (0)
7194
7195 TestImpl(8);
7196 TestImpl(16);
7197 TestImpl(32);
7198
7199 #undef TestImpl
7200 #undef TestImplAddr
7201 #undef TestImplReg
7202 }
7203
7204 TEST_F(AssemblerX8664Test, Not) {
7205 #define TestImpl(Dst) \
7206 do { \
7207 static constexpr uint32_t Value = 0xFF00A543; \
7208 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
7209 __ notl(Encoded_GPR_##Dst()); \
7210 \
7211 AssembledTest test = assemble(); \
7212 test.run(); \
7213 \
7214 ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")"; \
7215 reset(); \
7216 } while (0)
7217
7218 TestImpl(r1);
7219 TestImpl(r2);
7220 TestImpl(r3);
7221 TestImpl(r4);
7222 TestImpl(r5);
7223 TestImpl(r6);
7224 TestImpl(r7);
7225 TestImpl(r8);
7226 TestImpl(r10);
7227 TestImpl(r11);
7228 TestImpl(r12);
7229 TestImpl(r13);
7230 TestImpl(r14);
7231 TestImpl(r15);
7232
7233 #undef TestImpl
7234 }
7235
7236 TEST_F(AssemblerX8664Test, Bswap) {
7237 #define TestImpl(Dst) \
7238 do { \
7239 static constexpr uint32_t Value = 0xFF00A543; \
7240 static constexpr uint32_t Expected = 0x43A500FF; \
7241 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
7242 __ bswap(IceType_i32, Encoded_GPR_##Dst()); \
7243 \
7244 AssembledTest test = assemble(); \
7245 test.run(); \
7246 \
7247 ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")"; \
7248 reset(); \
7249 } while (0)
7250
7251 TestImpl(r1);
7252 TestImpl(r2);
7253 TestImpl(r3);
7254 TestImpl(r4);
7255 TestImpl(r5);
7256 TestImpl(r6);
7257 TestImpl(r7);
7258 TestImpl(r8);
7259 TestImpl(r10);
7260 TestImpl(r11);
7261 TestImpl(r12);
7262 TestImpl(r13);
7263 TestImpl(r14);
7264 TestImpl(r15);
7265
7266 #undef TestImpl
7267 }
7268
7269 TEST_F(AssemblerX8664Test, Bt) {
7270 #define TestImpl(Dst, Value0, Src, Value1) \
7271 do { \
7272 static constexpr char TestString[] = \
7273 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")"; \
7274 static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0; \
7275 \
7276 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value0)); \
7277 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value1)); \
7278 __ bt(Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
7279 __ setcc(Cond::Br_b, ByteRegister::Encoded_Reg_al); \
7280 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(0xFFu)); \
7281 \
7282 AssembledTest test = assemble(); \
7283 test.run(); \
7284 \
7285 ASSERT_EQ(Expected, test.eax()) << TestString; \
7286 reset(); \
7287 } while (0)
7288
7289 TestImpl(r1, 0x08000000, r2, 27u);
7290 TestImpl(r2, 0x08000000, r3, 23u);
7291 TestImpl(r3, 0x00000000, r4, 1u);
7292 TestImpl(r4, 0x08000300, r5, 9u);
7293 TestImpl(r5, 0x08000300, r6, 10u);
7294 TestImpl(r6, 0x7FFFEFFF, r7, 13u);
7295 TestImpl(r7, 0x08000000, r8, 27u);
7296 TestImpl(r8, 0x08000000, r10, 23u);
7297 TestImpl(r10, 0x00000000, r11, 1u);
7298 TestImpl(r11, 0x08000300, r12, 9u);
7299 TestImpl(r12, 0x08000300, r13, 10u);
7300 TestImpl(r13, 0x7FFFEFFF, r14, 13u);
7301 TestImpl(r14, 0x08000000, r15, 27u);
7302 TestImpl(r15, 0x08000000, r1, 23u);
7303
7304 #undef TestImpl
7305 }
7306
7307 template <uint32_t Value, uint32_t Bits> class BitScanHelper {
7308 BitScanHelper() = delete;
7309
7310 public:
7311 static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32");
7312 using ValueType =
7313 typename std::conditional<Bits == 16, uint16_t, uint32_t>::type;
7314
7315 private:
7316 static constexpr ValueType BitIndex(bool Forward, ValueType Index) {
7317 return (Value == 0)
7318 ? BitScanHelper<Value, Bits>::NoBitSet
7319 : (Value & (1u << Index)
7320 ? Index
7321 : BitIndex(Forward, (Forward ? Index + 1 : Index - 1)));
7322 }
7323
7324 public:
7325 static constexpr ValueType NoBitSet = static_cast<ValueType>(-1);
7326 static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0);
7327 static constexpr ValueType bsr =
7328 BitIndex(/*Forward*/ false, /*Index=*/Bits - 1);
7329 };
7330
7331 TEST_F(AssemblerX8664Test, BitScanOperations) {
7332 #define TestImplRegReg(Inst, Dst, Src, Value1, Size) \
7333 do { \
7334 static constexpr char TestString[] = \
7335 "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")"; \
7336 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
7337 const uint32_t ZeroFlag = allocateDword(); \
7338 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
7339 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
7340 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7341 \
7342 AssembledTest test = assemble(); \
7343 test.setDwordTo(ZeroFlag, 0u); \
7344 test.run(); \
7345 \
7346 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
7347 test.contentsOfDword(ZeroFlag)) \
7348 << TestString; \
7349 if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) { \
7350 ASSERT_EQ(Expected, test.Dst()) << TestString; \
7351 } \
7352 reset(); \
7353 } while (0)
7354
7355 #define TestImplRegAddr(Inst, Dst, Value1, Size) \
7356 do { \
7357 static constexpr char TestString[] = \
7358 "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")"; \
7359 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
7360 const uint32_t T0 = allocateDword(); \
7361 const uint32_t ZeroFlag = allocateDword(); \
7362 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
7363 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7364 \
7365 AssembledTest test = assemble(); \
7366 test.setDwordTo(T0, Value1); \
7367 test.setDwordTo(ZeroFlag, 0u); \
7368 test.run(); \
7369 \
7370 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
7371 test.contentsOfDword(ZeroFlag)) \
7372 << TestString; \
7373 if (Expected != BitScanHelper<Value1, Size>::NoBitSet) { \
7374 ASSERT_EQ(Expected, test.Dst()) << TestString; \
7375 } \
7376 reset(); \
7377 } while (0)
7378
7379 #define TestImplSize(Dst, Src, Value1, Size) \
7380 do { \
7381 TestImplRegReg(bsf, Dst, Src, Value1, Size); \
7382 TestImplRegAddr(bsf, Dst, Value1, Size); \
7383 TestImplRegReg(bsr, Dst, Src, Value1, Size); \
7384 TestImplRegAddr(bsf, Dst, Value1, Size); \
7385 } while (0)
7386
7387 #define TestImplValue(Dst, Src, Value1) \
7388 do { \
7389 TestImplSize(Dst, Src, Value1, 16); \
7390 TestImplSize(Dst, Src, Value1, 32); \
7391 } while (0)
7392
7393 #define TestImpl(Dst, Src) \
7394 do { \
7395 TestImplValue(Dst, Src, 0x80000001); \
7396 TestImplValue(Dst, Src, 0x00000000); \
7397 TestImplValue(Dst, Src, 0x80001000); \
7398 TestImplValue(Dst, Src, 0x00FFFF00); \
7399 } while (0)
7400
7401 TestImpl(r1, r2);
7402 TestImpl(r2, r3);
7403 TestImpl(r3, r4);
7404 TestImpl(r4, r5);
7405 TestImpl(r5, r6);
7406 TestImpl(r6, r7);
7407 TestImpl(r7, r8);
7408 TestImpl(r8, r10);
7409 TestImpl(r10, r11);
7410 TestImpl(r11, r12);
7411 TestImpl(r12, r13);
7412 TestImpl(r13, r14);
7413 TestImpl(r14, r15);
7414 TestImpl(r15, r1);
7415
7416 #undef TestImpl
7417 #undef TestImplValue
7418 #undef TestImplSize
7419 #undef TestImplRegAddr
7420 #undef TestImplRegReg
7421 }
7422
7423 TEST_F(AssemblerX8664LowLevelTest, Nop) {
7424 #define TestImpl(Size, ...) \
7425 do { \
7426 static constexpr char TestString[] = "(" #Size ", " #__VA_ARGS__ ")"; \
7427 __ nop(Size); \
7428 ASSERT_EQ(Size##u, codeBytesSize()) << TestString; \
7429 ASSERT_TRUE(verifyBytes<Size>(codeBytes(), __VA_ARGS__)) << TestString; \
7430 reset(); \
7431 } while (0);
7432
7433 TestImpl(1, 0x90);
7434 TestImpl(2, 0x66, 0x90);
7435 TestImpl(3, 0x0F, 0x1F, 0x00);
7436 TestImpl(4, 0x0F, 0x1F, 0x40, 0x00);
7437 TestImpl(5, 0x0F, 0x1F, 0x44, 0x00, 0x00);
7438 TestImpl(6, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00);
7439 TestImpl(7, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00);
7440 TestImpl(8, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00);
7441
7442 #undef TestImpl
7443 }
7444
7445 TEST_F(AssemblerX8664LowLevelTest, Int3) {
7446 __ int3();
7447 static constexpr uint32_t ByteCount = 1;
7448 ASSERT_EQ(ByteCount, codeBytesSize());
7449 verifyBytes<ByteCount>(codeBytes(), 0xCC);
7450 }
7451
7452 TEST_F(AssemblerX8664LowLevelTest, Hlt) {
7453 __ hlt();
7454 static constexpr uint32_t ByteCount = 1;
7455 ASSERT_EQ(ByteCount, codeBytesSize());
7456 verifyBytes<ByteCount>(codeBytes(), 0xF4);
7457 }
7458
7459 TEST_F(AssemblerX8664LowLevelTest, Ud2) {
7460 __ ud2();
7461 static constexpr uint32_t ByteCount = 2;
7462 ASSERT_EQ(ByteCount, codeBytesSize());
7463 verifyBytes<ByteCount>(codeBytes(), 0x0F, 0x0B);
7464 }
7465
7466 TEST_F(AssemblerX8664Test, Jmp) {
7467 // TestImplReg uses jmp(Label), so jmp(Label) needs to be tested before it.
7468 #define TestImplAddr(Near) \
7469 do { \
7470 Label ForwardJmp; \
7471 Label BackwardJmp; \
7472 Label Done; \
7473 \
7474 __ jmp(&ForwardJmp, AssemblerX8664::k##Near##Jump); \
7475 __ hlt(); \
7476 __ hlt(); \
7477 __ hlt(); \
7478 __ hlt(); \
7479 __ hlt(); \
7480 __ hlt(); \
7481 __ hlt(); \
7482 __ hlt(); \
7483 __ hlt(); \
7484 __ hlt(); \
7485 __ bind(&BackwardJmp); \
7486 __ jmp(&Done, AssemblerX8664::k##Near##Jump); \
7487 __ hlt(); \
7488 __ hlt(); \
7489 __ hlt(); \
7490 __ hlt(); \
7491 __ hlt(); \
7492 __ hlt(); \
7493 __ hlt(); \
7494 __ hlt(); \
7495 __ hlt(); \
7496 __ hlt(); \
7497 __ bind(&ForwardJmp); \
7498 __ jmp(&BackwardJmp, AssemblerX8664::k##NearJump); \
7499 __ hlt(); \
7500 __ hlt(); \
7501 __ hlt(); \
7502 __ hlt(); \
7503 __ hlt(); \
7504 __ hlt(); \
7505 __ hlt(); \
7506 __ hlt(); \
7507 __ hlt(); \
7508 __ hlt(); \
7509 __ bind(&Done); \
7510 } while (0)
7511
7512 #define TestImplReg(Dst) \
7513 do { \
7514 __ call(Immediate(16)); \
7515 Label Done; \
7516 __ jmp(&Done, AssemblerX8664::kNearJump); \
7517 __ hlt(); \
7518 __ hlt(); \
7519 __ hlt(); \
7520 __ hlt(); \
7521 __ hlt(); \
7522 __ hlt(); \
7523 __ hlt(); \
7524 __ hlt(); \
7525 __ hlt(); \
7526 __ hlt(); \
7527 __ popl(Encoded_GPR_##Dst()); \
7528 __ jmp(Encoded_GPR_##Dst()); \
7529 __ hlt(); \
7530 __ hlt(); \
7531 __ hlt(); \
7532 __ hlt(); \
7533 __ hlt(); \
7534 __ hlt(); \
7535 __ hlt(); \
7536 __ hlt(); \
7537 __ hlt(); \
7538 __ hlt(); \
7539 __ bind(&Done); \
7540 \
7541 AssembledTest test = assemble(); \
7542 test.run(); \
7543 \
7544 reset(); \
7545 } while (0)
7546
7547 TestImplAddr(Near);
7548 TestImplAddr(Far);
7549
7550 TestImplReg(r1);
7551 TestImplReg(r2);
7552 TestImplReg(r3);
7553 TestImplReg(r4);
7554 TestImplReg(r5);
7555 TestImplReg(r6);
7556 TestImplReg(r7);
7557 TestImplReg(r8);
7558 TestImplReg(r10);
7559 TestImplReg(r11);
7560 TestImplReg(r12);
7561 TestImplReg(r13);
7562 TestImplReg(r14);
7563 TestImplReg(r15);
7564
7565 #undef TestImplReg
7566 #undef TestImplAddr
7567 }
7568
7569 TEST_F(AssemblerX8664LowLevelTest, Mfence) {
7570 __ mfence();
7571
7572 static constexpr uint8_t ByteCount = 3;
7573 ASSERT_EQ(ByteCount, codeBytesSize());
7574 verifyBytes<ByteCount>(codeBytes(), 0x0F, 0xAE, 0xF0);
7575 }
7576
7577 TEST_F(AssemblerX8664LowLevelTest, Lock) {
7578 __ lock();
7579
7580 static constexpr uint8_t ByteCount = 1;
7581 ASSERT_EQ(ByteCount, codeBytesSize());
7582 verifyBytes<ByteCount>(codeBytes(), 0xF0);
7583 }
7584
7585 TEST_F(AssemblerX8664Test, Xchg) {
7586 static constexpr uint32_t Mask8 = 0x000000FF;
7587 static constexpr uint32_t Mask16 = 0x0000FFFF;
7588 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7589
7590 #define TestImplAddrReg(Value0, Dst1, Value1, Size) \
7591 do { \
7592 static constexpr char TestString[] = \
7593 "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
7594 const uint32_t T0 = allocateDword(); \
7595 const uint32_t V0 = (Value0)&Mask##Size; \
7596 const uint32_t V1 = (Value1)&Mask##Size; \
7597 \
7598 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), Immediate(Value1)); \
7599 __ xchg(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Dst1()); \
7600 __ And(IceType_i32, Encoded_GPR_##Dst1(), Immediate(Mask##Size)); \
7601 \
7602 AssembledTest test = assemble(); \
7603 test.setDwordTo(T0, V0); \
7604 test.run(); \
7605 \
7606 ASSERT_EQ(V0, test.Dst1()) << TestString; \
7607 ASSERT_EQ(V1, test.contentsOfDword(T0)) << TestString; \
7608 reset(); \
7609 } while (0)
7610
7611 #define TestImplSize(Dst1, Size) \
7612 do { \
7613 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Size); \
7614 } while (0)
7615
7616 #define TestImpl(Dst1) \
7617 do { \
7618 TestImplSize(Dst1, 8); \
7619 TestImplSize(Dst1, 16); \
7620 TestImplSize(Dst1, 32); \
7621 } while (0)
7622
7623 TestImpl(r1);
7624 TestImpl(r2);
7625 TestImpl(r3);
7626 TestImpl(r4);
7627 TestImpl(r5);
7628 TestImpl(r6);
7629 TestImpl(r7);
7630 TestImpl(r8);
7631 TestImpl(r10);
7632 TestImpl(r11);
7633 TestImpl(r12);
7634 TestImpl(r13);
7635 TestImpl(r14);
7636 TestImpl(r15);
7637
7638 #undef TestImpl
7639 #undef TestImplSize
7640 #undef TestImplAddrReg
7641 }
7642
7643 TEST_F(AssemblerX8664Test, Xadd) {
7644 static constexpr bool NotLocked = false;
7645 static constexpr bool Locked = true;
7646
7647 static constexpr uint32_t Mask8 = 0x000000FF;
7648 static constexpr uint32_t Mask16 = 0x0000FFFF;
7649 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7650
7651 #define TestImplAddrReg(Value0, Dst1, Value1, LockedOrNot, Size) \
7652 do { \
7653 static constexpr char TestString[] = \
7654 "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
7655 const uint32_t T0 = allocateDword(); \
7656 const uint32_t V0 = (Value0)&Mask##Size; \
7657 const uint32_t V1 = (Value1)&Mask##Size; \
7658 \
7659 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), Immediate(Value1)); \
7660 __ xadd(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Dst1(), \
7661 LockedOrNot); \
7662 __ And(IceType_i32, Encoded_GPR_##Dst1(), Immediate(Mask##Size)); \
7663 \
7664 AssembledTest test = assemble(); \
7665 test.setDwordTo(T0, V0); \
7666 test.run(); \
7667 \
7668 ASSERT_EQ(V0, test.Dst1()) << TestString; \
7669 ASSERT_EQ(Mask##Size &(V1 + V0), test.contentsOfDword(T0)) << TestString; \
7670 reset(); \
7671 } while (0)
7672
7673 #define TestImplSize(Dst1, Size) \
7674 do { \
7675 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, NotLocked, Size); \
7676 TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Locked, Size); \
7677 } while (0)
7678
7679 #define TestImpl(Dst1) \
7680 do { \
7681 TestImplSize(Dst1, 8); \
7682 TestImplSize(Dst1, 16); \
7683 TestImplSize(Dst1, 32); \
7684 } while (0)
7685
7686 TestImpl(r1);
7687 TestImpl(r2);
7688 TestImpl(r3);
7689 TestImpl(r4);
7690 TestImpl(r5);
7691 TestImpl(r6);
7692 TestImpl(r7);
7693 TestImpl(r8);
7694 TestImpl(r10);
7695 TestImpl(r11);
7696 TestImpl(r12);
7697 TestImpl(r13);
7698 TestImpl(r14);
7699 TestImpl(r15);
7700
7701 #undef TestImpl
7702 #undef TestImplSize
7703 #undef TestImplAddrReg
7704 }
7705
7706 TEST_F(AssemblerX8664LowLevelTest, Xadd) {
7707 static constexpr bool NotLocked = false;
7708 static constexpr bool Locked = true;
7709
7710 // Ensures that xadd emits a lock prefix accordingly.
7711 {
7712 __ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7713 NotLocked);
7714 static constexpr uint8_t ByteCountNotLocked8 = 8;
7715 ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
7716 ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xC0,
7717 0x35, 0x00, 0xFF, 0x01, 0x00));
7718 reset();
7719
7720 __ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7721 static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
7722 ASSERT_EQ(ByteCountLocked8, codeBytesSize());
7723 ASSERT_TRUE(verifyBytes<ByteCountLocked8>(
7724 codeBytes(), 0xF0, 0x44, 0x0F, 0xC0, 0x35, 0x00, 0xFF, 0x01, 0x00));
7725 reset();
7726 }
7727
7728 {
7729 __ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7730 NotLocked);
7731 static constexpr uint8_t ByteCountNotLocked16 = 9;
7732 ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
7733 ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(
7734 codeBytes(), 0x66, 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7735 reset();
7736
7737 __ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7738 static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
7739 ASSERT_EQ(ByteCountLocked16, codeBytesSize());
7740 ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44,
7741 0x0F, 0xC1, 0x35, 0x00, 0xFF,
7742 0x01, 0x00));
7743 reset();
7744 }
7745
7746 {
7747 __ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7748 NotLocked);
7749 static constexpr uint8_t ByteCountNotLocked32 = 8;
7750 ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
7751 ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(
7752 codeBytes(), 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7753 reset();
7754
7755 __ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
7756 static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
7757 ASSERT_EQ(ByteCountLocked32, codeBytesSize());
7758 ASSERT_TRUE(verifyBytes<ByteCountLocked32>(
7759 codeBytes(), 0xF0, 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7760 reset();
7761 }
7762 }
7763
7764 TEST_F(AssemblerX8664LowLevelTest, EmitSegmentOverride) {
7765 #define TestImpl(Prefix) \
7766 do { \
7767 static constexpr uint8_t ByteCount = 1; \
7768 __ emitSegmentOverride(Prefix); \
7769 ASSERT_EQ(ByteCount, codeBytesSize()) << Prefix; \
7770 ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), Prefix)); \
7771 reset(); \
7772 } while (0)
7773
7774 TestImpl(0x26);
7775 TestImpl(0x2E);
7776 TestImpl(0x36);
7777 TestImpl(0x3E);
7778 TestImpl(0x64);
7779 TestImpl(0x65);
7780 TestImpl(0x66);
7781 TestImpl(0x67);
7782
7783 #undef TestImpl
7784 }
7785
7786 TEST_F(AssemblerX8664Test, Cmpxchg8b) {
7787 static constexpr bool NotLocked = false;
7788 static constexpr bool Locked = true;
7789
7790 #define TestImpl(Value0, Value1, ValueMem, LockedOrNot) \
7791 do { \
7792 static constexpr char TestString[] = \
7793 "(" #Value0 ", " #Value1 ", " #ValueMem ", " #LockedOrNot ")"; \
7794 const uint32_t T0 = allocateQword(); \
7795 static constexpr uint64_t V0 = ValueMem; \
7796 const uint32_t ZeroFlag = allocateDword(); \
7797 \
7798 __ mov(IceType_i32, Encoded_GPR_eax(), \
7799 Immediate(uint64_t(Value0) & 0xFFFFFFFF)); \
7800 __ mov(IceType_i32, Encoded_GPR_edx(), Immediate(uint64_t(Value0) >> 32)); \
7801 __ mov(IceType_i32, Encoded_GPR_ebx(), \
7802 Immediate(uint64_t(Value1) & 0xFFFFFFFF)); \
7803 __ mov(IceType_i32, Encoded_GPR_ecx(), Immediate(uint64_t(Value1) >> 32)); \
7804 __ cmpxchg8b(dwordAddress(T0), LockedOrNot); \
7805 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7806 \
7807 AssembledTest test = assemble(); \
7808 test.setQwordTo(T0, V0); \
7809 test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
7810 test.run(); \
7811 \
7812 if (V0 == (Value0)) { \
7813 ASSERT_EQ(uint64_t(Value1), test.contentsOfQword(T0)) << TestString; \
7814 ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
7815 } else { \
7816 ASSERT_EQ(uint64_t(ValueMem) & 0xFFFFFFFF, test.eax()) << TestString; \
7817 ASSERT_EQ((uint64_t(ValueMem) >> 32) & 0xFFFFFFFF, test.edx()) \
7818 << TestString; \
7819 ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
7820 } \
7821 reset(); \
7822 } while (0)
7823
7824 TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, NotLocked);
7825 TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, Locked);
7826 TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, NotLocked);
7827 TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, Locked);
7828
7829 #undef TestImpl
7830 }
7831
7832 TEST_F(AssemblerX8664LowLevelTest, Cmpxchg8b) {
7833 static constexpr bool NotLocked = false;
7834 static constexpr bool Locked = true;
7835
7836 // Ensures that cmpxchg8b emits a lock prefix accordingly.
7837 __ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked);
7838 static constexpr uint8_t ByteCountNotLocked = 7;
7839 ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
7840 ASSERT_TRUE(verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D,
7841 0x00, 0xFF, 0x01, 0x00));
7842 reset();
7843
7844 __ cmpxchg8b(Address::Absolute(0x1FF00), Locked);
7845 static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
7846 ASSERT_EQ(ByteCountLocked, codeBytesSize());
7847 ASSERT_TRUE(verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D,
7848 0x00, 0xFF, 0x01, 0x00));
7849 reset();
7850 }
7851
7852 TEST_F(AssemblerX8664Test, Cmpxchg) {
7853 static constexpr bool NotLocked = false;
7854 static constexpr bool Locked = true;
7855
7856 static constexpr uint32_t Mask8 = 0x000000FF;
7857 static constexpr uint32_t Mask16 = 0x0000FFFF;
7858 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
7859
7860 #define TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, Size) \
7861 do { \
7862 static constexpr char TestString[] = \
7863 "(" #Value0 ", " #Src ", " #Value1 ", " #ValueMem ", " #LockedOrNot \
7864 ", " #Size ")"; \
7865 const uint32_t T0 = allocateDword(); \
7866 static constexpr uint32_t V0 = (ValueMem)&Mask##Size; \
7867 const uint32_t ZeroFlag = allocateDword(); \
7868 \
7869 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
7870 Immediate((Value0)&Mask##Size)); \
7871 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
7872 Immediate((Value1)&Mask##Size)); \
7873 __ cmpxchg(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src(), \
7874 LockedOrNot); \
7875 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
7876 \
7877 AssembledTest test = assemble(); \
7878 test.setDwordTo(T0, V0); \
7879 test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
7880 test.run(); \
7881 \
7882 if (V0 == (Mask##Size & (Value0))) { \
7883 ASSERT_EQ(uint32_t((Value1)&Mask##Size), test.contentsOfDword(T0)) \
7884 << TestString; \
7885 ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
7886 } else { \
7887 ASSERT_EQ(uint32_t((ValueMem)&Mask##Size), test.eax()) << TestString; \
7888 ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
7889 } \
7890 reset(); \
7891 } while (0)
7892
7893 #define TestImplValue(Value0, Src, Value1, ValueMem, LockedOrNot) \
7894 do { \
7895 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 8); \
7896 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 16); \
7897 TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 32); \
7898 } while (0)
7899
7900 #define TestImpl(Src, LockedOrNot) \
7901 do { \
7902 TestImplValue(0xFFFFFFFF, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
7903 TestImplValue(0x0FFF0F0F, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
7904 } while (0)
7905
7906 TestImpl(r2, Locked);
7907 TestImpl(r2, NotLocked);
7908 TestImpl(r3, Locked);
7909 TestImpl(r3, NotLocked);
7910 TestImpl(r4, Locked);
7911 TestImpl(r4, NotLocked);
7912 TestImpl(r5, Locked);
7913 TestImpl(r5, NotLocked);
7914 TestImpl(r6, Locked);
7915 TestImpl(r6, NotLocked);
7916 TestImpl(r7, Locked);
7917 TestImpl(r7, NotLocked);
7918 TestImpl(r8, Locked);
7919 TestImpl(r8, NotLocked);
7920 TestImpl(r10, Locked);
7921 TestImpl(r10, NotLocked);
7922 TestImpl(r11, Locked);
7923 TestImpl(r11, NotLocked);
7924 TestImpl(r12, Locked);
7925 TestImpl(r12, NotLocked);
7926 TestImpl(r13, Locked);
7927 TestImpl(r13, NotLocked);
7928 TestImpl(r14, Locked);
7929 TestImpl(r14, NotLocked);
7930 TestImpl(r15, Locked);
7931 TestImpl(r15, NotLocked);
7932
7933 #undef TestImpl
7934 #undef TestImplValue
7935 #undef TestImplAddrReg
7936 }
7937
7938 TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
7939 static constexpr bool NotLocked = false;
7940 static constexpr bool Locked = true;
7941
7942 // Ensures that cmpxchg emits a lock prefix accordingly.
7943 {
7944 __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7945 NotLocked);
7946 static constexpr uint8_t ByteCountNotLocked8 = 8;
7947 ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
7948 ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xB0,
7949 0x35, 0x00, 0xFF, 0x01, 0x00));
7950 reset();
7951
7952 __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7953 Locked);
7954 static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
7955 ASSERT_EQ(ByteCountLocked8, codeBytesSize());
7956 ASSERT_TRUE(verifyBytes<ByteCountLocked8>(
7957 codeBytes(), 0xF0, 0x44, 0x0F, 0xB0, 0x35, 0x00, 0xFF, 0x01, 0x00));
7958 reset();
7959 }
7960
7961 {
7962 __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7963 NotLocked);
7964 static constexpr uint8_t ByteCountNotLocked16 = 9;
7965 ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
7966 ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(
7967 codeBytes(), 0x66, 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7968 reset();
7969
7970 __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7971 Locked);
7972 static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
7973 ASSERT_EQ(ByteCountLocked16, codeBytesSize());
7974 ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44,
7975 0x0F, 0xB1, 0x35, 0x00, 0xFF,
7976 0x01, 0x00));
7977 reset();
7978 }
7979
7980 {
7981 __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7982 NotLocked);
7983 static constexpr uint8_t ByteCountNotLocked32 = 8;
7984 ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
7985 ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(
7986 codeBytes(), 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7987 reset();
7988
7989 __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
7990 Locked);
7991 static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
7992 ASSERT_EQ(ByteCountLocked32, codeBytesSize());
7993 ASSERT_TRUE(verifyBytes<ByteCountLocked32>(
7994 codeBytes(), 0xF0, 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00));
7995 reset();
7996 }
7997 }
7998
7999 TEST_F(AssemblerX8664Test, Set1ps) {
8000 #define TestImpl(Xmm, Src, Imm) \
8001 do { \
8002 __ set1ps(Encoded_Xmm_##Xmm(), Encoded_GPR_##Src(), Immediate(Imm)); \
8003 \
8004 AssembledTest test = assemble(); \
8005 test.run(); \
8006 \
8007 const Dqword Expected((uint64_t(Imm) << 32) | uint32_t(Imm), \
8008 (uint64_t(Imm) << 32) | uint32_t(Imm)); \
8009 ASSERT_EQ(Expected, test.Xmm<Dqword>()) \
8010 << "(" #Xmm ", " #Src ", " #Imm ")"; \
8011 reset(); \
8012 } while (0)
8013
8014 TestImpl(xmm0, r1, 1);
8015 TestImpl(xmm1, r2, 12);
8016 TestImpl(xmm2, r3, 22);
8017 TestImpl(xmm3, r4, 54);
8018 TestImpl(xmm4, r5, 80);
8019 TestImpl(xmm5, r6, 32);
8020 TestImpl(xmm6, r7, 55);
8021 TestImpl(xmm7, r8, 44);
8022 TestImpl(xmm8, r10, 10);
8023 TestImpl(xmm9, r11, 155);
8024 TestImpl(xmm10, r12, 165);
8025 TestImpl(xmm11, r13, 170);
8026 TestImpl(xmm12, r14, 200);
8027 TestImpl(xmm13, r15, 124);
8028 TestImpl(xmm14, r1, 101);
8029 TestImpl(xmm15, r2, 166);
8030
8031 #undef TestImpl
8032 }
8033
8034 #undef __
8035
8036 } // end of anonymous namespace
8037 } // end of namespace X8664
8038 } // end of namespace Ice
OLDNEW
« src/IceRegistersX8664.h ('K') | « unittest/IceAssemblerX8632Test.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698