1 //===- subzero/unittest/AssemblerX8664/GPRArith.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,PopAddr)16 TEST_F(AssemblerX8664Test, PopAddr) {
17 const uint32_t T0 = allocateQword();
18 constexpr uint64_t V0 = 0x3AABBEFABBBAA3ull;
19
20 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xC0FFEE));
21 __ pushl(GPRRegister::Encoded_Reg_eax);
22 __ popl(dwordAddress(T0));
23
24 AssembledTest test = assemble();
25 test.setQwordTo(T0, V0);
26
27 test.run();
28
29 ASSERT_EQ(0xC0FFEEul, test.contentsOfQword(T0));
30 }
31
TEST_F(AssemblerX8664Test,SetCC)32 TEST_F(AssemblerX8664Test, SetCC) {
33 #define TestSetCC(C, Dest, IsTrue, Src0, Value0, Src1, Value1) \
34 do { \
35 static constexpr char TestString[] = \
36 "(" #C ", " #Dest ", " #IsTrue ", " #Src0 ", " #Value0 ", " #Src1 \
37 ", " #Value1 ")"; \
38 const uint32_t T0 = allocateDword(); \
39 constexpr uint32_t V0 = 0xF00F00; \
40 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \
41 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \
42 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \
43 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0)); \
44 __ setcc(Cond::Br_##C, Encoded_Bytereg_##Dest()); \
45 __ setcc(Cond::Br_##C, dwordAddress(T0)); \
46 \
47 AssembledTest test = assemble(); \
48 test.setDwordTo(T0, V0); \
49 \
50 test.run(); \
51 \
52 ASSERT_EQ(IsTrue, test.Dest()) << TestString; \
53 ASSERT_EQ((0xF00F00 | IsTrue), test.contentsOfDword(T0)) << TestString; \
54 reset(); \
55 } while (0)
56
57 #define TestImpl(Dest, Src0, Src1) \
58 do { \
59 TestSetCC(o, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
60 TestSetCC(o, Dest, 0u, Src0, 0x1u, Src1, 0x10000000u); \
61 TestSetCC(no, Dest, 1u, Src0, 0x1u, Src1, 0x10000000u); \
62 TestSetCC(no, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
63 TestSetCC(b, Dest, 1u, Src0, 0x1, Src1, 0x80000000u); \
64 TestSetCC(b, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
65 TestSetCC(ae, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
66 TestSetCC(ae, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
67 TestSetCC(e, Dest, 1u, Src0, 0x1u, Src1, 0x1u); \
68 TestSetCC(e, Dest, 0u, Src0, 0x1u, Src1, 0x11111u); \
69 TestSetCC(ne, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
70 TestSetCC(ne, Dest, 0u, Src0, 0x1u, Src1, 0x1u); \
71 TestSetCC(be, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
72 TestSetCC(be, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
73 TestSetCC(a, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
74 TestSetCC(a, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
75 TestSetCC(s, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
76 TestSetCC(s, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
77 TestSetCC(ns, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
78 TestSetCC(ns, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
79 TestSetCC(p, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
80 TestSetCC(p, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
81 TestSetCC(np, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
82 TestSetCC(np, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
83 TestSetCC(l, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
84 TestSetCC(l, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
85 TestSetCC(ge, Dest, 1u, Src0, 0x1u, Src1, 0x80000000u); \
86 TestSetCC(ge, Dest, 0u, Src0, 0x80000000u, Src1, 0x1u); \
87 TestSetCC(le, Dest, 1u, Src0, 0x80000000u, Src1, 0x1u); \
88 TestSetCC(le, Dest, 0u, Src0, 0x1u, Src1, 0x80000000u); \
89 } while (0)
90
91 TestImpl(r1, r2, r3);
92 TestImpl(r2, r3, r4);
93 TestImpl(r3, r4, r5);
94 TestImpl(r4, r5, r6);
95 TestImpl(r4, r6, r7);
96 TestImpl(r5, r6, r7);
97 TestImpl(r6, r7, r8);
98 TestImpl(r7, r8, r10);
99 TestImpl(r8, r10, r11);
100 TestImpl(r10, r11, r12);
101 TestImpl(r11, r12, r13);
102 TestImpl(r12, r13, r14);
103 TestImpl(r13, r14, r15);
104 TestImpl(r14, r15, r1);
105 TestImpl(r15, r1, r2);
106
107 #undef TestImpl
108 #undef TestSetCC
109 }
110
TEST_F(AssemblerX8664Test,Lea)111 TEST_F(AssemblerX8664Test, Lea) {
112 #define TestLeaBaseDisp(Base, BaseValue, Disp, Dst) \
113 do { \
114 static constexpr char TestString[] = \
115 "(" #Base ", " #BaseValue ", " #Dst ")"; \
116 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
117 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
118 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
119 } \
120 __ lea(IceType_i32, Encoded_GPR_##Dst(), \
121 Address(Encoded_GPR_##Base(), Disp, AssemblerFixup::NoFixup)); \
122 AssembledTest test = assemble(); \
123 test.run(); \
124 ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d()) \
125 << TestString << " with Disp " << Disp; \
126 reset(); \
127 } while (0)
128
129 #define TestLeaIndex32bitDisp(Index, IndexValue, Disp, Dst0, Dst1, Dst2, Dst3) \
130 do { \
131 static constexpr char TestString[] = \
132 "(" #Index ", " #IndexValue ", " #Dst0 ", " #Dst1 ", " #Dst2 \
133 ", " #Dst3 ")"; \
134 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
135 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
136 } \
137 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
138 Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp, \
139 AssemblerFixup::NoFixup)); \
140 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
141 Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp, \
142 AssemblerFixup::NoFixup)); \
143 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
144 Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp, \
145 AssemblerFixup::NoFixup)); \
146 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
147 Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp, \
148 AssemblerFixup::NoFixup)); \
149 AssembledTest test = assemble(); \
150 test.run(); \
151 ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d()) \
152 << TestString << " " << Disp; \
153 ASSERT_EQ((test.Index##d() << Traits::TIMES_2) + (Disp), test.Dst1##d()) \
154 << TestString << " " << Disp; \
155 ASSERT_EQ((test.Index##d() << Traits::TIMES_4) + (Disp), test.Dst2##d()) \
156 << TestString << " " << Disp; \
157 ASSERT_EQ((test.Index##d() << Traits::TIMES_8) + (Disp), test.Dst3##d()) \
158 << TestString << " " << Disp; \
159 reset(); \
160 } while (0)
161
162 #define TestLeaBaseIndexDisp(Base, BaseValue, Index, IndexValue, Disp, Dst0, \
163 Dst1, Dst2, Dst3) \
164 do { \
165 static constexpr char TestString[] = \
166 "(" #Base ", " #BaseValue ", " #Index ", " #IndexValue ", " #Dst0 \
167 ", " #Dst1 ", " #Dst2 ", " #Dst3 ")"; \
168 if (Encoded_GPR_##Base() != Encoded_GPR_esp() && \
169 Encoded_GPR_##Base() != Encoded_GPR_r9()) { \
170 __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
171 } \
172 \
173 if (Encoded_GPR_##Index() != Encoded_GPR_r9()) { \
174 __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
175 } \
176 \
177 __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
178 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
179 Traits::TIMES_1, Disp, AssemblerFixup::NoFixup)); \
180 __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
181 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
182 Traits::TIMES_2, Disp, AssemblerFixup::NoFixup)); \
183 __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
184 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
185 Traits::TIMES_4, Disp, AssemblerFixup::NoFixup)); \
186 __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
187 Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
188 Traits::TIMES_8, Disp, AssemblerFixup::NoFixup)); \
189 AssembledTest test = assemble(); \
190 test.run(); \
191 uint32_t ExpectedIndexValue = test.Index(); \
192 if (Encoded_GPR_##Index() == Encoded_GPR_esp()) { \
193 ExpectedIndexValue = 0; \
194 } \
195 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_1) + \
196 (Disp), \
197 test.Dst0##d()) \
198 << TestString << " " << Disp; \
199 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_2) + \
200 (Disp), \
201 test.Dst1##d()) \
202 << TestString << " " << Disp; \
203 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_4) + \
204 (Disp), \
205 test.Dst2##d()) \
206 << TestString << " " << Disp; \
207 ASSERT_EQ(test.Base##d() + (ExpectedIndexValue << Traits::TIMES_8) + \
208 (Disp), \
209 test.Dst3##d()) \
210 << TestString << " " << Disp; \
211 reset(); \
212 } while (0)
213
214 for (const int32_t Disp :
215 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
216 TestLeaBaseDisp(r0, 0x22080Fu, Disp, r1);
217 TestLeaBaseDisp(r1, 0x10000Fu, Disp, r2);
218 TestLeaBaseDisp(r2, 0x20000Fu, Disp, r3);
219 TestLeaBaseDisp(r3, 0x30000Fu, Disp, r4);
220 TestLeaBaseDisp(r4, 0x40000Fu, Disp, r5);
221 TestLeaBaseDisp(r5, 0x50000Fu, Disp, r6);
222 TestLeaBaseDisp(r6, 0x60000Fu, Disp, r7);
223 TestLeaBaseDisp(r7, 0x11000Fu, Disp, r8);
224 TestLeaBaseDisp(r8, 0x11200Fu, Disp, r10);
225 TestLeaBaseDisp(r9, 0x220400u, Disp, r10);
226 TestLeaBaseDisp(r10, 0x22000Fu, Disp, r11);
227 TestLeaBaseDisp(r11, 0x22030Fu, Disp, r12);
228 TestLeaBaseDisp(r12, 0x22040Fu, Disp, r13);
229 TestLeaBaseDisp(r13, 0x22050Fu, Disp, r14);
230 TestLeaBaseDisp(r14, 0x22060Fu, Disp, r15);
231 TestLeaBaseDisp(r15, 0x22070Fu, Disp, r1);
232 }
233
234 // esp is not a valid index register.
235 // ebp is not valid in this addressing mode (rm = 0).
236 for (const int32_t Disp :
237 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
238 TestLeaIndex32bitDisp(r1, 0x2000u, Disp, r2, r3, r4, r6);
239 TestLeaIndex32bitDisp(r2, 0x4010u, Disp, r3, r4, r6, r7);
240 TestLeaIndex32bitDisp(r3, 0x6020u, Disp, r4, r6, r7, r5);
241 TestLeaIndex32bitDisp(r4, 0x8030u, Disp, r6, r7, r5, r10);
242 TestLeaIndex32bitDisp(r6, 0xA040u, Disp, r7, r5, r10, r1);
243 TestLeaIndex32bitDisp(r7, 0xC050u, Disp, r5, r10, r1, r11);
244 TestLeaIndex32bitDisp(r8, 0xC060u, Disp, r10, r1, r11, r12);
245 TestLeaIndex32bitDisp(r9, 0xC100u, Disp, r1, r11, r12, r13);
246 TestLeaIndex32bitDisp(r10, 0xC008u, Disp, r11, r12, r13, r14);
247 TestLeaIndex32bitDisp(r11, 0xC009u, Disp, r12, r13, r14, r15);
248 TestLeaIndex32bitDisp(r12, 0xC00Au, Disp, r13, r14, r15, r1);
249 TestLeaIndex32bitDisp(r13, 0xC00Bu, Disp, r14, r15, r1, r2);
250 TestLeaIndex32bitDisp(r14, 0xC00Cu, Disp, r15, r1, r2, r3);
251 TestLeaIndex32bitDisp(r15, 0xC00Du, Disp, r1, r2, r3, r4);
252 }
253
254 for (const int32_t Disp :
255 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) {
256 TestLeaBaseIndexDisp(r1, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
257 TestLeaBaseIndexDisp(r2, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
258 TestLeaBaseIndexDisp(r3, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r5);
259 TestLeaBaseIndexDisp(r4, 0x400000u, r6, 0x300u, Disp, r7, r8, r5, r10);
260 TestLeaBaseIndexDisp(r6, 0x500000u, r7, 0x200u, Disp, r8, r5, r10, r11);
261 TestLeaBaseIndexDisp(r7, 0x600000u, r8, 0x100u, Disp, r5, r10, r11, r12);
262 TestLeaBaseIndexDisp(r8, 0x600000u, r9, 0x1A0u, Disp, r10, r11, r12, r13);
263 TestLeaBaseIndexDisp(r9, 0x600050u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
264 TestLeaBaseIndexDisp(r10, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
265 TestLeaBaseIndexDisp(r11, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
266 TestLeaBaseIndexDisp(r12, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
267 TestLeaBaseIndexDisp(r13, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
268 TestLeaBaseIndexDisp(r14, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
269 TestLeaBaseIndexDisp(r15, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
270
271 TestLeaBaseIndexDisp(r0, 0, r2, 0x600u, Disp, r3, r4, r6, r7);
272 TestLeaBaseIndexDisp(r0, 0, r3, 0x500u, Disp, r4, r6, r7, r8);
273 TestLeaBaseIndexDisp(r0, 0, r4, 0x400u, Disp, r6, r7, r8, r5);
274 TestLeaBaseIndexDisp(r0, 0, r6, 0x300u, Disp, r7, r8, r5, r10);
275 TestLeaBaseIndexDisp(r0, 0, r7, 0x200u, Disp, r8, r5, r10, r11);
276 TestLeaBaseIndexDisp(r0, 0, r8, 0x100u, Disp, r5, r10, r11, r12);
277 TestLeaBaseIndexDisp(r0, 0, r9, 0x1000u, Disp, r10, r11, r12, r13);
278 TestLeaBaseIndexDisp(r0, 0, r10, 0x1B0u, Disp, r11, r12, r13, r14);
279 TestLeaBaseIndexDisp(r0, 0, r11, 0x1C0u, Disp, r12, r13, r14, r15);
280 TestLeaBaseIndexDisp(r0, 0, r12, 0x1D0u, Disp, r13, r14, r15, r1);
281 TestLeaBaseIndexDisp(r0, 0, r13, 0x1E0u, Disp, r14, r15, r1, r2);
282 TestLeaBaseIndexDisp(r0, 0, r14, 0x1F0u, Disp, r15, r1, r2, r3);
283 TestLeaBaseIndexDisp(r0, 0, r15, 0x10Au, Disp, r1, r2, r3, r4);
284 TestLeaBaseIndexDisp(r0, 0, r1, 0x10Bu, Disp, r2, r3, r4, r6);
285
286 TestLeaBaseIndexDisp(r5, 0x100000u, r2, 0x600u, Disp, r3, r4, r6, r7);
287 TestLeaBaseIndexDisp(r5, 0x200000u, r3, 0x500u, Disp, r4, r6, r7, r8);
288 TestLeaBaseIndexDisp(r5, 0x300000u, r4, 0x400u, Disp, r6, r7, r8, r1);
289 TestLeaBaseIndexDisp(r5, 0x400000u, r6, 0x300u, Disp, r7, r8, r1, r10);
290 TestLeaBaseIndexDisp(r5, 0x500000u, r7, 0x200u, Disp, r8, r1, r10, r11);
291 TestLeaBaseIndexDisp(r5, 0x600000u, r8, 0x100u, Disp, r1, r10, r11, r12);
292 TestLeaBaseIndexDisp(r5, 0x600000u, r9, 0x1A00u, Disp, r10, r11, r12, r13);
293 TestLeaBaseIndexDisp(r5, 0x601000u, r10, 0x1B0u, Disp, r11, r12, r13, r14);
294 TestLeaBaseIndexDisp(r5, 0x602000u, r11, 0x1C0u, Disp, r12, r13, r14, r15);
295 TestLeaBaseIndexDisp(r5, 0x603000u, r12, 0x1D0u, Disp, r13, r14, r15, r1);
296 TestLeaBaseIndexDisp(r5, 0x604000u, r13, 0x1E0u, Disp, r14, r15, r1, r2);
297 TestLeaBaseIndexDisp(r5, 0x605000u, r14, 0x1F0u, Disp, r15, r1, r2, r3);
298 TestLeaBaseIndexDisp(r5, 0x606000u, r15, 0x10Au, Disp, r1, r2, r3, r4);
299 TestLeaBaseIndexDisp(r5, 0x607000u, r1, 0x10Bu, Disp, r2, r3, r4, r6);
300
301 TestLeaBaseIndexDisp(r2, 0x100000u, r5, 0x600u, Disp, r3, r4, r6, r7);
302 TestLeaBaseIndexDisp(r3, 0x200000u, r5, 0x500u, Disp, r4, r6, r7, r8);
303 TestLeaBaseIndexDisp(r4, 0x300000u, r5, 0x400u, Disp, r6, r7, r8, r1);
304 TestLeaBaseIndexDisp(r6, 0x400000u, r5, 0x300u, Disp, r7, r8, r1, r10);
305 TestLeaBaseIndexDisp(r7, 0x500000u, r5, 0x200u, Disp, r8, r1, r10, r11);
306 TestLeaBaseIndexDisp(r8, 0x600000u, r5, 0x100u, Disp, r1, r10, r11, r12);
307 TestLeaBaseIndexDisp(r9, 0x660000u, r5, 0x1A0u, Disp, r10, r11, r12, r13);
308 TestLeaBaseIndexDisp(r10, 0x601000u, r5, 0x1B0u, Disp, r11, r12, r13, r14);
309 TestLeaBaseIndexDisp(r11, 0x602000u, r5, 0x1C0u, Disp, r12, r13, r14, r15);
310 TestLeaBaseIndexDisp(r12, 0x603000u, r5, 0x1D0u, Disp, r13, r14, r15, r1);
311 TestLeaBaseIndexDisp(r13, 0x604000u, r5, 0x1E0u, Disp, r14, r15, r1, r2);
312 TestLeaBaseIndexDisp(r14, 0x605000u, r5, 0x1F0u, Disp, r15, r1, r2, r3);
313 TestLeaBaseIndexDisp(r15, 0x606000u, r5, 0x10Au, Disp, r1, r2, r3, r4);
314 TestLeaBaseIndexDisp(r1, 0x607000u, r5, 0x10Bu, Disp, r2, r3, r4, r6);
315
316 TestLeaBaseIndexDisp(r0, 0, r5, 0xC0BEBEEF, Disp, r2, r3, r4, r6);
317 }
318
319 // Absolute addressing mode is tested in the Low Level tests. The encoding used
320 // by the assembler has different meanings in x86-32 and x86-64.
321 #undef TestLeaBaseIndexDisp
322 #undef TestLeaScaled32bitDisp
323 #undef TestLeaBaseDisp
324 }
325
TEST_F(AssemblerX8664LowLevelTest,LeaAbsolute)326 TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
327 #define TestLeaAbsolute(Dst, Value) \
328 do { \
329 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
330 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
331 Address::Absolute(Value)); \
332 static constexpr uint32_t ByteCount = 8; \
333 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
334 static constexpr uint8_t Opcode = 0x8D; \
335 static constexpr uint8_t ModRM = \
336 /*mod*/ 0x00 | /*reg*/ (GPRRegister::Encoded_Reg_##Dst << 3) | \
337 /*rm*/ GPRRegister::Encoded_Reg_esp; \
338 static constexpr uint8_t SIB = \
339 /*Scale*/ 0x00 | /*Index*/ (GPRRegister::Encoded_Reg_esp << 3) | \
340 /*base*/ GPRRegister::Encoded_Reg_ebp; \
341 ASSERT_TRUE(verifyBytes<ByteCount>( \
342 codeBytes(), 0x67, Opcode, ModRM, SIB, (Value)&0xFF, \
343 (Value >> 8) & 0xFF, (Value >> 16) & 0xFF, (Value >> 24) & 0xFF)); \
344 reset(); \
345 } while (0)
346
347 TestLeaAbsolute(eax, 0x11BEEF22);
348 TestLeaAbsolute(ebx, 0x33BEEF44);
349 TestLeaAbsolute(ecx, 0x55BEEF66);
350 TestLeaAbsolute(edx, 0x77BEEF88);
351 TestLeaAbsolute(esi, 0x99BEEFAA);
352 TestLeaAbsolute(edi, 0xBBBEEFBB);
353
354 #undef TesLeaAbsolute
355 }
356
TEST_F(AssemblerX8664Test,Test)357 TEST_F(AssemblerX8664Test, Test) {
358 static constexpr uint32_t Mask8 = 0xFF;
359 static constexpr uint32_t Mask16 = 0xFFFF;
360 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
361
362 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
363 do { \
364 static constexpr bool NearJump = true; \
365 static constexpr char TestString[] = \
366 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
367 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
368 static constexpr uint32_t ValueIfFalse = 0x11111111; \
369 \
370 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
371 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
372 __ test(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
373 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
374 Label Done; \
375 __ j(Cond::Br_e, &Done, NearJump); \
376 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
377 __ bind(&Done); \
378 \
379 AssembledTest test = assemble(); \
380 test.run(); \
381 \
382 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
383 : ValueIfFalse, \
384 test.Dst()) \
385 << TestString; \
386 reset(); \
387 } while (0)
388
389 #define TestImplRegImm(Dst, Value0, Imm, Size) \
390 do { \
391 static constexpr bool NearJump = true; \
392 static constexpr char TestString[] = \
393 "(" #Dst ", " #Value0 ", " #Imm ", " #Size ")"; \
394 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
395 static constexpr uint32_t ValueIfFalse = 0x11111111; \
396 \
397 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
398 __ test(IceType_i##Size, Encoded_GPR_##Dst(), \
399 Immediate((Imm)&Mask##Size)); \
400 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfFalse)); \
401 Label Done; \
402 __ j(Cond::Br_e, &Done, NearJump); \
403 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(ValueIfTrue)); \
404 __ bind(&Done); \
405 \
406 AssembledTest test = assemble(); \
407 test.run(); \
408 \
409 ASSERT_EQ(((Value0)&Mask##Size) & ((Imm)&Mask##Size) ? ValueIfTrue \
410 : ValueIfFalse, \
411 test.Dst()) \
412 << TestString; \
413 reset(); \
414 } while (0)
415
416 #define TestImplAddrReg(Value0, Src, Value1, Size) \
417 do { \
418 static constexpr bool NearJump = true; \
419 static constexpr char TestString[] = \
420 "(Addr, " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
421 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
422 static constexpr uint32_t ValueIfFalse = 0x11111111; \
423 const uint32_t T0 = allocateDword(); \
424 \
425 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
426 __ test(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
427 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
428 Label Done; \
429 __ j(Cond::Br_e, &Done, NearJump); \
430 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
431 __ bind(&Done); \
432 \
433 AssembledTest test = assemble(); \
434 test.setDwordTo(T0, uint32_t(Value0)); \
435 test.run(); \
436 \
437 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
438 : ValueIfFalse, \
439 test.contentsOfDword(T0)) \
440 << TestString; \
441 reset(); \
442 } while (0)
443
444 #define TestImplAddrImm(Value0, Value1, Size) \
445 do { \
446 static constexpr bool NearJump = true; \
447 static constexpr char TestString[] = \
448 "(Addr, " #Value0 ", " #Value1 ", " #Size ")"; \
449 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \
450 static constexpr uint32_t ValueIfFalse = 0x11111111; \
451 const uint32_t T0 = allocateDword(); \
452 \
453 __ test(IceType_i##Size, dwordAddress(T0), \
454 Immediate((Value1)&Mask##Size)); \
455 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \
456 Label Done; \
457 __ j(Cond::Br_e, &Done, NearJump); \
458 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \
459 __ bind(&Done); \
460 \
461 AssembledTest test = assemble(); \
462 test.setDwordTo(T0, uint32_t(Value0)); \
463 test.run(); \
464 \
465 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \
466 : ValueIfFalse, \
467 test.contentsOfDword(T0)) \
468 << TestString; \
469 reset(); \
470 } while (0)
471
472 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
473 do { \
474 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
475 TestImplRegImm(Dst, Value0, Value1, Size); \
476 TestImplAddrReg(Value0, Src, Value1, Size); \
477 TestImplAddrImm(Value0, Value1, Size); \
478 } while (0)
479
480 #define TestImplSize(Dst, Src, Size) \
481 do { \
482 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
483 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
484 TestImplValues(Dst, 0x0F00000F, Src, 0xF00000F0, Size); \
485 } while (0)
486
487 #define TestImpl(Dst, Src) \
488 do { \
489 TestImplSize(Dst, Src, 8); \
490 TestImplSize(Dst, Src, 16); \
491 TestImplSize(Dst, Src, 32); \
492 } while (0)
493
494 TestImpl(r1, r2);
495 TestImpl(r2, r3);
496 TestImpl(r3, r4);
497 TestImpl(r4, r5);
498 TestImpl(r5, r6);
499 TestImpl(r6, r7);
500 TestImpl(r7, r8);
501 TestImpl(r8, r10);
502 TestImpl(r10, r11);
503 TestImpl(r11, r12);
504 TestImpl(r12, r13);
505 TestImpl(r13, r14);
506 TestImpl(r14, r15);
507 TestImpl(r15, r1);
508
509 #undef TestImpl
510 #undef TestImplSize
511 #undef TestImplValues
512 #undef TestImplAddrImm
513 #undef TestImplAddrReg
514 #undef TestImplRegImm
515 #undef TestImplRegReg
516 }
517
518 // No mull/div because x86.
519 // No shift because x86.
TEST_F(AssemblerX8664Test,Arith_most)520 TEST_F(AssemblerX8664Test, Arith_most) {
521 static constexpr uint32_t Mask8 = 0xFF;
522 static constexpr uint32_t Mask16 = 0xFFFF;
523 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
524
525 #define TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
526 do { \
527 static constexpr char TestString[] = \
528 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
529 ", " #Type #Size "_t, " #Op ")"; \
530 \
531 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
532 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
533 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
534 \
535 AssembledTest test = assemble(); \
536 test.run(); \
537 \
538 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
539 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
540 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
541 Mask##Size &test.Dst()) \
542 << TestString; \
543 reset(); \
544 } while (0)
545
546 #define TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op) \
547 do { \
548 static constexpr char TestString[] = \
549 "(" #Inst ", " #Dst ", " #Value0 ", Addr, " #Value1 ", " #Type #Size \
550 "_t, " #Op ")"; \
551 const uint32_t T0 = allocateDword(); \
552 const uint32_t V0 = Value1; \
553 \
554 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
555 __ mov(IceType_i##Size, dwordAddress(T0), Immediate(Value1)); \
556 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
557 \
558 AssembledTest test = assemble(); \
559 test.setDwordTo(T0, V0); \
560 test.run(); \
561 \
562 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
563 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
564 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
565 Mask##Size &test.Dst()) \
566 << TestString; \
567 reset(); \
568 } while (0)
569
570 #define TestImplRegImm(Inst, Dst, Value0, Imm, Type, Size, Op) \
571 do { \
572 static constexpr char TestString[] = \
573 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Type #Size \
574 "_t, " #Op ")"; \
575 \
576 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Value0)); \
577 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
578 Immediate((Imm)&Mask##Size)); \
579 \
580 AssembledTest test = assemble(); \
581 test.run(); \
582 \
583 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
584 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
585 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
586 Mask##Size &test.Dst()) \
587 << TestString; \
588 reset(); \
589 } while (0)
590
591 #define TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op) \
592 do { \
593 static constexpr char TestString[] = \
594 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Type #Size \
595 "_t, " #Op ")"; \
596 const uint32_t T0 = allocateDword(); \
597 const uint32_t V0 = Value0; \
598 \
599 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
600 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
601 \
602 AssembledTest test = assemble(); \
603 test.setDwordTo(T0, V0); \
604 test.run(); \
605 \
606 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
607 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
608 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \
609 Mask##Size &test.contentsOfDword(T0)) \
610 << TestString; \
611 reset(); \
612 } while (0)
613
614 #define TestImplAddrImm(Inst, Value0, Imm, Type, Size, Op) \
615 do { \
616 static constexpr char TestString[] = \
617 "(" #Inst ", Addr, " #Value0 ", Imm, " #Imm ", " #Type #Size \
618 "_t, " #Op ")"; \
619 const uint32_t T0 = allocateDword(); \
620 const uint32_t V0 = Value0; \
621 \
622 __ Inst(IceType_i##Size, dwordAddress(T0), Immediate((Imm)&Mask##Size)); \
623 \
624 AssembledTest test = assemble(); \
625 test.setDwordTo(T0, V0); \
626 test.run(); \
627 \
628 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \
629 static_cast<Type##Size##_t>((Value0)&Mask##Size) \
630 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \
631 Mask##Size &test.contentsOfDword(T0)) \
632 << TestString; \
633 reset(); \
634 } while (0)
635
636 #define TestImplOp(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \
637 do { \
638 TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op); \
639 TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op); \
640 TestImplRegImm(Inst, Dst, Value0, Value1, Type, Size, Op); \
641 TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op); \
642 TestImplAddrImm(Inst, Value0, Value1, Type, Size, Op); \
643 } while (0)
644
645 #define TestImplValues(Dst, Value0, Src, Value1, Size) \
646 do { \
647 TestImplOp(And, Dst, Value0, Src, Value1, int, Size, &); \
648 TestImplOp(And, Dst, Value0, Src, Value1, uint, Size, &); \
649 TestImplOp(Or, Dst, Value0, Src, Value1, int, Size, | ); \
650 TestImplOp(Or, Dst, Value0, Src, Value1, uint, Size, | ); \
651 TestImplOp(Xor, Dst, Value0, Src, Value1, int, Size, ^); \
652 TestImplOp(Xor, Dst, Value0, Src, Value1, uint, Size, ^); \
653 TestImplOp(add, Dst, Value0, Src, Value1, int, Size, +); \
654 TestImplOp(add, Dst, Value0, Src, Value1, uint, Size, +); \
655 TestImplOp(sub, Dst, Value0, Src, Value1, int, Size, -); \
656 TestImplOp(sub, Dst, Value0, Src, Value1, uint, Size, -); \
657 } while (0)
658
659 #define TestImplSize(Dst, Src, Size) \
660 do { \
661 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \
662 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \
663 TestImplValues(Dst, 0x0F00000F, Src, 0xF0000070, Size); \
664 TestImplValues(Dst, 0x0F00F00F, Src, 0xF000F070, Size); \
665 } while (0)
666
667 #define TestImpl(Dst, Src) \
668 do { \
669 TestImplSize(Dst, Src, 8); \
670 TestImplSize(Dst, Src, 16); \
671 TestImplSize(Dst, Src, 32); \
672 } while (0)
673
674 TestImpl(r1, r2);
675 TestImpl(r2, r3);
676 TestImpl(r3, r4);
677 TestImpl(r4, r5);
678 TestImpl(r5, r6);
679 TestImpl(r6, r7);
680 TestImpl(r7, r8);
681 TestImpl(r8, r10);
682 TestImpl(r10, r11);
683 TestImpl(r11, r12);
684 TestImpl(r12, r13);
685 TestImpl(r13, r14);
686 TestImpl(r14, r15);
687 TestImpl(r15, r1);
688
689 #undef TestImpl
690 #undef TestImplSize
691 #undef TestImplValues
692 #undef TestImplOp
693 #undef TestImplAddrImm
694 #undef TestImplAddrReg
695 #undef TestImplRegImm
696 #undef TestImplRegAddr
697 #undef TestImplRegReg
698 }
699
TEST_F(AssemblerX8664Test,Arith_BorrowNCarry)700 TEST_F(AssemblerX8664Test, Arith_BorrowNCarry) {
701 const uint32_t Mask8 = 0x000000FF;
702 const uint32_t Mask16 = 0x0000FFFF;
703 const uint32_t Mask32 = 0xFFFFFFFF;
704
705 const uint64_t ResultMask8 = 0x000000000000FFFFull;
706 const uint64_t ResultMask16 = 0x00000000FFFFFFFFull;
707 const uint64_t ResultMask32 = 0xFFFFFFFFFFFFFFFFull;
708
709 #define TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, \
710 Op, Size) \
711 do { \
712 static_assert(Size == 8 || Size == 16 || Size == 32, \
713 "Invalid size " #Size); \
714 static constexpr char TestString[] = \
715 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 ", " #Src0 \
716 ", " #Src1 ", " #Value1 ", " #Op ", " #Size ")"; \
717 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
718 Immediate(uint64_t(Value0) & Mask##Size)); \
719 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
720 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
721 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
722 Immediate(uint64_t(Value1) & Mask##Size)); \
723 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
724 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
725 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), Encoded_GPR_##Src0()); \
726 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), Encoded_GPR_##Src1()); \
727 \
728 AssembledTest test = assemble(); \
729 test.run(); \
730 \
731 static constexpr uint64_t Result = \
732 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
733 ResultMask##Size); \
734 static constexpr uint32_t Expected0 = Result & Mask##Size; \
735 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
736 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
737 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
738 reset(); \
739 } while (0)
740
741 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size) \
742 do { \
743 static_assert(Size == 8 || Size == 16 || Size == 32, \
744 "Invalid size " #Size); \
745 static constexpr char TestString[] = \
746 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
747 ", Addr, " #Value1 ", " #Op ", " #Size ")"; \
748 const uint32_t T0 = allocateDword(); \
749 const uint32_t V0 = uint64_t(Value1) & Mask##Size; \
750 const uint32_t T1 = allocateDword(); \
751 const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size; \
752 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
753 Immediate(uint64_t(Value0) & Mask##Size)); \
754 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
755 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
756 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), dwordAddress(T0)); \
757 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), dwordAddress(T1)); \
758 \
759 AssembledTest test = assemble(); \
760 test.setDwordTo(T0, V0); \
761 test.setDwordTo(T1, V1); \
762 test.run(); \
763 \
764 static constexpr uint64_t Result = \
765 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
766 ResultMask##Size); \
767 static constexpr uint32_t Expected0 = Result & Mask##Size; \
768 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
769 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
770 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
771 reset(); \
772 } while (0)
773
774 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size) \
775 do { \
776 static_assert(Size == 8 || Size == 16 || Size == 32, \
777 "Invalid size " #Size); \
778 static constexpr char TestString[] = \
779 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
780 ", Imm(" #Imm "), " #Op ", " #Size ")"; \
781 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
782 Immediate(uint64_t(Value0) & Mask##Size)); \
783 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
784 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
785 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), \
786 Immediate(uint64_t(Imm) & Mask##Size)); \
787 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), \
788 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
789 \
790 AssembledTest test = assemble(); \
791 test.run(); \
792 \
793 static constexpr uint64_t Result = \
794 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
795 ResultMask##Size); \
796 static constexpr uint32_t Expected0 = Result & Mask##Size; \
797 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
798 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
799 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
800 reset(); \
801 } while (0)
802
803 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size) \
804 do { \
805 static_assert(Size == 8 || Size == 16 || Size == 32, \
806 "Invalid size " #Size); \
807 static constexpr char TestString[] = \
808 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1 \
809 ", " #Value1 ", " #Op ", " #Size ")"; \
810 const uint32_t T0 = allocateDword(); \
811 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
812 const uint32_t T1 = allocateDword(); \
813 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
814 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
815 Immediate(uint64_t(Value1) & Mask##Size)); \
816 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
817 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
818 __ Inst0(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src0()); \
819 __ Inst1(IceType_i##Size, dwordAddress(T1), Encoded_GPR_##Src1()); \
820 \
821 AssembledTest test = assemble(); \
822 test.setDwordTo(T0, V0); \
823 test.setDwordTo(T1, V1); \
824 test.run(); \
825 \
826 static constexpr uint64_t Result = \
827 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \
828 ResultMask##Size); \
829 static constexpr uint32_t Expected0 = Result & Mask##Size; \
830 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
831 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
832 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
833 reset(); \
834 } while (0)
835
836 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size) \
837 do { \
838 static_assert(Size == 8 || Size == 16 || Size == 32, \
839 "Invalid size " #Size); \
840 static constexpr char TestString[] = \
841 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op \
842 ", " #Size ")"; \
843 const uint32_t T0 = allocateDword(); \
844 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
845 const uint32_t T1 = allocateDword(); \
846 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
847 __ Inst0(IceType_i##Size, dwordAddress(T0), \
848 Immediate(uint64_t(Imm) & Mask##Size)); \
849 __ Inst1(IceType_i##Size, dwordAddress(T1), \
850 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
851 \
852 AssembledTest test = assemble(); \
853 test.setDwordTo(T0, V0); \
854 test.setDwordTo(T1, V1); \
855 test.run(); \
856 \
857 static constexpr uint64_t Result = \
858 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \
859 ResultMask##Size); \
860 static constexpr uint32_t Expected0 = Result & Mask##Size; \
861 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
862 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
863 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
864 reset(); \
865 } while (0)
866
867 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
868 Size) \
869 do { \
870 TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
871 Size); \
872 TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
873 TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
874 TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size); \
875 TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size); \
876 } while (0)
877
878 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size) \
879 do { \
880 TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size); \
881 TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size); \
882 } while (0)
883
884 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size) \
885 do { \
886 TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1, \
887 0xFFFFFFFF0000017Full, Size); \
888 } while (0)
889
890 #define TestImpl(Dst0, Dst1, Src0, Src1) \
891 do { \
892 TestImplSize(Dst0, Dst1, Src0, Src1, 8); \
893 TestImplSize(Dst0, Dst1, Src0, Src1, 16); \
894 TestImplSize(Dst0, Dst1, Src0, Src1, 32); \
895 } while (0)
896
897 TestImpl(r1, r2, r3, r5);
898 TestImpl(r2, r3, r4, r6);
899 TestImpl(r3, r4, r5, r7);
900 TestImpl(r4, r5, r6, r8);
901 TestImpl(r5, r6, r7, r10);
902 TestImpl(r6, r7, r8, r11);
903 TestImpl(r7, r8, r10, r12);
904 TestImpl(r8, r10, r11, r13);
905 TestImpl(r10, r11, r12, r14);
906 TestImpl(r11, r12, r13, r15);
907 TestImpl(r12, r13, r14, r1);
908 TestImpl(r13, r14, r15, r2);
909 TestImpl(r14, r15, r1, r3);
910 TestImpl(r15, r1, r2, r4);
911
912 #undef TestImpl
913 #undef TestImplSize
914 #undef TestImplValues
915 #undef TestImplOp
916 #undef TestImplAddrImm
917 #undef TestImplAddrReg
918 #undef TestImplRegImm
919 #undef TestImplRegAddr
920 #undef TestImplRegReg
921 }
922
TEST_F(AssemblerX8664LowLevelTest,Cbw_Cwd_Cdq)923 TEST_F(AssemblerX8664LowLevelTest, Cbw_Cwd_Cdq) {
924 #define TestImpl(Inst, BytesSize, ...) \
925 do { \
926 __ Inst(); \
927 ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst; \
928 ASSERT_TRUE(verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__)); \
929 reset(); \
930 } while (0)
931
932 TestImpl(cbw, 2u, 0x66, 0x98);
933 TestImpl(cwd, 2u, 0x66, 0x99);
934 TestImpl(cdq, 1u, 0x99);
935
936 #undef TestImpl
937 }
938
TEST_F(AssemblerX8664Test,SingleOperandMul)939 TEST_F(AssemblerX8664Test, SingleOperandMul) {
940 static constexpr uint32_t Mask8 = 0x000000FF;
941 static constexpr uint32_t Mask16 = 0x0000FFFF;
942 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
943
944 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
945 do { \
946 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
947 "eax can not be src1."); \
948 \
949 static constexpr char TestString[] = \
950 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
951 ")"; \
952 static constexpr Type##64_t OperandEax = \
953 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
954 static constexpr Type##64_t OperandOther = \
955 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
956 static constexpr uint32_t ExpectedEax = \
957 Mask##Size & (OperandEax * OperandOther); \
958 static constexpr uint32_t ExpectedEdx = \
959 Mask##Size & ((OperandEax * OperandOther) >> Size); \
960 \
961 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
962 Immediate((Value0)&Mask##Size)); \
963 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
964 Immediate((Value1)&Mask##Size)); \
965 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
966 \
967 if (Size == 8) { \
968 /* mov %ah, %dl */ \
969 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
970 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
971 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
972 } \
973 \
974 AssembledTest test = assemble(); \
975 test.run(); \
976 \
977 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
978 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
979 reset(); \
980 } while (0)
981
982 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
983 do { \
984 static constexpr char TestString[] = \
985 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
986 static const uint32_t T0 = allocateDword(); \
987 static constexpr uint32_t V0 = Value1; \
988 static constexpr Type##64_t OperandEax = \
989 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
990 static constexpr Type##64_t OperandOther = \
991 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
992 static constexpr uint32_t ExpectedEax = \
993 Mask##Size & (OperandEax * OperandOther); \
994 static constexpr uint32_t ExpectedEdx = \
995 Mask##Size & ((OperandEax * OperandOther) >> Size); \
996 \
997 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
998 Immediate((Value0)&Mask##Size)); \
999 __ Inst(IceType_i##Size, dwordAddress(T0)); \
1000 \
1001 if (Size == 8) { \
1002 /* mov %ah, %dl */ \
1003 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1004 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1005 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1006 } \
1007 \
1008 AssembledTest test = assemble(); \
1009 test.setDwordTo(T0, V0); \
1010 test.run(); \
1011 \
1012 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
1013 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
1014 reset(); \
1015 } while (0)
1016
1017 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
1018 do { \
1019 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
1020 TestImplAddr(Inst, Value0, Value1, Type, Size); \
1021 } while (0)
1022
1023 #define TestImplValue(Value0, Src, Value1, Size) \
1024 do { \
1025 TestImplOp(mul, Value0, Src, Value1, uint, Size); \
1026 TestImplOp(imul, Value0, Src, Value1, int, Size); \
1027 } while (0)
1028
1029 #define TestImplSize(Src, Size) \
1030 do { \
1031 TestImplValue(10, Src, 1, Size); \
1032 TestImplValue(10, Src, -1, Size); \
1033 TestImplValue(-10, Src, 37, Size); \
1034 TestImplValue(-10, Src, -15, Size); \
1035 } while (0)
1036
1037 #define TestImpl(Src) \
1038 do { \
1039 TestImplSize(Src, 8); \
1040 TestImplSize(Src, 16); \
1041 TestImplSize(Src, 32); \
1042 } while (0)
1043
1044 TestImpl(r2);
1045 TestImpl(r3);
1046 TestImpl(r4);
1047 TestImpl(r5);
1048 TestImpl(r6);
1049 TestImpl(r7);
1050 TestImpl(r8);
1051 TestImpl(r10);
1052 TestImpl(r11);
1053 TestImpl(r12);
1054 TestImpl(r13);
1055 TestImpl(r14);
1056 TestImpl(r15);
1057
1058 #undef TestImpl
1059 #undef TestImplSize
1060 #undef TestImplValue
1061 #undef TestImplOp
1062 #undef TestImplAddr
1063 #undef TestImplReg
1064 }
1065
TEST_F(AssemblerX8664Test,TwoOperandImul)1066 TEST_F(AssemblerX8664Test, TwoOperandImul) {
1067 static constexpr uint32_t Mask16 = 0x0000FFFF;
1068 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1069
1070 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
1071 do { \
1072 static constexpr char TestString[] = \
1073 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
1074 static constexpr int64_t Operand0 = \
1075 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1076 static constexpr int64_t Operand1 = \
1077 static_cast<int##Size##_t>((Value1)&Mask##Size); \
1078 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1079 \
1080 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1081 Immediate((Value0)&Mask##Size)); \
1082 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1083 Immediate((Value1)&Mask##Size)); \
1084 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1085 \
1086 if (Size == 8) { \
1087 /* mov %ah, %dl */ \
1088 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1089 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1090 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1091 } \
1092 \
1093 AssembledTest test = assemble(); \
1094 test.run(); \
1095 \
1096 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1097 reset(); \
1098 } while (0)
1099
1100 #define TestImplRegImm(Dst, Value0, Imm, Size) \
1101 do { \
1102 static constexpr char TestString[] = \
1103 "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")"; \
1104 static constexpr int64_t Operand0 = \
1105 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1106 static constexpr int64_t Operand1 = \
1107 static_cast<int##Size##_t>((Imm)&Mask##Size); \
1108 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1109 \
1110 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1111 Immediate((Value0)&Mask##Size)); \
1112 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Imm)); \
1113 \
1114 if (Size == 8) { \
1115 /* mov %ah, %dl */ \
1116 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1117 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1118 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1119 } \
1120 \
1121 AssembledTest test = assemble(); \
1122 test.run(); \
1123 \
1124 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1125 reset(); \
1126 } while (0)
1127
1128 #define TestImplRegAddr(Dst, Value0, Value1, Size) \
1129 do { \
1130 static constexpr char TestString[] = \
1131 "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")"; \
1132 static constexpr int64_t Operand0 = \
1133 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1134 static constexpr int64_t Operand1 = \
1135 static_cast<int##Size##_t>((Value1)&Mask##Size); \
1136 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1137 const uint32_t T0 = allocateDword(); \
1138 \
1139 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1140 Immediate((Value0)&Mask##Size)); \
1141 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
1142 \
1143 if (Size == 8) { \
1144 /* mov %ah, %dl */ \
1145 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1146 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1147 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1148 } \
1149 \
1150 AssembledTest test = assemble(); \
1151 test.setDwordTo(T0, static_cast<uint32_t>(Operand1)); \
1152 test.run(); \
1153 \
1154 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1155 reset(); \
1156 } while (0)
1157
1158 #define TestImplValue(Dst, Value0, Src, Value1, Size) \
1159 do { \
1160 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
1161 TestImplRegImm(Dst, Value0, Value1, Size); \
1162 TestImplRegAddr(Dst, Value0, Value1, Size); \
1163 } while (0)
1164
1165 #define TestImplSize(Dst, Src, Size) \
1166 do { \
1167 TestImplValue(Dst, 1, Src, 1, Size); \
1168 TestImplValue(Dst, -10, Src, 0x4050AA20, Size); \
1169 TestImplValue(Dst, -2, Src, -55, Size); \
1170 } while (0)
1171
1172 #define TestImpl(Dst, Src) \
1173 do { \
1174 TestImplSize(Dst, Src, 16); \
1175 TestImplSize(Dst, Src, 32); \
1176 } while (0)
1177
1178 TestImpl(r1, r2);
1179 TestImpl(r2, r3);
1180 TestImpl(r3, r4);
1181 TestImpl(r4, r5);
1182 TestImpl(r5, r6);
1183 TestImpl(r6, r7);
1184 TestImpl(r7, r8);
1185 TestImpl(r8, r10);
1186 TestImpl(r10, r11);
1187 TestImpl(r11, r12);
1188 TestImpl(r12, r13);
1189 TestImpl(r13, r14);
1190 TestImpl(r14, r15);
1191 TestImpl(r15, r1);
1192
1193 #undef TestImpl
1194 #undef TestImplSize
1195 #undef TestImplValue
1196 #undef TestImplRegAddr
1197 #undef TestImplRegImm
1198 #undef TestImplRegReg
1199 }
1200
TEST_F(AssemblerX8664Test,Div)1201 TEST_F(AssemblerX8664Test, Div) {
1202 static constexpr uint32_t Mask8 = 0x000000FF;
1203 static constexpr uint32_t Mask16 = 0x0000FFFF;
1204 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1205
1206 static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull;
1207 static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull;
1208 static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull;
1209
1210 using Operand0Type_int8 = int16_t;
1211 using Operand0Type_uint8 = uint16_t;
1212 using Operand0Type_int16 = int32_t;
1213 using Operand0Type_uint16 = uint32_t;
1214 using Operand0Type_int32 = int64_t;
1215 using Operand0Type_uint32 = uint64_t;
1216
1217 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
1218 do { \
1219 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
1220 "eax can not be src1."); \
1221 static_assert(Encoded_GPR_edx() != Encoded_GPR_##Src(), \
1222 "edx can not be src1."); \
1223 \
1224 static constexpr char TestString[] = \
1225 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
1226 ")"; \
1227 static constexpr Operand0Type_##Type##Size Operand0 = \
1228 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
1229 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
1230 static constexpr Type##Size##_t Operand0Hi = \
1231 (Operand0 >> Size) & Mask##Size; \
1232 static constexpr Type##Size##_t Operand1 = \
1233 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
1234 if (Size == 8) { \
1235 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
1236 __ mov( \
1237 IceType_i16, Encoded_GPR_eax(), \
1238 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
1239 } else { \
1240 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
1241 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
1242 } \
1243 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Operand1)); \
1244 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
1245 if (Size == 8) { \
1246 /* mov %ah, %dl */ \
1247 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1248 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1249 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
1250 if (Encoded_GPR_##Src() == Encoded_GPR_esi()) { \
1251 __ And(IceType_i16, Encoded_GPR_edx(), Immediate(0x00FF)); \
1252 } \
1253 } \
1254 \
1255 AssembledTest test = assemble(); \
1256 test.run(); \
1257 \
1258 static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size; \
1259 static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size; \
1260 ASSERT_EQ(Quocient, test.eax()) << TestString; \
1261 ASSERT_EQ(Reminder, test.edx()) << TestString; \
1262 reset(); \
1263 } while (0)
1264
1265 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
1266 do { \
1267 static constexpr char TestString[] = \
1268 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
1269 static constexpr Operand0Type_##Type##Size Operand0 = \
1270 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
1271 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
1272 static constexpr Type##Size##_t Operand0Hi = \
1273 (Operand0 >> Size) & Mask##Size; \
1274 const uint32_t T0 = allocateDword(); \
1275 static constexpr Type##Size##_t V0 = \
1276 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
1277 if (Size == 8) { \
1278 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
1279 __ mov( \
1280 IceType_i16, Encoded_GPR_eax(), \
1281 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
1282 } else { \
1283 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
1284 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
1285 } \
1286 __ Inst(IceType_i##Size, dwordAddress(T0)); \
1287 if (Size == 8) { \
1288 /* mov %ah, %dl */ \
1289 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1290 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1291 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
1292 } \
1293 \
1294 AssembledTest test = assemble(); \
1295 test.setDwordTo(T0, static_cast<uint32_t>(V0)); \
1296 test.run(); \
1297 \
1298 static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size; \
1299 static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size; \
1300 ASSERT_EQ(Quocient, test.eax()) << TestString; \
1301 ASSERT_EQ(Reminder, test.edx()) << TestString; \
1302 reset(); \
1303 } while (0)
1304
1305 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
1306 do { \
1307 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
1308 TestImplAddr(Inst, Value0, Value1, Type, Size); \
1309 } while (0)
1310
1311 #define TestImplValue(Value0, Src, Value1, Size) \
1312 do { \
1313 TestImplOp(div, Value0, Src, Value1, uint, Size); \
1314 TestImplOp(idiv, Value0, Src, Value1, int, Size); \
1315 } while (0)
1316
1317 #define TestImplSize(Src, Size) \
1318 do { \
1319 TestImplValue(10, Src, 1, Size); \
1320 TestImplValue(10, Src, -1, Size); \
1321 } while (0)
1322
1323 #define TestImpl(Src) \
1324 do { \
1325 TestImplSize(Src, 8); \
1326 TestImplSize(Src, 16); \
1327 TestImplSize(Src, 32); \
1328 } while (0)
1329
1330 TestImpl(r2);
1331 TestImpl(r3);
1332 TestImpl(r5);
1333 TestImpl(r6);
1334 TestImpl(r7);
1335 TestImpl(r8);
1336 TestImpl(r10);
1337 TestImpl(r11);
1338 TestImpl(r12);
1339 TestImpl(r13);
1340 TestImpl(r14);
1341 TestImpl(r15);
1342
1343 #undef TestImpl
1344 #undef TestImplSize
1345 #undef TestImplValue
1346 #undef TestImplOp
1347 #undef TestImplAddr
1348 #undef TestImplReg
1349 }
1350
TEST_F(AssemblerX8664Test,Incl_Decl_Addr)1351 TEST_F(AssemblerX8664Test, Incl_Decl_Addr) {
1352 #define TestImpl(Inst, Value0) \
1353 do { \
1354 const bool IsInc = std::string(#Inst).find("incl") != std::string::npos; \
1355 const uint32_t T0 = allocateDword(); \
1356 const uint32_t V0 = Value0; \
1357 \
1358 __ Inst(dwordAddress(T0)); \
1359 \
1360 AssembledTest test = assemble(); \
1361 test.setDwordTo(T0, V0); \
1362 test.run(); \
1363 \
1364 ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)), \
1365 test.contentsOfDword(T0)); \
1366 reset(); \
1367 } while (0)
1368
1369 #define TestInc(Value0) \
1370 do { \
1371 TestImpl(incl, Value0); \
1372 } while (0)
1373
1374 #define TestDec(Value0) \
1375 do { \
1376 TestImpl(decl, Value0); \
1377 } while (0)
1378
1379 TestInc(230);
1380
1381 TestDec(30);
1382
1383 #undef TestInc
1384 #undef TestDec
1385 #undef TestImpl
1386 }
1387
TEST_F(AssemblerX8664Test,Shifts)1388 TEST_F(AssemblerX8664Test, Shifts) {
1389 static constexpr uint32_t Mask8 = 0x000000FF;
1390 static constexpr uint32_t Mask16 = 0x0000FFFF;
1391 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1392
1393 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size) \
1394 do { \
1395 static constexpr char TestString[] = \
1396 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type \
1397 ", " #Size ")"; \
1398 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1399 const uint##Size##_t Expected = \
1400 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) | \
1401 (!IsRol ? 0 : (Value0) >> (Size - Imm))); \
1402 \
1403 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1404 Immediate((Value0)&Mask##Size)); \
1405 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
1406 Immediate((Imm)&Mask##Size)); \
1407 \
1408 AssembledTest test = assemble(); \
1409 test.run(); \
1410 \
1411 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1412 reset(); \
1413 } while (0)
1414
1415 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
1416 Type, Size) \
1417 do { \
1418 static constexpr char TestString[] = \
1419 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
1420 ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1421 const uint##Size##_t Expected = \
1422 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1423 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1424 \
1425 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1426 Immediate((Value0)&Mask##Size)); \
1427 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1428 Immediate((Value1)&Mask##Size)); \
1429 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src(), \
1430 Immediate(Count)); \
1431 \
1432 AssembledTest test = assemble(); \
1433 test.run(); \
1434 \
1435 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1436 reset(); \
1437 } while (0)
1438
1439 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size) \
1440 do { \
1441 static constexpr char TestString[] = \
1442 "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type \
1443 ", " #Size ")"; \
1444 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1445 const uint##Size##_t Expected = \
1446 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
1447 (!IsRol ? 0 : Value0 >> (Size - Count))); \
1448 \
1449 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1450 Immediate((Value0)&Mask##Size)); \
1451 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
1452 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_ecx()); \
1453 \
1454 AssembledTest test = assemble(); \
1455 test.run(); \
1456 \
1457 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1458 reset(); \
1459 } while (0)
1460
1461 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
1462 Type, Size) \
1463 do { \
1464 static constexpr char TestString[] = \
1465 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count \
1466 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1467 const uint##Size##_t Expected = \
1468 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1469 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1470 \
1471 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1472 Immediate((Value0)&Mask##Size)); \
1473 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1474 Immediate((Value1)&Mask##Size)); \
1475 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
1476 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1477 \
1478 AssembledTest test = assemble(); \
1479 test.run(); \
1480 \
1481 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1482 reset(); \
1483 } while (0)
1484
1485 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size) \
1486 do { \
1487 static constexpr char TestString[] = \
1488 "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type \
1489 ", " #Size ")"; \
1490 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1491 const uint##Size##_t Expected = \
1492 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
1493 (!IsRol ? 0 : Value0 >> (Size - Count))); \
1494 const uint32_t T0 = allocateDword(); \
1495 const uint32_t V0 = Value0; \
1496 \
1497 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
1498 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_ecx()); \
1499 \
1500 AssembledTest test = assemble(); \
1501 test.setDwordTo(T0, V0); \
1502 test.run(); \
1503 \
1504 ASSERT_EQ(static_cast<uint32_t>(Expected), \
1505 Mask##Size &test.contentsOfDword(T0)) \
1506 << TestString; \
1507 reset(); \
1508 } while (0)
1509
1510 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1511 Size) \
1512 do { \
1513 static constexpr char TestString[] = \
1514 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count \
1515 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1516 const uint##Size##_t Expected = \
1517 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1518 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1519 const uint32_t T0 = allocateDword(); \
1520 \
1521 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1522 Immediate((Value1)&Mask##Size)); \
1523 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
1524 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
1525 \
1526 AssembledTest test = assemble(); \
1527 test.setDwordTo(T0, static_cast<uint32_t>(Value0)); \
1528 test.run(); \
1529 \
1530 ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0)) \
1531 << TestString; \
1532 reset(); \
1533 } while (0)
1534
1535 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size) \
1536 do { \
1537 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
1538 "ecx should not be specified as Dst"); \
1539 TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size); \
1540 TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size); \
1541 TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size); \
1542 TestImplAddrCl(Inst, Value0, Count, Op, Type, Size); \
1543 } while (0)
1544
1545 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0, \
1546 Op1, Type, Size) \
1547 do { \
1548 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
1549 "ecx should not be specified as Dst"); \
1550 static_assert(Encoded_GPR_##Src() != Encoded_GPR_ecx(), \
1551 "ecx should not be specified as Src"); \
1552 TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1553 Size); \
1554 TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1555 Size); \
1556 TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \
1557 } while (0)
1558
1559 #define TestImplValue(Dst, Value0, Count, Size) \
1560 do { \
1561 TestImplOp(rol, Dst, Value0, Count, <<, uint, Size); \
1562 TestImplOp(shl, Dst, Value0, Count, <<, uint, Size); \
1563 TestImplOp(shr, Dst, Value0, Count, >>, uint, Size); \
1564 TestImplOp(sar, Dst, Value0, Count, >>, int, Size); \
1565 } while (0)
1566
1567 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size) \
1568 do { \
1569 TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>, \
1570 uint, Size); \
1571 TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<, \
1572 uint, Size); \
1573 } while (0)
1574
1575 #define TestImplSize(Dst, Size) \
1576 do { \
1577 TestImplValue(Dst, 0x8F, 3, Size); \
1578 TestImplValue(Dst, 0x8FFF, 7, Size); \
1579 TestImplValue(Dst, 0x8FFFF, 7, Size); \
1580 } while (0)
1581
1582 #define TestImplThreeOperandSize(Dst, Src, Size) \
1583 do { \
1584 TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size); \
1585 } while (0)
1586
1587 #define TestImpl(Dst, Src) \
1588 do { \
1589 TestImplSize(Dst, 8); \
1590 TestImplSize(Dst, 16); \
1591 TestImplThreeOperandSize(Dst, Src, 16); \
1592 TestImplSize(Dst, 32); \
1593 TestImplThreeOperandSize(Dst, Src, 32); \
1594 } while (0)
1595
1596 TestImpl(r1, r2);
1597 TestImpl(r2, r4);
1598 TestImpl(r4, r5);
1599 TestImpl(r5, r6);
1600 TestImpl(r6, r7);
1601 TestImpl(r7, r8);
1602 TestImpl(r8, r10);
1603 TestImpl(r10, r11);
1604 TestImpl(r11, r12);
1605 TestImpl(r12, r13);
1606 TestImpl(r13, r14);
1607 TestImpl(r14, r15);
1608 TestImpl(r15, r1);
1609
1610 #undef TestImpl
1611 #undef TestImplThreeOperandSize
1612 #undef TestImplSize
1613 #undef TestImplValue
1614 #undef TestImplThreeOperandValue
1615 #undef TestImplOp
1616 #undef TestImplThreeOperandOp
1617 #undef TestImplAddrCl
1618 #undef TestImplRegRegCl
1619 #undef TestImplRegCl
1620 #undef TestImplRegRegImm
1621 #undef TestImplRegImm
1622 }
1623
TEST_F(AssemblerX8664Test,Neg)1624 TEST_F(AssemblerX8664Test, Neg) {
1625 static constexpr uint32_t Mask8 = 0x000000ff;
1626 static constexpr uint32_t Mask16 = 0x0000ffff;
1627 static constexpr uint32_t Mask32 = 0xffffffff;
1628
1629 #define TestImplReg(Dst, Size) \
1630 do { \
1631 static constexpr int32_t Value = 0xFF00A543; \
1632 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1633 Immediate(static_cast<int##Size##_t>(Value) & Mask##Size)); \
1634 __ neg(IceType_i##Size, Encoded_GPR_##Dst()); \
1635 __ mov(IceType_i##Size, Encoded_GPR_eax(), Encoded_GPR_##Dst()); \
1636 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(Mask##Size)); \
1637 \
1638 AssembledTest test = assemble(); \
1639 test.run(); \
1640 \
1641 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
1642 test.eax()) \
1643 << "(" #Dst ", " #Size ")"; \
1644 reset(); \
1645 } while (0)
1646
1647 #define TestImplAddr(Size) \
1648 do { \
1649 static constexpr int32_t Value = 0xFF00A543; \
1650 const uint32_t T0 = allocateDword(); \
1651 __ neg(IceType_i##Size, dwordAddress(T0)); \
1652 \
1653 AssembledTest test = assemble(); \
1654 test.setDwordTo(T0, Value &Mask##Size); \
1655 test.run(); \
1656 \
1657 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
1658 test.contentsOfDword(T0)) \
1659 << "(Addr, " #Size ")"; \
1660 reset(); \
1661 } while (0)
1662
1663 #define TestImpl(Size) \
1664 do { \
1665 TestImplAddr(Size); \
1666 TestImplReg(r1, Size); \
1667 TestImplReg(r2, Size); \
1668 TestImplReg(r3, Size); \
1669 TestImplReg(r4, Size); \
1670 TestImplReg(r5, Size); \
1671 TestImplReg(r6, Size); \
1672 TestImplReg(r7, Size); \
1673 TestImplReg(r8, Size); \
1674 TestImplReg(r10, Size); \
1675 TestImplReg(r11, Size); \
1676 TestImplReg(r12, Size); \
1677 TestImplReg(r13, Size); \
1678 TestImplReg(r14, Size); \
1679 TestImplReg(r15, Size); \
1680 } while (0)
1681
1682 TestImpl(8);
1683 TestImpl(16);
1684 TestImpl(32);
1685
1686 #undef TestImpl
1687 #undef TestImplAddr
1688 #undef TestImplReg
1689 }
1690
TEST_F(AssemblerX8664Test,Not)1691 TEST_F(AssemblerX8664Test, Not) {
1692 #define TestImpl(Dst) \
1693 do { \
1694 static constexpr uint32_t Value = 0xFF00A543; \
1695 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
1696 __ notl(Encoded_GPR_##Dst()); \
1697 \
1698 AssembledTest test = assemble(); \
1699 test.run(); \
1700 \
1701 ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")"; \
1702 reset(); \
1703 } while (0)
1704
1705 TestImpl(r1);
1706 TestImpl(r2);
1707 TestImpl(r3);
1708 TestImpl(r4);
1709 TestImpl(r5);
1710 TestImpl(r6);
1711 TestImpl(r7);
1712 TestImpl(r8);
1713 TestImpl(r10);
1714 TestImpl(r11);
1715 TestImpl(r12);
1716 TestImpl(r13);
1717 TestImpl(r14);
1718 TestImpl(r15);
1719
1720 #undef TestImpl
1721 }
1722
TEST_F(AssemblerX8664Test,Bswap)1723 TEST_F(AssemblerX8664Test, Bswap) {
1724 #define TestImpl(Dst) \
1725 do { \
1726 static constexpr uint32_t Value = 0xFF00A543; \
1727 static constexpr uint32_t Expected = 0x43A500FF; \
1728 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
1729 __ bswap(IceType_i32, Encoded_GPR_##Dst()); \
1730 \
1731 AssembledTest test = assemble(); \
1732 test.run(); \
1733 \
1734 ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")"; \
1735 reset(); \
1736 } while (0)
1737
1738 TestImpl(r1);
1739 TestImpl(r2);
1740 TestImpl(r3);
1741 TestImpl(r4);
1742 TestImpl(r5);
1743 TestImpl(r6);
1744 TestImpl(r7);
1745 TestImpl(r8);
1746 TestImpl(r10);
1747 TestImpl(r11);
1748 TestImpl(r12);
1749 TestImpl(r13);
1750 TestImpl(r14);
1751 TestImpl(r15);
1752
1753 #undef TestImpl
1754 }
1755
TEST_F(AssemblerX8664Test,Bt)1756 TEST_F(AssemblerX8664Test, Bt) {
1757 #define TestImpl(Dst, Value0, Src, Value1) \
1758 do { \
1759 static constexpr char TestString[] = \
1760 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")"; \
1761 static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0; \
1762 \
1763 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value0)); \
1764 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value1)); \
1765 __ bt(Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1766 __ setcc(Cond::Br_b, ByteRegister::Encoded_8_Reg_al); \
1767 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(0xFFu)); \
1768 \
1769 AssembledTest test = assemble(); \
1770 test.run(); \
1771 \
1772 ASSERT_EQ(Expected, test.eax()) << TestString; \
1773 reset(); \
1774 } while (0)
1775
1776 TestImpl(r1, 0x08000000, r2, 27u);
1777 TestImpl(r2, 0x08000000, r3, 23u);
1778 TestImpl(r3, 0x00000000, r4, 1u);
1779 TestImpl(r4, 0x08000300, r5, 9u);
1780 TestImpl(r5, 0x08000300, r6, 10u);
1781 TestImpl(r6, 0x7FFFEFFF, r7, 13u);
1782 TestImpl(r7, 0x08000000, r8, 27u);
1783 TestImpl(r8, 0x08000000, r10, 23u);
1784 TestImpl(r10, 0x00000000, r11, 1u);
1785 TestImpl(r11, 0x08000300, r12, 9u);
1786 TestImpl(r12, 0x08000300, r13, 10u);
1787 TestImpl(r13, 0x7FFFEFFF, r14, 13u);
1788 TestImpl(r14, 0x08000000, r15, 27u);
1789 TestImpl(r15, 0x08000000, r1, 23u);
1790
1791 #undef TestImpl
1792 }
1793
1794 template <uint32_t Value, uint32_t Bits> class BitScanHelper {
1795 BitScanHelper() = delete;
1796
1797 public:
1798 static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32");
1799 using ValueType =
1800 typename std::conditional<Bits == 16, uint16_t, uint32_t>::type;
1801
1802 private:
BitIndex(bool Forward,ValueType Index)1803 static constexpr ValueType BitIndex(bool Forward, ValueType Index) {
1804 return (Value == 0)
1805 ? BitScanHelper<Value, Bits>::NoBitSet
1806 : (Value & (1u << Index)
1807 ? Index
1808 : BitIndex(Forward, (Forward ? Index + 1 : Index - 1)));
1809 }
1810
1811 public:
1812 static constexpr ValueType NoBitSet = static_cast<ValueType>(-1);
1813 static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0);
1814 static constexpr ValueType bsr =
1815 BitIndex(/*Forward*/ false, /*Index=*/Bits - 1);
1816 };
1817
TEST_F(AssemblerX8664Test,BitScanOperations)1818 TEST_F(AssemblerX8664Test, BitScanOperations) {
1819 #define TestImplRegReg(Inst, Dst, Src, Value1, Size) \
1820 do { \
1821 static constexpr char TestString[] = \
1822 "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")"; \
1823 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
1824 const uint32_t ZeroFlag = allocateDword(); \
1825 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
1826 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1827 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
1828 \
1829 AssembledTest test = assemble(); \
1830 test.setDwordTo(ZeroFlag, 0u); \
1831 test.run(); \
1832 \
1833 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
1834 test.contentsOfDword(ZeroFlag)) \
1835 << TestString; \
1836 if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) { \
1837 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1838 } \
1839 reset(); \
1840 } while (0)
1841
1842 #define TestImplRegAddr(Inst, Dst, Value1, Size) \
1843 do { \
1844 static constexpr char TestString[] = \
1845 "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")"; \
1846 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
1847 const uint32_t T0 = allocateDword(); \
1848 const uint32_t ZeroFlag = allocateDword(); \
1849 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
1850 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
1851 \
1852 AssembledTest test = assemble(); \
1853 test.setDwordTo(T0, Value1); \
1854 test.setDwordTo(ZeroFlag, 0u); \
1855 test.run(); \
1856 \
1857 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
1858 test.contentsOfDword(ZeroFlag)) \
1859 << TestString; \
1860 if (Expected != BitScanHelper<Value1, Size>::NoBitSet) { \
1861 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1862 } \
1863 reset(); \
1864 } while (0)
1865
1866 #define TestImplSize(Dst, Src, Value1, Size) \
1867 do { \
1868 TestImplRegReg(bsf, Dst, Src, Value1, Size); \
1869 TestImplRegAddr(bsf, Dst, Value1, Size); \
1870 TestImplRegReg(bsr, Dst, Src, Value1, Size); \
1871 TestImplRegAddr(bsf, Dst, Value1, Size); \
1872 } while (0)
1873
1874 #define TestImplValue(Dst, Src, Value1) \
1875 do { \
1876 TestImplSize(Dst, Src, Value1, 16); \
1877 TestImplSize(Dst, Src, Value1, 32); \
1878 } while (0)
1879
1880 #define TestImpl(Dst, Src) \
1881 do { \
1882 TestImplValue(Dst, Src, 0x80000001); \
1883 TestImplValue(Dst, Src, 0x00000000); \
1884 TestImplValue(Dst, Src, 0x80001000); \
1885 TestImplValue(Dst, Src, 0x00FFFF00); \
1886 } while (0)
1887
1888 TestImpl(r1, r2);
1889 TestImpl(r2, r3);
1890 TestImpl(r3, r4);
1891 TestImpl(r4, r5);
1892 TestImpl(r5, r6);
1893 TestImpl(r6, r7);
1894 TestImpl(r7, r8);
1895 TestImpl(r8, r10);
1896 TestImpl(r10, r11);
1897 TestImpl(r11, r12);
1898 TestImpl(r12, r13);
1899 TestImpl(r13, r14);
1900 TestImpl(r14, r15);
1901 TestImpl(r15, r1);
1902
1903 #undef TestImpl
1904 #undef TestImplValue
1905 #undef TestImplSize
1906 #undef TestImplRegAddr
1907 #undef TestImplRegReg
1908 }
1909
1910 } // end of anonymous namespace
1911 } // end of namespace Test
1912 } // end of namespace X8664
1913 } // end of namespace Ice
1914