• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/unittest/AssemblerX8664/ControlFlow.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 "AssemblerX8664/TestUtil.h"
10 
11 namespace Ice {
12 namespace X8664 {
13 namespace Test {
14 namespace {
15 
TEST_F(AssemblerX8664Test,J)16 TEST_F(AssemblerX8664Test, J) {
17 #define TestJ(C, Near, Dest, Src0, Value0, Src1, Value1)                       \
18   do {                                                                         \
19     static constexpr char TestString[] =                                       \
20         "(" #C ", " #Near ", " #Dest ", " #Src0 ", " #Value0 ", " #Src1        \
21         ", " #Value1 ")";                                                      \
22     const bool NearJmp = AssemblerX8664::k##Near##Jump;                        \
23     Label ShouldBeTaken;                                                       \
24     __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0));              \
25     __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1));              \
26     __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xBEEF));              \
27     __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1());           \
28     __ j(Cond::Br_##C, &ShouldBeTaken, NearJmp);                               \
29     __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xC0FFEE));            \
30     __ bind(&ShouldBeTaken);                                                   \
31     AssembledTest test = assemble();                                           \
32     test.run();                                                                \
33     ASSERT_EQ(Value0, test.Src0()) << TestString;                              \
34     ASSERT_EQ(Value1, test.Src1()) << TestString;                              \
35     ASSERT_EQ(0xBEEFul, test.Dest()) << TestString;                            \
36     reset();                                                                   \
37   } while (0)
38 
39 #define TestImpl(Dst, Src0, Src1)                                              \
40   do {                                                                         \
41     TestJ(o, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
42     TestJ(o, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                       \
43     TestJ(no, Near, Dst, Src0, 0x1ul, Src1, 0x1ul);                            \
44     TestJ(no, Far, Dst, Src0, 0x1ul, Src1, 0x1ul);                             \
45     TestJ(b, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
46     TestJ(b, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                       \
47     TestJ(ae, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                     \
48     TestJ(ae, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
49     TestJ(e, Near, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul);               \
50     TestJ(e, Far, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul);                \
51     TestJ(ne, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                     \
52     TestJ(ne, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
53     TestJ(be, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                     \
54     TestJ(be, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
55     TestJ(a, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
56     TestJ(a, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                       \
57     TestJ(s, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
58     TestJ(s, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                       \
59     TestJ(ns, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                     \
60     TestJ(ns, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
61     TestJ(p, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
62     TestJ(p, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                       \
63     TestJ(np, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                     \
64     TestJ(np, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
65     TestJ(l, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
66     TestJ(l, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                       \
67     TestJ(ge, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                     \
68     TestJ(ge, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
69     TestJ(le, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                     \
70     TestJ(le, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul);                      \
71     TestJ(g, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                      \
72     TestJ(g, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul);                       \
73   } while (0)
74 
75   TestImpl(r1, r2, r3);
76   TestImpl(r2, r3, r4);
77   TestImpl(r3, r4, r5);
78   TestImpl(r4, r5, r6);
79   TestImpl(r5, r6, r7);
80   TestImpl(r6, r7, r8);
81   TestImpl(r7, r8, r10);
82   TestImpl(r8, r10, r11);
83   TestImpl(r10, r11, r12);
84   TestImpl(r11, r12, r13);
85   TestImpl(r12, r13, r14);
86   TestImpl(r13, r14, r15);
87   TestImpl(r14, r15, r1);
88   TestImpl(r15, r1, r2);
89 
90 #undef TestImpl
91 #undef TestJ
92 }
93 
TEST_F(AssemblerX8664Test,CallImm)94 TEST_F(AssemblerX8664Test, CallImm) {
95   __ call(Immediate(16));
96   __ hlt();
97   __ hlt();
98   __ hlt();
99   __ hlt();
100   __ hlt();
101   __ hlt();
102   __ hlt();
103   __ hlt();
104   __ hlt();
105   __ hlt();
106   __ hlt();
107   __ hlt();
108   __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf00f));
109   __ popl(GPRRegister::Encoded_Reg_ebx);
110 
111   AssembledTest test = assemble();
112 
113   test.run();
114 
115   EXPECT_EQ(0xF00Fu, test.eax());
116 }
117 
TEST_F(AssemblerX8664Test,CallReg)118 TEST_F(AssemblerX8664Test, CallReg) {
119 #define TestImpl(Dst, Src)                                                     \
120   do {                                                                         \
121     __ call(Immediate(16));                                                    \
122     int CallTargetAddr = codeBytesSize() + 12;                                 \
123     __ popl(Encoded_GPR_##Dst());                                              \
124     __ pushl(Encoded_GPR_##Dst());                                             \
125     __ ret();                                                                  \
126     for (int I = codeBytesSize(); I < CallTargetAddr; ++I) {                   \
127       __ hlt();                                                                \
128     }                                                                          \
129     __ popl(Encoded_GPR_##Src());                                              \
130     __ call(Encoded_GPR_##Src());                                              \
131                                                                                \
132     AssembledTest test = assemble();                                           \
133                                                                                \
134     test.run();                                                                \
135                                                                                \
136     ASSERT_LE(15u, test.Dst() - test.Src()) << "(" #Dst ", " #Src ")";         \
137     reset();                                                                   \
138   } while (0)
139 
140   TestImpl(r1, r2);
141   TestImpl(r2, r3);
142   TestImpl(r3, r4);
143   TestImpl(r4, r5);
144   TestImpl(r5, r6);
145   TestImpl(r6, r7);
146   TestImpl(r7, r8);
147   TestImpl(r8, r10);
148   TestImpl(r10, r11);
149   TestImpl(r11, r12);
150   TestImpl(r12, r13);
151   TestImpl(r13, r14);
152   TestImpl(r14, r15);
153   TestImpl(r15, r1);
154 
155 #undef TestImpl
156 }
157 
TEST_F(AssemblerX8664Test,CallAddr)158 TEST_F(AssemblerX8664Test, CallAddr) {
159 #define TestImpl(Dst, Src)                                                     \
160   do {                                                                         \
161     const uint32_t T0 = allocateQword();                                       \
162     const uint64_t V0 = 0xA0C0FFEEBEEFFEEFull;                                 \
163     const uint32_t T1 = allocateDword();                                       \
164     __ call(Immediate(16));                                                    \
165     int CallTargetAddr = codeBytesSize() + 12;                                 \
166     __ mov(IceType_i8, Encoded_GPR_##Dst##l(), Immediate(0xf4));               \
167     __ ret();                                                                  \
168     for (int I = codeBytesSize(); I < CallTargetAddr; ++I) {                   \
169       __ hlt();                                                                \
170     }                                                                          \
171     __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0));             \
172     __ popl(Encoded_GPR_##Src##q());                                           \
173     __ mov(IceType_i32, dwordAddress(T1), Encoded_GPR_##Src##d());             \
174     __ call(dwordAddress(T1));                                                 \
175                                                                                \
176     AssembledTest test = assemble();                                           \
177     test.setQwordTo(T0, V0);                                                   \
178     test.run();                                                                \
179                                                                                \
180     ASSERT_EQ(0xA0C0FFEEBEEFFEF4ull, test.Dst##q()) << "(" #Dst ", " #Src ")"; \
181     reset();                                                                   \
182   } while (0)
183 
184   TestImpl(r1, r2);
185   TestImpl(r2, r3);
186   TestImpl(r3, r4);
187   TestImpl(r4, r5);
188   TestImpl(r5, r6);
189   TestImpl(r6, r7);
190   TestImpl(r7, r8);
191   TestImpl(r8, r10);
192   TestImpl(r10, r11);
193   TestImpl(r11, r12);
194   TestImpl(r12, r13);
195   TestImpl(r13, r14);
196   TestImpl(r14, r15);
197   TestImpl(r15, r1);
198 
199 #undef TestImpl
200 }
201 
TEST_F(AssemblerX8664Test,Jmp)202 TEST_F(AssemblerX8664Test, Jmp) {
203 // TestImplReg uses jmp(Label), so jmp(Label) needs to be tested before it.
204 #define TestImplAddr(Near)                                                     \
205   do {                                                                         \
206     Label ForwardJmp;                                                          \
207     Label BackwardJmp;                                                         \
208     Label Done;                                                                \
209                                                                                \
210     __ jmp(&ForwardJmp, AssemblerX8664::k##Near##Jump);                        \
211     __ hlt();                                                                  \
212     __ hlt();                                                                  \
213     __ hlt();                                                                  \
214     __ hlt();                                                                  \
215     __ hlt();                                                                  \
216     __ hlt();                                                                  \
217     __ hlt();                                                                  \
218     __ hlt();                                                                  \
219     __ hlt();                                                                  \
220     __ hlt();                                                                  \
221     __ bind(&BackwardJmp);                                                     \
222     __ jmp(&Done, AssemblerX8664::k##Near##Jump);                              \
223     __ hlt();                                                                  \
224     __ hlt();                                                                  \
225     __ hlt();                                                                  \
226     __ hlt();                                                                  \
227     __ hlt();                                                                  \
228     __ hlt();                                                                  \
229     __ hlt();                                                                  \
230     __ hlt();                                                                  \
231     __ hlt();                                                                  \
232     __ hlt();                                                                  \
233     __ bind(&ForwardJmp);                                                      \
234     __ jmp(&BackwardJmp, AssemblerX8664::k##NearJump);                         \
235     __ hlt();                                                                  \
236     __ hlt();                                                                  \
237     __ hlt();                                                                  \
238     __ hlt();                                                                  \
239     __ hlt();                                                                  \
240     __ hlt();                                                                  \
241     __ hlt();                                                                  \
242     __ hlt();                                                                  \
243     __ hlt();                                                                  \
244     __ hlt();                                                                  \
245     __ bind(&Done);                                                            \
246   } while (0)
247 
248 #define TestImplReg(Dst)                                                       \
249   do {                                                                         \
250     __ call(Immediate(16));                                                    \
251     Label Done;                                                                \
252     __ jmp(&Done, AssemblerX8664::kNearJump);                                  \
253     __ hlt();                                                                  \
254     __ hlt();                                                                  \
255     __ hlt();                                                                  \
256     __ hlt();                                                                  \
257     __ hlt();                                                                  \
258     __ hlt();                                                                  \
259     __ hlt();                                                                  \
260     __ hlt();                                                                  \
261     __ hlt();                                                                  \
262     __ hlt();                                                                  \
263     __ popl(Encoded_GPR_##Dst());                                              \
264     __ jmp(Encoded_GPR_##Dst());                                               \
265     __ hlt();                                                                  \
266     __ hlt();                                                                  \
267     __ hlt();                                                                  \
268     __ hlt();                                                                  \
269     __ hlt();                                                                  \
270     __ hlt();                                                                  \
271     __ hlt();                                                                  \
272     __ hlt();                                                                  \
273     __ hlt();                                                                  \
274     __ hlt();                                                                  \
275     __ bind(&Done);                                                            \
276                                                                                \
277     AssembledTest test = assemble();                                           \
278     test.run();                                                                \
279                                                                                \
280     reset();                                                                   \
281   } while (0)
282 
283   TestImplAddr(Near);
284   TestImplAddr(Far);
285 
286   TestImplReg(r1);
287   TestImplReg(r2);
288   TestImplReg(r3);
289   TestImplReg(r4);
290   TestImplReg(r5);
291   TestImplReg(r6);
292   TestImplReg(r7);
293   TestImplReg(r8);
294   TestImplReg(r10);
295   TestImplReg(r11);
296   TestImplReg(r12);
297   TestImplReg(r13);
298   TestImplReg(r14);
299   TestImplReg(r15);
300 
301 #undef TestImplReg
302 #undef TestImplAddr
303 }
304 
305 } // end of anonymous namespace
306 } // end of namespace Test
307 } // end of namespace X8664
308 } // end of namespace Ice
309