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

Side by Side Diff: unittest/IceAssemblerX8632Test.cpp

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

Powered by Google App Engine
This is Rietveld 408576698