• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/unittest/AssemblerX8632/Locked.cpp -------------------------===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "AssemblerX8632/TestUtil.h"
10 
11 namespace Ice {
12 namespace X8632 {
13 namespace Test {
14 namespace {
15 
TEST_F(AssemblerX8632LowLevelTest,Mfence)16 TEST_F(AssemblerX8632LowLevelTest, Mfence) {
17   __ mfence();
18 
19   static constexpr uint8_t ByteCount = 3;
20   ASSERT_EQ(ByteCount, codeBytesSize());
21   verifyBytes<ByteCount>(codeBytes(), 0x0F, 0xAE, 0xF0);
22 }
23 
TEST_F(AssemblerX8632LowLevelTest,Lock)24 TEST_F(AssemblerX8632LowLevelTest, Lock) {
25   __ lock();
26 
27   static constexpr uint8_t ByteCount = 1;
28   ASSERT_EQ(ByteCount, codeBytesSize());
29   verifyBytes<ByteCount>(codeBytes(), 0xF0);
30 }
31 
TEST_F(AssemblerX8632Test,Xchg)32 TEST_F(AssemblerX8632Test, Xchg) {
33   static constexpr uint32_t Mask8 = 0x000000FF;
34   static constexpr uint32_t Mask16 = 0x0000FFFF;
35   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
36 
37 #define TestImplAddrReg(Value0, Dst1, Value1, Size)                            \
38   do {                                                                         \
39     static constexpr char TestString[] =                                       \
40         "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")";                    \
41     const uint32_t T0 = allocateDword();                                       \
42     const uint32_t V0 = (Value0)&Mask##Size;                                   \
43     const uint32_t V1 = (Value1)&Mask##Size;                                   \
44                                                                                \
45     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1,                   \
46            Immediate(Value1));                                                 \
47     __ xchg(IceType_i##Size, dwordAddress(T0),                                 \
48             GPRRegister::Encoded_Reg_##Dst1);                                  \
49     __ And(IceType_i32, GPRRegister::Encoded_Reg_##Dst1,                       \
50            Immediate(Mask##Size));                                             \
51                                                                                \
52     AssembledTest test = assemble();                                           \
53     test.setDwordTo(T0, V0);                                                   \
54     test.run();                                                                \
55                                                                                \
56     ASSERT_EQ(V0, test.Dst1()) << TestString;                                  \
57     ASSERT_EQ(V1, test.contentsOfDword(T0)) << TestString;                     \
58     reset();                                                                   \
59   } while (0)
60 
61 #define TestImplSize(Dst1, Size)                                               \
62   do {                                                                         \
63     TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Size);                       \
64   } while (0)
65 
66 #define TestImpl(Dst1)                                                         \
67   do {                                                                         \
68     if (GPRRegister::Encoded_Reg_##Dst1 < 4) {                                 \
69       TestImplSize(Dst1, 8);                                                   \
70     }                                                                          \
71     TestImplSize(Dst1, 16);                                                    \
72     TestImplSize(Dst1, 32);                                                    \
73   } while (0)
74 
75   TestImpl(eax);
76   TestImpl(ebx);
77   TestImpl(ecx);
78   TestImpl(edx);
79   TestImpl(esi);
80   TestImpl(edi);
81 
82 #undef TestImpl
83 #undef TestImplSize
84 #undef TestImplAddrReg
85 
86 #define TestImplRegReg(Reg0, Value0, Reg1, Value1, Size)                       \
87   do {                                                                         \
88     static constexpr char TestString[] =                                       \
89         "(" #Reg0 "," #Value0 ", " #Reg1 ", " #Value1 ", " #Size ")";          \
90     const uint32_t V0 = (Value0)&Mask##Size;                                   \
91     const uint32_t V1 = (Value1)&Mask##Size;                                   \
92                                                                                \
93     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Reg0,                   \
94            Immediate(Value0));                                                 \
95     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Reg1,                   \
96            Immediate(Value1));                                                 \
97     __ xchg(IceType_i##Size, GPRRegister::Encoded_Reg_##Reg0,                  \
98             GPRRegister::Encoded_Reg_##Reg1);                                  \
99     __ And(IceType_i32, GPRRegister::Encoded_Reg_##Reg0,                       \
100            Immediate(Mask##Size));                                             \
101     __ And(IceType_i32, GPRRegister::Encoded_Reg_##Reg1,                       \
102            Immediate(Mask##Size));                                             \
103                                                                                \
104     AssembledTest test = assemble();                                           \
105     test.run();                                                                \
106                                                                                \
107     ASSERT_EQ(V0, test.Reg1()) << TestString;                                  \
108     ASSERT_EQ(V1, test.Reg0()) << TestString;                                  \
109     reset();                                                                   \
110   } while (0)
111 
112 #define TestImplSize(Reg0, Reg1, Size)                                         \
113   do {                                                                         \
114     TestImplRegReg(Reg0, 0xa2b34567, Reg1, 0x0507ddee, Size);                  \
115   } while (0)
116 
117 #define TestImpl(Reg0, Reg1)                                                   \
118   do {                                                                         \
119     if (GPRRegister::Encoded_Reg_##Reg0 < 4 &&                                 \
120         GPRRegister::Encoded_Reg_##Reg1 < 4) {                                 \
121       TestImplSize(Reg0, Reg1, 8);                                             \
122     }                                                                          \
123     TestImplSize(Reg0, Reg1, 16);                                              \
124     TestImplSize(Reg0, Reg1, 32);                                              \
125   } while (0)
126 
127   TestImpl(eax, ebx);
128   TestImpl(edx, eax);
129   TestImpl(ecx, edx);
130   TestImpl(esi, eax);
131   TestImpl(edx, edi);
132 
133 #undef TestImpl
134 #undef TestImplSize
135 #undef TestImplRegReg
136 }
137 
TEST_F(AssemblerX8632Test,Xadd)138 TEST_F(AssemblerX8632Test, Xadd) {
139   static constexpr bool NotLocked = false;
140   static constexpr bool Locked = true;
141 
142   static constexpr uint32_t Mask8 = 0x000000FF;
143   static constexpr uint32_t Mask16 = 0x0000FFFF;
144   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
145 
146 #define TestImplAddrReg(Value0, Dst1, Value1, LockedOrNot, Size)               \
147   do {                                                                         \
148     static constexpr char TestString[] =                                       \
149         "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")";                    \
150     const uint32_t T0 = allocateDword();                                       \
151     const uint32_t V0 = (Value0)&Mask##Size;                                   \
152     const uint32_t V1 = (Value1)&Mask##Size;                                   \
153                                                                                \
154     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1,                   \
155            Immediate(Value1));                                                 \
156     __ xadd(IceType_i##Size, dwordAddress(T0),                                 \
157             GPRRegister::Encoded_Reg_##Dst1, LockedOrNot);                     \
158     __ And(IceType_i32, GPRRegister::Encoded_Reg_##Dst1,                       \
159            Immediate(Mask##Size));                                             \
160                                                                                \
161     AssembledTest test = assemble();                                           \
162     test.setDwordTo(T0, V0);                                                   \
163     test.run();                                                                \
164                                                                                \
165     ASSERT_EQ(V0, test.Dst1()) << TestString;                                  \
166     ASSERT_EQ(Mask##Size &(V1 + V0), test.contentsOfDword(T0)) << TestString;  \
167     reset();                                                                   \
168   } while (0)
169 
170 #define TestImplSize(Dst1, Size)                                               \
171   do {                                                                         \
172     TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, NotLocked, Size);            \
173     TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Locked, Size);               \
174   } while (0)
175 
176 #define TestImpl(Dst1)                                                         \
177   do {                                                                         \
178     if (GPRRegister::Encoded_Reg_##Dst1 < 4) {                                 \
179       TestImplSize(Dst1, 8);                                                   \
180     }                                                                          \
181     TestImplSize(Dst1, 16);                                                    \
182     TestImplSize(Dst1, 32);                                                    \
183   } while (0)
184 
185   TestImpl(eax);
186   TestImpl(ebx);
187   TestImpl(ecx);
188   TestImpl(edx);
189   TestImpl(esi);
190   TestImpl(edi);
191 
192 #undef TestImpl
193 #undef TestImplSize
194 #undef TestImplAddrReg
195 }
196 
TEST_F(AssemblerX8632LowLevelTest,Xadd)197 TEST_F(AssemblerX8632LowLevelTest, Xadd) {
198   static constexpr bool NotLocked = false;
199   static constexpr bool Locked = true;
200 
201   // Ensures that xadd emits a lock prefix accordingly.
202   {
203     __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
204             GPRRegister::Encoded_Reg_esi, NotLocked);
205     static constexpr uint8_t ByteCountNotLocked8 = 7;
206     ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
207     verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x0F, 0xC0, 0x35, 0x00, 0xFF,
208                                      0x01, 0x00);
209     reset();
210 
211     __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
212             GPRRegister::Encoded_Reg_esi, Locked);
213     static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
214     ASSERT_EQ(ByteCountLocked8, codeBytesSize());
215     verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x0F, 0xC0, 0x35, 0x00,
216                                   0xFF, 0x01, 0x00);
217     reset();
218   }
219 
220   {
221     __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
222             GPRRegister::Encoded_Reg_esi, NotLocked);
223     static constexpr uint8_t ByteCountNotLocked16 = 8;
224     ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
225     verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x0F, 0xC1, 0x35, 0x00,
226                                       0xFF, 0x01, 0x00);
227     reset();
228 
229     __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
230             GPRRegister::Encoded_Reg_esi, Locked);
231     static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
232     ASSERT_EQ(ByteCountLocked16, codeBytesSize());
233     verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x0F, 0xC1, 0x35,
234                                    0x00, 0xFF, 0x01, 0x00);
235     reset();
236   }
237 
238   {
239     __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
240             GPRRegister::Encoded_Reg_esi, NotLocked);
241     static constexpr uint8_t ByteCountNotLocked32 = 7;
242     ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
243     verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x0F, 0xC1, 0x35, 0x00, 0xFF,
244                                       0x01, 0x00);
245     reset();
246 
247     __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
248             GPRRegister::Encoded_Reg_esi, Locked);
249     static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
250     ASSERT_EQ(ByteCountLocked32, codeBytesSize());
251     verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x0F, 0xC1, 0x35, 0x00,
252                                    0xFF, 0x01, 0x00);
253     reset();
254   }
255 }
256 
TEST_F(AssemblerX8632Test,Cmpxchg8b)257 TEST_F(AssemblerX8632Test, Cmpxchg8b) {
258   static constexpr bool NotLocked = false;
259   static constexpr bool Locked = true;
260 
261 #define TestImpl(Value0, Value1, ValueMem, LockedOrNot)                        \
262   do {                                                                         \
263     static constexpr char TestString[] =                                       \
264         "(" #Value0 ", " #Value1 ", " #ValueMem ", " #LockedOrNot ")";         \
265     const uint32_t T0 = allocateQword();                                       \
266     static constexpr uint64_t V0 = ValueMem;                                   \
267     const uint32_t ZeroFlag = allocateDword();                                 \
268                                                                                \
269     __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax,                          \
270            Immediate(uint64_t(Value0) & 0xFFFFFFFF));                          \
271     __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx,                          \
272            Immediate(uint64_t(Value0) >> 32));                                 \
273     __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx,                          \
274            Immediate(uint64_t(Value1) & 0xFFFFFFFF));                          \
275     __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx,                          \
276            Immediate(uint64_t(Value1) >> 32));                                 \
277     __ cmpxchg8b(dwordAddress(T0), LockedOrNot);                               \
278     __ setcc(Cond::Br_e, dwordAddress(ZeroFlag));                              \
279                                                                                \
280     AssembledTest test = assemble();                                           \
281     test.setQwordTo(T0, V0);                                                   \
282     test.setDwordTo(ZeroFlag, uint32_t(0xFF));                                 \
283     test.run();                                                                \
284                                                                                \
285     if (V0 == (Value0)) {                                                      \
286       ASSERT_EQ(uint64_t(Value1), test.contentsOfQword(T0)) << TestString;     \
287       ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString;             \
288     } else {                                                                   \
289       ASSERT_EQ(uint64_t(ValueMem) & 0xFFFFFFFF, test.eax()) << TestString;    \
290       ASSERT_EQ((uint64_t(ValueMem) >> 32) & 0xFFFFFFFF, test.edx())           \
291           << TestString;                                                       \
292       ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString;             \
293     }                                                                          \
294     reset();                                                                   \
295   } while (0)
296 
297   TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, NotLocked);
298   TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, Locked);
299   TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, NotLocked);
300   TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, Locked);
301 
302 #undef TestImpl
303 }
304 
TEST_F(AssemblerX8632LowLevelTest,Cmpxchg8b)305 TEST_F(AssemblerX8632LowLevelTest, Cmpxchg8b) {
306   static constexpr bool NotLocked = false;
307   static constexpr bool Locked = true;
308 
309   // Ensures that cmpxchg8b emits a lock prefix accordingly.
310   __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), NotLocked);
311   static constexpr uint8_t ByteCountNotLocked = 7;
312   ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
313   verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
314                                   0x01, 0x00);
315   reset();
316 
317   __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), Locked);
318   static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
319   ASSERT_EQ(ByteCountLocked, codeBytesSize());
320   verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
321                                0x01, 0x00);
322   reset();
323 }
324 
TEST_F(AssemblerX8632Test,Cmpxchg)325 TEST_F(AssemblerX8632Test, Cmpxchg) {
326   static constexpr bool NotLocked = false;
327   static constexpr bool Locked = true;
328 
329   static constexpr uint32_t Mask8 = 0x000000FF;
330   static constexpr uint32_t Mask16 = 0x0000FFFF;
331   static constexpr uint32_t Mask32 = 0xFFFFFFFF;
332 
333 #define TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, Size)      \
334   do {                                                                         \
335     static constexpr char TestString[] =                                       \
336         "(" #Value0 ", " #Src ", " #Value1 ", " #ValueMem ", " #LockedOrNot    \
337         ", " #Size ")";                                                        \
338     const uint32_t T0 = allocateDword();                                       \
339     static constexpr uint32_t V0 = (ValueMem)&Mask##Size;                      \
340     const uint32_t ZeroFlag = allocateDword();                                 \
341                                                                                \
342     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax,                      \
343            Immediate((Value0)&Mask##Size));                                    \
344     __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src,                    \
345            Immediate((Value1)&Mask##Size));                                    \
346     __ cmpxchg(IceType_i##Size, dwordAddress(T0),                              \
347                GPRRegister::Encoded_Reg_##Src, LockedOrNot);                   \
348     __ setcc(Cond::Br_e, dwordAddress(ZeroFlag));                              \
349                                                                                \
350     AssembledTest test = assemble();                                           \
351     test.setDwordTo(T0, V0);                                                   \
352     test.setDwordTo(ZeroFlag, uint32_t(0xFF));                                 \
353     test.run();                                                                \
354                                                                                \
355     if (V0 == (Mask##Size & (Value0))) {                                       \
356       ASSERT_EQ(uint32_t((Value1)&Mask##Size), test.contentsOfDword(T0))       \
357           << TestString;                                                       \
358       ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString;             \
359     } else {                                                                   \
360       ASSERT_EQ(uint32_t((ValueMem)&Mask##Size), test.eax()) << TestString;    \
361       ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString;             \
362     }                                                                          \
363     reset();                                                                   \
364   } while (0)
365 
366 #define TestImplValue(Value0, Src, Value1, ValueMem, LockedOrNot)              \
367   do {                                                                         \
368     if (GPRRegister::Encoded_Reg_##Src < 4) {                                  \
369       TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 8);          \
370     }                                                                          \
371     TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 16);           \
372     TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 32);           \
373   } while (0)
374 
375 #define TestImpl(Src, LockedOrNot)                                             \
376   do {                                                                         \
377     TestImplValue(0xFFFFFFFF, Src, 0x1, 0xFFFFFFFF, LockedOrNot);              \
378     TestImplValue(0x0FFF0F0F, Src, 0x1, 0xFFFFFFFF, LockedOrNot);              \
379   } while (0)
380 
381   TestImpl(ebx, Locked);
382   TestImpl(edx, NotLocked);
383   TestImpl(ecx, Locked);
384   TestImpl(ecx, NotLocked);
385   TestImpl(edx, Locked);
386   TestImpl(edx, NotLocked);
387   TestImpl(esi, Locked);
388   TestImpl(esi, NotLocked);
389   TestImpl(edi, Locked);
390   TestImpl(edi, NotLocked);
391 
392 #undef TestImpl
393 #undef TestImplValue
394 #undef TestImplAddrReg
395 }
396 
TEST_F(AssemblerX8632LowLevelTest,Cmpxchg)397 TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
398   static constexpr bool NotLocked = false;
399   static constexpr bool Locked = true;
400 
401   // Ensures that cmpxchg emits a lock prefix accordingly.
402   {
403     __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
404                GPRRegister::Encoded_Reg_esi, NotLocked);
405     static constexpr uint8_t ByteCountNotLocked8 = 7;
406     ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
407     verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x0F, 0xB0, 0x35, 0x00, 0xFF,
408                                      0x01, 0x00);
409     reset();
410 
411     __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
412                GPRRegister::Encoded_Reg_esi, Locked);
413     static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
414     ASSERT_EQ(ByteCountLocked8, codeBytesSize());
415     verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x0F, 0xB0, 0x35, 0x00,
416                                   0xFF, 0x01, 0x00);
417     reset();
418   }
419 
420   {
421     __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
422                GPRRegister::Encoded_Reg_esi, NotLocked);
423     static constexpr uint8_t ByteCountNotLocked16 = 8;
424     ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
425     verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x0F, 0xB1, 0x35, 0x00,
426                                       0xFF, 0x01, 0x00);
427     reset();
428 
429     __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
430                GPRRegister::Encoded_Reg_esi, Locked);
431     static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
432     ASSERT_EQ(ByteCountLocked16, codeBytesSize());
433     verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x0F, 0xB1, 0x35,
434                                    0x00, 0xFF, 0x01, 0x00);
435     reset();
436   }
437 
438   {
439     __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
440                GPRRegister::Encoded_Reg_esi, NotLocked);
441     static constexpr uint8_t ByteCountNotLocked32 = 7;
442     ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
443     verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x0F, 0xB1, 0x35, 0x00, 0xFF,
444                                       0x01, 0x00);
445     reset();
446 
447     __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
448                GPRRegister::Encoded_Reg_esi, Locked);
449     static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
450     ASSERT_EQ(ByteCountLocked32, codeBytesSize());
451     verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x0F, 0xB1, 0x35, 0x00,
452                                    0xFF, 0x01, 0x00);
453     reset();
454   }
455 }
456 
457 } // end of anonymous namespace
458 } // end of namespace Test
459 } // end of namespace X8632
460 } // end of namespace Ice
461