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

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: Addresses comments; make format Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « unittest/AssemblerX8664/XmmArith.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/unittest/IceAssemblerX8632.cpp - X8632 Assembler tests -----===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "IceAssemblerX8632.h"
11
12 #include "IceDefs.h"
13
14 #include "gtest/gtest.h"
15
16 #include <cstring>
17 #include <errno.h>
18 #include <iostream>
19 #include <memory>
20 #include <sys/mman.h>
21 #include <type_traits>
22
23 namespace Ice {
24 namespace X8632 {
25 namespace {
26
27 class AssemblerX8632TestBase : public ::testing::Test {
28 protected:
29 using Address = AssemblerX8632::Traits::Address;
30 using Cond = AssemblerX8632::Traits::Cond;
31 using GPRRegister = AssemblerX8632::Traits::GPRRegister;
32 using XmmRegister = AssemblerX8632::Traits::XmmRegister;
33 using X87STRegister = AssemblerX8632::Traits::X87STRegister;
34
35 AssemblerX8632TestBase() { reset(); }
36
37 void reset() { Assembler.reset(new AssemblerX8632()); }
38
39 AssemblerX8632 *assembler() const { return Assembler.get(); }
40
41 size_t codeBytesSize() const { return Assembler->getBufferView().size(); }
42
43 const uint8_t *codeBytes() const {
44 return static_cast<const uint8_t *>(
45 static_cast<const void *>(Assembler->getBufferView().data()));
46 }
47
48 private:
49 std::unique_ptr<AssemblerX8632> Assembler;
50 };
51
52 // __ is a helper macro. It allows test cases to emit X8632 assembly
53 // instructions with
54 //
55 // __ mov(GPRRegister::Reg_Eax, 1);
56 // __ ret();
57 //
58 // and so on. The idea of having this was "stolen" from dart's unit tests.
59 #define __ (this->assembler())->
60
61 // AssemblerX8632LowLevelTest verify that the "basic" instructions the tests
62 // rely on are encoded correctly. Therefore, instead of executing the assembled
63 // code, these tests will verify that the assembled bytes are sane.
64 class AssemblerX8632LowLevelTest : public AssemblerX8632TestBase {
65 protected:
66 // 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
68 // instruction encoding.
69 template <int N, int I> static void verifyBytes(const uint8_t *) {
70 static_assert(I == N, "Invalid template instantiation.");
71 }
72
73 template <int N, int I = 0, typename... Args>
74 static void verifyBytes(const uint8_t *Buffer, uint8_t Byte,
75 Args... OtherBytes) {
76 static_assert(I < N, "Invalid template instantiation.");
77 EXPECT_EQ(Byte, Buffer[I]) << "Byte " << (I + 1) << " of " << N;
78 verifyBytes<N, I + 1>(Buffer, OtherBytes...);
79 assert(Buffer[I] == Byte);
80 }
81 };
82
83 TEST_F(AssemblerX8632LowLevelTest, Ret) {
84 __ ret();
85
86 constexpr size_t ByteCount = 1;
87 ASSERT_EQ(ByteCount, codeBytesSize());
88
89 verifyBytes<ByteCount>(codeBytes(), 0xc3);
90 }
91
92 TEST_F(AssemblerX8632LowLevelTest, CallImm4) {
93 __ call(Immediate(4));
94
95 constexpr size_t ByteCount = 5;
96 ASSERT_EQ(ByteCount, codeBytesSize());
97
98 verifyBytes<ByteCount>(codeBytes(), 0xe8, 0x00, 0x00, 0x00, 0x00);
99 }
100
101 TEST_F(AssemblerX8632LowLevelTest, PopRegs) {
102 __ popl(GPRRegister::Encoded_Reg_eax);
103 __ popl(GPRRegister::Encoded_Reg_ebx);
104 __ popl(GPRRegister::Encoded_Reg_ecx);
105 __ popl(GPRRegister::Encoded_Reg_edx);
106 __ popl(GPRRegister::Encoded_Reg_edi);
107 __ popl(GPRRegister::Encoded_Reg_esi);
108 __ popl(GPRRegister::Encoded_Reg_ebp);
109
110 constexpr size_t ByteCount = 7;
111 ASSERT_EQ(ByteCount, codeBytesSize());
112
113 constexpr uint8_t PopOpcode = 0x58;
114 verifyBytes<ByteCount>(codeBytes(), PopOpcode | GPRRegister::Encoded_Reg_eax,
115 PopOpcode | GPRRegister::Encoded_Reg_ebx,
116 PopOpcode | GPRRegister::Encoded_Reg_ecx,
117 PopOpcode | GPRRegister::Encoded_Reg_edx,
118 PopOpcode | GPRRegister::Encoded_Reg_edi,
119 PopOpcode | GPRRegister::Encoded_Reg_esi,
120 PopOpcode | GPRRegister::Encoded_Reg_ebp);
121 }
122
123 TEST_F(AssemblerX8632LowLevelTest, PushRegs) {
124 __ pushl(GPRRegister::Encoded_Reg_eax);
125 __ pushl(GPRRegister::Encoded_Reg_ebx);
126 __ pushl(GPRRegister::Encoded_Reg_ecx);
127 __ pushl(GPRRegister::Encoded_Reg_edx);
128 __ pushl(GPRRegister::Encoded_Reg_edi);
129 __ pushl(GPRRegister::Encoded_Reg_esi);
130 __ pushl(GPRRegister::Encoded_Reg_ebp);
131
132 constexpr size_t ByteCount = 7;
133 ASSERT_EQ(ByteCount, codeBytesSize());
134
135 constexpr uint8_t PushOpcode = 0x50;
136 verifyBytes<ByteCount>(codeBytes(), PushOpcode | GPRRegister::Encoded_Reg_eax,
137 PushOpcode | GPRRegister::Encoded_Reg_ebx,
138 PushOpcode | GPRRegister::Encoded_Reg_ecx,
139 PushOpcode | GPRRegister::Encoded_Reg_edx,
140 PushOpcode | GPRRegister::Encoded_Reg_edi,
141 PushOpcode | GPRRegister::Encoded_Reg_esi,
142 PushOpcode | GPRRegister::Encoded_Reg_ebp);
143 }
144
145 TEST_F(AssemblerX8632LowLevelTest, MovRegisterZero) {
146 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x00));
147 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(0x00));
148 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(0x00));
149 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(0x00));
150 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(0x00));
151 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x00));
152
153 constexpr size_t MovReg32BitImmBytes = 5;
154 constexpr size_t ByteCount = 6 * MovReg32BitImmBytes;
155 ASSERT_EQ(ByteCount, codeBytesSize());
156
157 constexpr uint8_t MovOpcode = 0xb8;
158 verifyBytes<ByteCount>(
159 codeBytes(), MovOpcode | GPRRegister::Encoded_Reg_eax, 0x00, 0x00, 0x00,
160 0x00, MovOpcode | GPRRegister::Encoded_Reg_ebx, 0x00, 0x00, 0x00, 0x00,
161 MovOpcode | GPRRegister::Encoded_Reg_ecx, 0x00, 0x00, 0x00, 0x00,
162 MovOpcode | GPRRegister::Encoded_Reg_edx, 0x00, 0x00, 0x00, 0x00,
163 MovOpcode | GPRRegister::Encoded_Reg_edi, 0x00, 0x00, 0x00, 0x00,
164 MovOpcode | GPRRegister::Encoded_Reg_esi, 0x00, 0x00, 0x00, 0x00);
165 }
166
167 TEST_F(AssemblerX8632LowLevelTest, CmpRegReg) {
168 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_eax,
169 GPRRegister::Encoded_Reg_ebx);
170 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_ebx,
171 GPRRegister::Encoded_Reg_ecx);
172 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_ecx,
173 GPRRegister::Encoded_Reg_edx);
174 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_edx,
175 GPRRegister::Encoded_Reg_edi);
176 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_edi,
177 GPRRegister::Encoded_Reg_esi);
178 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_esi,
179 GPRRegister::Encoded_Reg_eax);
180
181 const size_t CmpRegRegBytes = 2;
182 const size_t ByteCount = 6 * CmpRegRegBytes;
183 ASSERT_EQ(ByteCount, codeBytesSize());
184
185 constexpr size_t CmpOpcode = 0x3b;
186 constexpr size_t ModRm = 0xC0 /* Register Addressing */;
187 verifyBytes<ByteCount>(
188 codeBytes(), CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_eax << 3) |
189 GPRRegister::Encoded_Reg_ebx,
190 CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_ebx << 3) |
191 GPRRegister::Encoded_Reg_ecx,
192 CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_ecx << 3) |
193 GPRRegister::Encoded_Reg_edx,
194 CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_edx << 3) |
195 GPRRegister::Encoded_Reg_edi,
196 CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_edi << 3) |
197 GPRRegister::Encoded_Reg_esi,
198 CmpOpcode, ModRm | (GPRRegister::Encoded_Reg_esi << 3) |
199 GPRRegister::Encoded_Reg_eax);
200 }
201
202 // After these tests we should have a sane environment; we know the following
203 // work:
204 //
205 // (*) zeroing eax, ebx, ecx, edx, edi, and esi;
206 // (*) call $4 instruction (used for ip materialization);
207 // (*) register push and pop;
208 // (*) cmp reg, reg; and
209 // (*) returning from functions.
210 //
211 // We can now dive into testing each emitting method in AssemblerX8632. Each
212 // test will emit some instructions for performing the test. The assembled
213 // instructions will operate in a "safe" environment. All x86-32 registers are
214 // spilled to the program stack, and the registers are then zeroed out, with the
215 // exception of %esp and %ebp.
216 //
217 // The jitted code and the unittest code will share the same stack. Therefore,
218 // test harnesses need to ensure it does not leave anything it pushed on the
219 // stack.
220 //
221 // %ebp is initialized with a pointer for rIP-based addressing. This pointer is
222 // used for position-independent access to a scratchpad area for use in tests.
223 // This mechanism is used because the test framework needs to generate addresses
224 // that work on both x86-32 and x86-64 hosts, but are encodable using our x86-32
225 // assembler. This is made possible because the encoding for
226 //
227 // pushq %rax (x86-64 only)
228 //
229 // is the same as the one for
230 //
231 // pushl %eax (x86-32 only; not encodable in x86-64)
232 //
233 // Likewise, the encodings for
234 //
235 // movl offset(%ebp), %reg (32-bit only)
236 // movl <src>, offset(%ebp) (32-bit only)
237 //
238 // and
239 //
240 // movl offset(%rbp), %reg (64-bit only)
241 // movl <src>, offset(%rbp) (64-bit only)
242 //
243 // are also the same.
244 //
245 // We use a call instruction in order to generate a natural sized address on the
246 // stack. Said address is then removed from the stack with a pop %rBP, which can
247 // then be used to address memory safely in either x86-32 or x86-64, as long as
248 // the test code does not perform any arithmetic operation that writes to %rBP.
249 // This PC materialization technique is very common in x86-32 PIC.
250 //
251 // %rBP is used to provide the tests with a scratchpad area that can safely and
252 // portably be written to and read from. This scratchpad area is also used to
253 // store the "final" values in eax, ebx, ecx, edx, esi, and edi, allowing the
254 // harnesses access to 6 "return values" instead of the usual single return
255 // value supported by C++.
256 //
257 // The jitted code will look like the following:
258 //
259 // test:
260 // push %eax
261 // push %ebx
262 // push %ecx
263 // push %edx
264 // push %edi
265 // push %esi
266 // push %ebp
267 // call test$materialize_ip
268 // test$materialize_ip: <<------- %eBP will point here
269 // pop %ebp
270 // mov $0, %eax
271 // mov $0, %ebx
272 // mov $0, %ecx
273 // mov $0, %edx
274 // mov $0, %edi
275 // mov $0, %esi
276 //
277 // << test code goes here >>
278 //
279 // mov %eax, { 0 + $ScratchpadOffset}(%ebp)
280 // mov %ebx, { 4 + $ScratchpadOffset}(%ebp)
281 // mov %ecx, { 8 + $ScratchpadOffset}(%ebp)
282 // mov %edx, {12 + $ScratchpadOffset}(%ebp)
283 // mov %edi, {16 + $ScratchpadOffset}(%ebp)
284 // mov %esi, {20 + $ScratchpadOffset}(%ebp)
285 //
286 // pop %ebp
287 // pop %esi
288 // pop %edi
289 // pop %edx
290 // pop %ecx
291 // pop %ebx
292 // pop %eax
293 // ret
294 //
295 // << ... >>
296 //
297 // scratchpad: <<------- accessed via $Offset(%ebp)
298 //
299 // << test scratch area >>
300 //
301 // TODO(jpp): test the
302 //
303 // mov %reg, $Offset(%ebp)
304 //
305 // encodings using the low level assembler test ensuring that the register
306 // values can be written to the scratchpad area.
307 class AssemblerX8632Test : public AssemblerX8632TestBase {
308 protected:
309 AssemblerX8632Test() { reset(); }
310
311 void reset() {
312 AssemblerX8632TestBase::reset();
313
314 NeedsEpilogue = true;
315 // 6 dwords are allocated for saving the GPR state after the jitted code
316 // runs.
317 NumAllocatedDwords = 6;
318 addPrologue();
319 }
320
321 // AssembledBuffer 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
323 // 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
325 // also exposes helper methods for reading the register state after test
326 // execution, as well as for reading the scratchpad area.
327 class AssembledBuffer {
328 AssembledBuffer() = delete;
329 AssembledBuffer(const AssembledBuffer &) = delete;
330 AssembledBuffer &operator=(const AssembledBuffer &) = delete;
331
332 public:
333 static constexpr uint32_t MaximumCodeSize = 1 << 20;
334 static constexpr uint32_t EaxSlot = 0;
335 static constexpr uint32_t EbxSlot = 1;
336 static constexpr uint32_t EcxSlot = 2;
337 static constexpr uint32_t EdxSlot = 3;
338 static constexpr uint32_t EdiSlot = 4;
339 static constexpr uint32_t EsiSlot = 5;
340
341 AssembledBuffer(const uint8_t *Data, const size_t MySize,
342 const size_t ExtraStorageDwords)
343 : Size(MaximumCodeSize + 4 * ExtraStorageDwords) {
344 // MaxCodeSize is needed because EXPECT_LT needs a symbol with a name --
345 // probably a compiler bug?
346 uint32_t MaxCodeSize = MaximumCodeSize;
347 EXPECT_LT(MySize, MaxCodeSize);
348 assert(MySize < MaximumCodeSize);
349 ExecutableData = mmap(nullptr, Size, PROT_WRITE | PROT_READ | PROT_EXEC,
350 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
351 EXPECT_NE(MAP_FAILED, ExecutableData) << strerror(errno);
352 assert(MAP_FAILED != ExecutableData);
353 std::memcpy(ExecutableData, Data, MySize);
354 }
355
356 // We allow AssembledBuffer to be moved so that we can return objects of
357 // this type.
358 AssembledBuffer(AssembledBuffer &&Buffer)
359 : ExecutableData(Buffer.ExecutableData), Size(Buffer.Size) {
360 Buffer.ExecutableData = nullptr;
361 Buffer.Size = 0;
362 }
363
364 AssembledBuffer &operator=(AssembledBuffer &&Buffer) {
365 ExecutableData = Buffer.ExecutableData;
366 Buffer.ExecutableData = nullptr;
367 Size = Buffer.Size;
368 Buffer.Size = 0;
369 return *this;
370 }
371
372 ~AssembledBuffer() {
373 if (ExecutableData != nullptr) {
374 munmap(ExecutableData, Size);
375 ExecutableData = nullptr;
376 }
377 }
378
379 void run() const { reinterpret_cast<void (*)()>(ExecutableData)(); }
380
381 uint32_t eax() const { return contentsOfDword(AssembledBuffer::EaxSlot); }
382
383 uint32_t ebx() const { return contentsOfDword(AssembledBuffer::EbxSlot); }
384
385 uint32_t ecx() const { return contentsOfDword(AssembledBuffer::EcxSlot); }
386
387 uint32_t edx() const { return contentsOfDword(AssembledBuffer::EdxSlot); }
388
389 uint32_t edi() const { return contentsOfDword(AssembledBuffer::EdiSlot); }
390
391 uint32_t esi() const { return contentsOfDword(AssembledBuffer::EsiSlot); }
392
393 // contentsOfDword is used for reading the values in the scratchpad area.
394 // Valid arguments are the dword ids returned by
395 // AssemblerX8632Test::allocateDword() -- other inputs are considered
396 // invalid, and are not guaranteed to work if the implementation changes.
397 uint32_t contentsOfDword(uint32_t Dword) const {
398 return *reinterpret_cast<uint32_t *>(
399 static_cast<uint8_t *>(ExecutableData) + dwordOffset(Dword));
400 }
401
402 private:
403 static uint32_t dwordOffset(uint32_t Index) {
404 return MaximumCodeSize + (Index * 4);
405 }
406
407 void *ExecutableData = nullptr;
408 size_t Size;
409 };
410
411 // assemble created an AssembledBuffer with the jitted code. The first time
412 // assemble is executed it will add the epilogue to the jitted code (which is
413 // the reason why this method is not const qualified.
414 AssembledBuffer assemble() {
415 if (NeedsEpilogue) {
416 addEpilogue();
417 }
418
419 NeedsEpilogue = false;
420 return AssembledBuffer(codeBytes(), codeBytesSize(), NumAllocatedDwords);
421 }
422
423 // Allocates a new dword slot in the test's scratchpad area.
424 uint32_t allocateDword() { return NumAllocatedDwords++; }
425
426 Address dwordAddress(uint32_t Dword) {
427 return Address(GPRRegister::Encoded_Reg_ebp, dwordDisp(Dword));
428 }
429
430 private:
431 // 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
433 // 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
435 // execution these slots' contents are undefined and should not be accessed.
436 Address eaxSlotAddress() { return dwordAddress(AssembledBuffer::EaxSlot); }
437 Address ebxSlotAddress() { return dwordAddress(AssembledBuffer::EbxSlot); }
438 Address ecxSlotAddress() { return dwordAddress(AssembledBuffer::EcxSlot); }
439 Address edxSlotAddress() { return dwordAddress(AssembledBuffer::EdxSlot); }
440 Address ediSlotAddress() { return dwordAddress(AssembledBuffer::EdiSlot); }
441 Address esiSlotAddress() { return dwordAddress(AssembledBuffer::EsiSlot); }
442
443 // Returns the displacement that should be used when accessing the specified
444 // Dword in the scratchpad area. It needs to adjust for the initial
445 // instructions that are emitted before the call that materializes the IP
446 // register.
447 uint32_t dwordDisp(uint32_t Dword) const {
448 EXPECT_LT(Dword, NumAllocatedDwords);
449 assert(Dword < NumAllocatedDwords);
450 static constexpr uint8_t PushBytes = 1;
451 static constexpr uint8_t CallImmBytes = 5;
452 return AssembledBuffer::MaximumCodeSize + (Dword * 4) -
453 (7 * PushBytes + CallImmBytes);
454 }
455
456 void addPrologue() {
457 __ pushl(GPRRegister::Encoded_Reg_eax);
458 __ pushl(GPRRegister::Encoded_Reg_ebx);
459 __ pushl(GPRRegister::Encoded_Reg_ecx);
460 __ pushl(GPRRegister::Encoded_Reg_edx);
461 __ pushl(GPRRegister::Encoded_Reg_edi);
462 __ pushl(GPRRegister::Encoded_Reg_esi);
463 __ pushl(GPRRegister::Encoded_Reg_ebp);
464
465 __ call(Immediate(4));
466 __ popl(GPRRegister::Encoded_Reg_ebp);
467 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x00));
468 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(0x00));
469 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(0x00));
470 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(0x00));
471 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(0x00));
472 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x00));
473 }
474
475 void addEpilogue() {
476 __ mov(IceType_i32, eaxSlotAddress(), GPRRegister::Encoded_Reg_eax);
477 __ mov(IceType_i32, ebxSlotAddress(), GPRRegister::Encoded_Reg_ebx);
478 __ mov(IceType_i32, ecxSlotAddress(), GPRRegister::Encoded_Reg_ecx);
479 __ mov(IceType_i32, edxSlotAddress(), GPRRegister::Encoded_Reg_edx);
480 __ mov(IceType_i32, ediSlotAddress(), GPRRegister::Encoded_Reg_edi);
481 __ mov(IceType_i32, esiSlotAddress(), GPRRegister::Encoded_Reg_esi);
482
483 __ popl(GPRRegister::Encoded_Reg_ebp);
484 __ popl(GPRRegister::Encoded_Reg_esi);
485 __ popl(GPRRegister::Encoded_Reg_edi);
486 __ popl(GPRRegister::Encoded_Reg_edx);
487 __ popl(GPRRegister::Encoded_Reg_ecx);
488 __ popl(GPRRegister::Encoded_Reg_ebx);
489 __ popl(GPRRegister::Encoded_Reg_eax);
490
491 __ ret();
492 }
493
494 bool NeedsEpilogue;
495 uint32_t NumAllocatedDwords;
496 };
497
498 TEST_F(AssemblerX8632Test, MovRegImm) {
499 constexpr uint32_t ExpectedEax = 0x000000FFul;
500 constexpr uint32_t ExpectedEbx = 0x0000FF00ul;
501 constexpr uint32_t ExpectedEcx = 0x00FF0000ul;
502 constexpr uint32_t ExpectedEdx = 0xFF000000ul;
503 constexpr uint32_t ExpectedEdi = 0x6AAA0006ul;
504 constexpr uint32_t ExpectedEsi = 0x6000AAA6ul;
505
506 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedEax));
507 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedEbx));
508 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedEcx));
509 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedEdx));
510 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedEdi));
511 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedEsi));
512
513 AssembledBuffer test = assemble();
514 test.run();
515 EXPECT_EQ(ExpectedEax, test.eax());
516 EXPECT_EQ(ExpectedEbx, test.ebx());
517 EXPECT_EQ(ExpectedEcx, test.ecx());
518 EXPECT_EQ(ExpectedEdx, test.edx());
519 EXPECT_EQ(ExpectedEdi, test.edi());
520 EXPECT_EQ(ExpectedEsi, test.esi());
521 }
522
523 TEST_F(AssemblerX8632Test, MovMemImm) {
524 const uint32_t T0 = allocateDword();
525 constexpr uint32_t ExpectedT0 = 0x00111100ul;
526 const uint32_t T1 = allocateDword();
527 constexpr uint32_t ExpectedT1 = 0x00222200ul;
528 const uint32_t T2 = allocateDword();
529 constexpr uint32_t ExpectedT2 = 0x03333000ul;
530 const uint32_t T3 = allocateDword();
531 constexpr uint32_t ExpectedT3 = 0x00444400ul;
532
533 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
534 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1));
535 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2));
536 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
537
538 AssembledBuffer test = assemble();
539 test.run();
540 EXPECT_EQ(0ul, test.eax());
541 EXPECT_EQ(0ul, test.ebx());
542 EXPECT_EQ(0ul, test.ecx());
543 EXPECT_EQ(0ul, test.edx());
544 EXPECT_EQ(0ul, test.edi());
545 EXPECT_EQ(0ul, test.esi());
546 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
547 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1));
548 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2));
549 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
550 }
551
552 TEST_F(AssemblerX8632Test, MovMemReg) {
553 const uint32_t T0 = allocateDword();
554 constexpr uint32_t ExpectedT0 = 0x00111100ul;
555 const uint32_t T1 = allocateDword();
556 constexpr uint32_t ExpectedT1 = 0x00222200ul;
557 const uint32_t T2 = allocateDword();
558 constexpr uint32_t ExpectedT2 = 0x00333300ul;
559 const uint32_t T3 = allocateDword();
560 constexpr uint32_t ExpectedT3 = 0x00444400ul;
561 const uint32_t T4 = allocateDword();
562 constexpr uint32_t ExpectedT4 = 0x00555500ul;
563 const uint32_t T5 = allocateDword();
564 constexpr uint32_t ExpectedT5 = 0x00666600ul;
565
566 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedT0));
567 __ mov(IceType_i32, dwordAddress(T0), GPRRegister::Encoded_Reg_eax);
568 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedT1));
569 __ mov(IceType_i32, dwordAddress(T1), GPRRegister::Encoded_Reg_ebx);
570 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedT2));
571 __ mov(IceType_i32, dwordAddress(T2), GPRRegister::Encoded_Reg_ecx);
572 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedT3));
573 __ mov(IceType_i32, dwordAddress(T3), GPRRegister::Encoded_Reg_edx);
574 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedT4));
575 __ mov(IceType_i32, dwordAddress(T4), GPRRegister::Encoded_Reg_edi);
576 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedT5));
577 __ mov(IceType_i32, dwordAddress(T5), GPRRegister::Encoded_Reg_esi);
578
579 AssembledBuffer test = assemble();
580 test.run();
581 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0));
582 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1));
583 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2));
584 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3));
585 EXPECT_EQ(ExpectedT4, test.contentsOfDword(T4));
586 EXPECT_EQ(ExpectedT5, test.contentsOfDword(T5));
587 }
588
589 TEST_F(AssemblerX8632Test, MovRegReg) {
590 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x20));
591 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx,
592 GPRRegister::Encoded_Reg_eax);
593 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx,
594 GPRRegister::Encoded_Reg_ebx);
595 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx,
596 GPRRegister::Encoded_Reg_ecx);
597 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi,
598 GPRRegister::Encoded_Reg_edx);
599 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi,
600 GPRRegister::Encoded_Reg_edi);
601
602 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x55000000ul));
603 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax,
604 GPRRegister::Encoded_Reg_esi);
605
606 AssembledBuffer test = assemble();
607 test.run();
608 EXPECT_EQ(0x55000000ul, test.eax());
609 EXPECT_EQ(0x20ul, test.ebx());
610 EXPECT_EQ(0x20ul, test.ecx());
611 EXPECT_EQ(0x20ul, test.edx());
612 EXPECT_EQ(0x20ul, test.edi());
613 EXPECT_EQ(0x55000000ul, test.esi());
614 }
615
616 TEST_F(AssemblerX8632Test, MovRegMem) {
617 const uint32_t T0 = allocateDword();
618 constexpr uint32_t ExpectedT0 = 0x00111100ul;
619 const uint32_t T1 = allocateDword();
620 constexpr uint32_t ExpectedT1 = 0x00222200ul;
621 const uint32_t T2 = allocateDword();
622 constexpr uint32_t ExpectedT2 = 0x00333300ul;
623 const uint32_t T3 = allocateDword();
624 constexpr uint32_t ExpectedT3 = 0x00444400ul;
625 const uint32_t T4 = allocateDword();
626 constexpr uint32_t ExpectedT4 = 0x00555500ul;
627 const uint32_t T5 = allocateDword();
628 constexpr uint32_t ExpectedT5 = 0x00666600ul;
629
630 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0));
631 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, dwordAddress(T0));
632
633 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1));
634 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, dwordAddress(T1));
635
636 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2));
637 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, dwordAddress(T2));
638
639 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3));
640 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, dwordAddress(T3));
641
642 __ mov(IceType_i32, dwordAddress(T4), Immediate(ExpectedT4));
643 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, dwordAddress(T4));
644
645 __ mov(IceType_i32, dwordAddress(T5), Immediate(ExpectedT5));
646 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, dwordAddress(T5));
647
648 AssembledBuffer test = assemble();
649 test.run();
650 EXPECT_EQ(ExpectedT0, test.eax());
651 EXPECT_EQ(ExpectedT1, test.ebx());
652 EXPECT_EQ(ExpectedT2, test.ecx());
653 EXPECT_EQ(ExpectedT3, test.edx());
654 EXPECT_EQ(ExpectedT4, test.edi());
655 EXPECT_EQ(ExpectedT5, test.esi());
656 }
657
658 TEST_F(AssemblerX8632Test, J) {
659 #define TestJ(C, Near, Src0, Value0, Src1, Value1, Dest) \
660 do { \
661 const bool NearJmp = std::strcmp(#Near, "Near") == 0; \
662 Label ShouldBeTaken; \
663 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \
664 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1)); \
665 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(0xBEEF)); \
666 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, \
667 GPRRegister::Encoded_Reg_##Src1); \
668 __ j(Cond::Br_##C, &ShouldBeTaken, NearJmp); \
669 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(0xC0FFEE)); \
670 __ bind(&ShouldBeTaken); \
671 AssembledBuffer test = assemble(); \
672 test.run(); \
673 EXPECT_EQ(Value0, test.Src0()) << "Br_" #C ", " #Near; \
674 EXPECT_EQ(Value1, test.Src1()) << "Br_" #C ", " #Near; \
675 EXPECT_EQ(0xBEEFul, test.Dest()) << "Br_" #C ", " #Near; \
676 reset(); \
677 } while (0)
678
679 TestJ(o, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx);
680 TestJ(o, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx);
681 TestJ(no, Near, ecx, 0x1ul, edx, 0x1ul, edi);
682 TestJ(no, Far, edx, 0x1ul, edi, 0x1ul, esi);
683 TestJ(b, Near, edi, 0x1ul, esi, 0x80000000ul, eax);
684 TestJ(b, Far, esi, 0x1ul, eax, 0x80000000ul, ebx);
685 TestJ(ae, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx);
686 TestJ(ae, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx);
687 TestJ(e, Near, ecx, 0x80000000ul, edx, 0x80000000ul, edi);
688 TestJ(e, Far, edx, 0x80000000ul, edi, 0x80000000ul, esi);
689 TestJ(ne, Near, edi, 0x80000000ul, esi, 0x1ul, eax);
690 TestJ(ne, Far, esi, 0x80000000ul, eax, 0x1ul, ebx);
691 TestJ(be, Near, eax, 0x1ul, ebx, 0x80000000ul, ecx);
692 TestJ(be, Far, ebx, 0x1ul, ecx, 0x80000000ul, edx);
693 TestJ(a, Near, ecx, 0x80000000ul, edx, 0x1ul, edi);
694 TestJ(a, Far, edx, 0x80000000ul, edi, 0x1ul, esi);
695 TestJ(s, Near, edi, 0x1ul, esi, 0x80000000ul, eax);
696 TestJ(s, Far, esi, 0x1ul, eax, 0x80000000ul, ebx);
697 TestJ(ns, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx);
698 TestJ(ns, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx);
699 TestJ(p, Near, ecx, 0x80000000ul, edx, 0x1ul, edi);
700 TestJ(p, Far, edx, 0x80000000ul, edi, 0x1ul, esi);
701 TestJ(np, Near, edi, 0x1ul, esi, 0x80000000ul, eax);
702 TestJ(np, Far, esi, 0x1ul, eax, 0x80000000ul, ebx);
703 TestJ(l, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx);
704 TestJ(l, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx);
705 TestJ(ge, Near, ecx, 0x1ul, edx, 0x80000000ul, edi);
706 TestJ(ge, Far, edx, 0x1ul, edi, 0x80000000ul, esi);
707 TestJ(le, Near, edi, 0x80000000ul, esi, 0x1ul, eax);
708 TestJ(le, Far, esi, 0x80000000ul, eax, 0x1ul, ebx);
709 TestJ(g, Near, eax, 0x1ul, ebx, 0x80000000ul, ecx);
710 TestJ(g, Far, ebx, 0x1ul, ecx, 0x80000000ul, edx);
711
712 #undef TestJ
713 }
714
715 #undef __
716
717 } // end of anonymous namespace
718 } // end of namespace X8632
719 } // end of namespace Ice
OLDNEW
« no previous file with comments | « unittest/AssemblerX8664/XmmArith.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698