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