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 = (uint64_t(Value0) & ResultMask##Size) \
732 Op(uint64_t(Value1) & ResultMask##Size); \
733 static constexpr uint32_t Expected0 = Result & Mask##Size; \
734 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
735 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
736 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
737 reset(); \
738 } while (0)
739
740 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size) \
741 do { \
742 static_assert(Size == 8 || Size == 16 || Size == 32, \
743 "Invalid size " #Size); \
744 static constexpr char TestString[] = \
745 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
746 ", Addr, " #Value1 ", " #Op ", " #Size ")"; \
747 const uint32_t T0 = allocateDword(); \
748 const uint32_t V0 = uint64_t(Value1) & Mask##Size; \
749 const uint32_t T1 = allocateDword(); \
750 const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size; \
751 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
752 Immediate(uint64_t(Value0) & Mask##Size)); \
753 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
754 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
755 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), dwordAddress(T0)); \
756 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), dwordAddress(T1)); \
757 \
758 AssembledTest test = assemble(); \
759 test.setDwordTo(T0, V0); \
760 test.setDwordTo(T1, V1); \
761 test.run(); \
762 \
763 static constexpr uint64_t Result = (uint64_t(Value0) & ResultMask##Size) \
764 Op(uint64_t(Value1) & ResultMask##Size); \
765 static constexpr uint32_t Expected0 = Result & Mask##Size; \
766 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
767 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
768 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
769 reset(); \
770 } while (0)
771
772 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size) \
773 do { \
774 static_assert(Size == 8 || Size == 16 || Size == 32, \
775 "Invalid size " #Size); \
776 static constexpr char TestString[] = \
777 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \
778 ", Imm(" #Imm "), " #Op ", " #Size ")"; \
779 __ mov(IceType_i##Size, Encoded_GPR_##Dst0(), \
780 Immediate(uint64_t(Value0) & Mask##Size)); \
781 __ mov(IceType_i##Size, Encoded_GPR_##Dst1(), \
782 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \
783 __ Inst0(IceType_i##Size, Encoded_GPR_##Dst0(), \
784 Immediate(uint64_t(Imm) & Mask##Size)); \
785 __ Inst1(IceType_i##Size, Encoded_GPR_##Dst1(), \
786 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
787 \
788 AssembledTest test = assemble(); \
789 test.run(); \
790 \
791 static constexpr uint64_t Result = (uint64_t(Value0) & ResultMask##Size) \
792 Op(uint64_t(Imm) & ResultMask##Size); \
793 static constexpr uint32_t Expected0 = Result & Mask##Size; \
794 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
795 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \
796 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \
797 reset(); \
798 } while (0)
799
800 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size) \
801 do { \
802 static_assert(Size == 8 || Size == 16 || Size == 32, \
803 "Invalid size " #Size); \
804 static constexpr char TestString[] = \
805 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1 \
806 ", " #Value1 ", " #Op ", " #Size ")"; \
807 const uint32_t T0 = allocateDword(); \
808 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
809 const uint32_t T1 = allocateDword(); \
810 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
811 __ mov(IceType_i##Size, Encoded_GPR_##Src0(), \
812 Immediate(uint64_t(Value1) & Mask##Size)); \
813 __ mov(IceType_i##Size, Encoded_GPR_##Src1(), \
814 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \
815 __ Inst0(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src0()); \
816 __ Inst1(IceType_i##Size, dwordAddress(T1), Encoded_GPR_##Src1()); \
817 \
818 AssembledTest test = assemble(); \
819 test.setDwordTo(T0, V0); \
820 test.setDwordTo(T1, V1); \
821 test.run(); \
822 \
823 static constexpr uint64_t Result = (uint64_t(Value0) & ResultMask##Size) \
824 Op(uint64_t(Value1) & ResultMask##Size); \
825 static constexpr uint32_t Expected0 = Result & Mask##Size; \
826 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
827 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
828 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
829 reset(); \
830 } while (0)
831
832 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size) \
833 do { \
834 static_assert(Size == 8 || Size == 16 || Size == 32, \
835 "Invalid size " #Size); \
836 static constexpr char TestString[] = \
837 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op \
838 ", " #Size ")"; \
839 const uint32_t T0 = allocateDword(); \
840 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \
841 const uint32_t T1 = allocateDword(); \
842 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \
843 __ Inst0(IceType_i##Size, dwordAddress(T0), \
844 Immediate(uint64_t(Imm) & Mask##Size)); \
845 __ Inst1(IceType_i##Size, dwordAddress(T1), \
846 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \
847 \
848 AssembledTest test = assemble(); \
849 test.setDwordTo(T0, V0); \
850 test.setDwordTo(T1, V1); \
851 test.run(); \
852 \
853 static constexpr uint64_t Result = (uint64_t(Value0) & ResultMask##Size) \
854 Op(uint64_t(Imm) & ResultMask##Size); \
855 static constexpr uint32_t Expected0 = Result & Mask##Size; \
856 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \
857 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \
858 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \
859 reset(); \
860 } while (0)
861
862 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
863 Size) \
864 do { \
865 TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \
866 Size); \
867 TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
868 TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \
869 TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size); \
870 TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size); \
871 } while (0)
872
873 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size) \
874 do { \
875 TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size); \
876 TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size); \
877 } while (0)
878
879 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size) \
880 do { \
881 TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1, \
882 0xFFFFFFFF0000017Full, Size); \
883 } while (0)
884
885 #define TestImpl(Dst0, Dst1, Src0, Src1) \
886 do { \
887 TestImplSize(Dst0, Dst1, Src0, Src1, 8); \
888 TestImplSize(Dst0, Dst1, Src0, Src1, 16); \
889 TestImplSize(Dst0, Dst1, Src0, Src1, 32); \
890 } while (0)
891
892 TestImpl(r1, r2, r3, r5);
893 TestImpl(r2, r3, r4, r6);
894 TestImpl(r3, r4, r5, r7);
895 TestImpl(r4, r5, r6, r8);
896 TestImpl(r5, r6, r7, r10);
897 TestImpl(r6, r7, r8, r11);
898 TestImpl(r7, r8, r10, r12);
899 TestImpl(r8, r10, r11, r13);
900 TestImpl(r10, r11, r12, r14);
901 TestImpl(r11, r12, r13, r15);
902 TestImpl(r12, r13, r14, r1);
903 TestImpl(r13, r14, r15, r2);
904 TestImpl(r14, r15, r1, r3);
905 TestImpl(r15, r1, r2, r4);
906
907 #undef TestImpl
908 #undef TestImplSize
909 #undef TestImplValues
910 #undef TestImplOp
911 #undef TestImplAddrImm
912 #undef TestImplAddrReg
913 #undef TestImplRegImm
914 #undef TestImplRegAddr
915 #undef TestImplRegReg
916 }
917
TEST_F(AssemblerX8664LowLevelTest,Cbw_Cwd_Cdq)918 TEST_F(AssemblerX8664LowLevelTest, Cbw_Cwd_Cdq) {
919 #define TestImpl(Inst, BytesSize, ...) \
920 do { \
921 __ Inst(); \
922 ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst; \
923 ASSERT_TRUE(verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__)); \
924 reset(); \
925 } while (0)
926
927 TestImpl(cbw, 2u, 0x66, 0x98);
928 TestImpl(cwd, 2u, 0x66, 0x99);
929 TestImpl(cdq, 1u, 0x99);
930
931 #undef TestImpl
932 }
933
TEST_F(AssemblerX8664Test,SingleOperandMul)934 TEST_F(AssemblerX8664Test, SingleOperandMul) {
935 static constexpr uint32_t Mask8 = 0x000000FF;
936 static constexpr uint32_t Mask16 = 0x0000FFFF;
937 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
938
939 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
940 do { \
941 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
942 "eax can not be src1."); \
943 \
944 static constexpr char TestString[] = \
945 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
946 ")"; \
947 static constexpr Type##64_t OperandEax = \
948 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
949 static constexpr Type##64_t OperandOther = \
950 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
951 static constexpr uint32_t ExpectedEax = \
952 Mask##Size & (OperandEax * OperandOther); \
953 static constexpr uint32_t ExpectedEdx = \
954 Mask##Size & ((OperandEax * OperandOther) >> Size); \
955 \
956 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
957 Immediate((Value0)&Mask##Size)); \
958 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
959 Immediate((Value1)&Mask##Size)); \
960 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
961 \
962 if (Size == 8) { \
963 /* mov %ah, %dl */ \
964 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
965 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
966 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
967 } \
968 \
969 AssembledTest test = assemble(); \
970 test.run(); \
971 \
972 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
973 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
974 reset(); \
975 } while (0)
976
977 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
978 do { \
979 static constexpr char TestString[] = \
980 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
981 static const uint32_t T0 = allocateDword(); \
982 static constexpr uint32_t V0 = Value1; \
983 static constexpr Type##64_t OperandEax = \
984 static_cast<Type##Size##_t>((Value0)&Mask##Size); \
985 static constexpr Type##64_t OperandOther = \
986 static_cast<Type##Size##_t>((Value1)&Mask##Size); \
987 static constexpr uint32_t ExpectedEax = \
988 Mask##Size & (OperandEax * OperandOther); \
989 static constexpr uint32_t ExpectedEdx = \
990 Mask##Size & ((OperandEax * OperandOther) >> Size); \
991 \
992 __ mov(IceType_i##Size, Encoded_GPR_eax(), \
993 Immediate((Value0)&Mask##Size)); \
994 __ Inst(IceType_i##Size, dwordAddress(T0)); \
995 \
996 if (Size == 8) { \
997 /* mov %ah, %dl */ \
998 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
999 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1000 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1001 } \
1002 \
1003 AssembledTest test = assemble(); \
1004 test.setDwordTo(T0, V0); \
1005 test.run(); \
1006 \
1007 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \
1008 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \
1009 reset(); \
1010 } while (0)
1011
1012 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
1013 do { \
1014 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
1015 TestImplAddr(Inst, Value0, Value1, Type, Size); \
1016 } while (0)
1017
1018 #define TestImplValue(Value0, Src, Value1, Size) \
1019 do { \
1020 TestImplOp(mul, Value0, Src, Value1, uint, Size); \
1021 TestImplOp(imul, Value0, Src, Value1, int, Size); \
1022 } while (0)
1023
1024 #define TestImplSize(Src, Size) \
1025 do { \
1026 TestImplValue(10, Src, 1, Size); \
1027 TestImplValue(10, Src, -1, Size); \
1028 TestImplValue(-10, Src, 37, Size); \
1029 TestImplValue(-10, Src, -15, Size); \
1030 } while (0)
1031
1032 #define TestImpl(Src) \
1033 do { \
1034 TestImplSize(Src, 8); \
1035 TestImplSize(Src, 16); \
1036 TestImplSize(Src, 32); \
1037 } while (0)
1038
1039 TestImpl(r2);
1040 TestImpl(r3);
1041 TestImpl(r4);
1042 TestImpl(r5);
1043 TestImpl(r6);
1044 TestImpl(r7);
1045 TestImpl(r8);
1046 TestImpl(r10);
1047 TestImpl(r11);
1048 TestImpl(r12);
1049 TestImpl(r13);
1050 TestImpl(r14);
1051 TestImpl(r15);
1052
1053 #undef TestImpl
1054 #undef TestImplSize
1055 #undef TestImplValue
1056 #undef TestImplOp
1057 #undef TestImplAddr
1058 #undef TestImplReg
1059 }
1060
TEST_F(AssemblerX8664Test,TwoOperandImul)1061 TEST_F(AssemblerX8664Test, TwoOperandImul) {
1062 static constexpr uint32_t Mask16 = 0x0000FFFF;
1063 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1064
1065 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \
1066 do { \
1067 static constexpr char TestString[] = \
1068 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \
1069 static constexpr int64_t Operand0 = \
1070 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1071 static constexpr int64_t Operand1 = \
1072 static_cast<int##Size##_t>((Value1)&Mask##Size); \
1073 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1074 \
1075 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1076 Immediate((Value0)&Mask##Size)); \
1077 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1078 Immediate((Value1)&Mask##Size)); \
1079 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1080 \
1081 if (Size == 8) { \
1082 /* mov %ah, %dl */ \
1083 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1084 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1085 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1086 } \
1087 \
1088 AssembledTest test = assemble(); \
1089 test.run(); \
1090 \
1091 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1092 reset(); \
1093 } while (0)
1094
1095 #define TestImplRegImm(Dst, Value0, Imm, Size) \
1096 do { \
1097 static constexpr char TestString[] = \
1098 "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")"; \
1099 static constexpr int64_t Operand0 = \
1100 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1101 static constexpr int64_t Operand1 = \
1102 static_cast<int##Size##_t>((Imm)&Mask##Size); \
1103 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1104 \
1105 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1106 Immediate((Value0)&Mask##Size)); \
1107 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), Immediate(Imm)); \
1108 \
1109 if (Size == 8) { \
1110 /* mov %ah, %dl */ \
1111 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1112 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1113 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1114 } \
1115 \
1116 AssembledTest test = assemble(); \
1117 test.run(); \
1118 \
1119 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1120 reset(); \
1121 } while (0)
1122
1123 #define TestImplRegAddr(Dst, Value0, Value1, Size) \
1124 do { \
1125 static constexpr char TestString[] = \
1126 "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")"; \
1127 static constexpr int64_t Operand0 = \
1128 static_cast<int##Size##_t>((Value0)&Mask##Size); \
1129 static constexpr int64_t Operand1 = \
1130 static_cast<int##Size##_t>((Value1)&Mask##Size); \
1131 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \
1132 const uint32_t T0 = allocateDword(); \
1133 \
1134 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1135 Immediate((Value0)&Mask##Size)); \
1136 __ imul(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
1137 \
1138 if (Size == 8) { \
1139 /* mov %ah, %dl */ \
1140 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1141 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1142 __ And(IceType_i16, Encoded_GPR_ax(), Immediate(0x00FF)); \
1143 } \
1144 \
1145 AssembledTest test = assemble(); \
1146 test.setDwordTo(T0, static_cast<uint32_t>(Operand1)); \
1147 test.run(); \
1148 \
1149 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1150 reset(); \
1151 } while (0)
1152
1153 #define TestImplValue(Dst, Value0, Src, Value1, Size) \
1154 do { \
1155 TestImplRegReg(Dst, Value0, Src, Value1, Size); \
1156 TestImplRegImm(Dst, Value0, Value1, Size); \
1157 TestImplRegAddr(Dst, Value0, Value1, Size); \
1158 } while (0)
1159
1160 #define TestImplSize(Dst, Src, Size) \
1161 do { \
1162 TestImplValue(Dst, 1, Src, 1, Size); \
1163 TestImplValue(Dst, -10, Src, 0x4050AA20, Size); \
1164 TestImplValue(Dst, -2, Src, -55, Size); \
1165 } while (0)
1166
1167 #define TestImpl(Dst, Src) \
1168 do { \
1169 TestImplSize(Dst, Src, 16); \
1170 TestImplSize(Dst, Src, 32); \
1171 } while (0)
1172
1173 TestImpl(r1, r2);
1174 TestImpl(r2, r3);
1175 TestImpl(r3, r4);
1176 TestImpl(r4, r5);
1177 TestImpl(r5, r6);
1178 TestImpl(r6, r7);
1179 TestImpl(r7, r8);
1180 TestImpl(r8, r10);
1181 TestImpl(r10, r11);
1182 TestImpl(r11, r12);
1183 TestImpl(r12, r13);
1184 TestImpl(r13, r14);
1185 TestImpl(r14, r15);
1186 TestImpl(r15, r1);
1187
1188 #undef TestImpl
1189 #undef TestImplSize
1190 #undef TestImplValue
1191 #undef TestImplRegAddr
1192 #undef TestImplRegImm
1193 #undef TestImplRegReg
1194 }
1195
TEST_F(AssemblerX8664Test,Div)1196 TEST_F(AssemblerX8664Test, Div) {
1197 static constexpr uint32_t Mask8 = 0x000000FF;
1198 static constexpr uint32_t Mask16 = 0x0000FFFF;
1199 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1200
1201 static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull;
1202 static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull;
1203 static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull;
1204
1205 using Operand0Type_int8 = int16_t;
1206 using Operand0Type_uint8 = uint16_t;
1207 using Operand0Type_int16 = int32_t;
1208 using Operand0Type_uint16 = uint32_t;
1209 using Operand0Type_int32 = int64_t;
1210 using Operand0Type_uint32 = uint64_t;
1211
1212 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \
1213 do { \
1214 static_assert(Encoded_GPR_eax() != Encoded_GPR_##Src(), \
1215 "eax can not be src1."); \
1216 static_assert(Encoded_GPR_edx() != Encoded_GPR_##Src(), \
1217 "edx can not be src1."); \
1218 \
1219 static constexpr char TestString[] = \
1220 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \
1221 ")"; \
1222 static constexpr Operand0Type_##Type##Size Operand0 = \
1223 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
1224 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
1225 static constexpr Type##Size##_t Operand0Hi = \
1226 (Operand0 >> Size) & Mask##Size; \
1227 static constexpr Type##Size##_t Operand1 = \
1228 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
1229 if (Size == 8) { \
1230 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
1231 __ mov( \
1232 IceType_i16, Encoded_GPR_eax(), \
1233 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
1234 } else { \
1235 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
1236 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
1237 } \
1238 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Operand1)); \
1239 __ Inst(IceType_i##Size, Encoded_GPR_##Src()); \
1240 if (Size == 8) { \
1241 /* mov %ah, %dl */ \
1242 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1243 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1244 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
1245 if (Encoded_GPR_##Src() == Encoded_GPR_esi()) { \
1246 __ And(IceType_i16, Encoded_GPR_edx(), Immediate(0x00FF)); \
1247 } \
1248 } \
1249 \
1250 AssembledTest test = assemble(); \
1251 test.run(); \
1252 \
1253 static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size; \
1254 static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size; \
1255 ASSERT_EQ(Quocient, test.eax()) << TestString; \
1256 ASSERT_EQ(Reminder, test.edx()) << TestString; \
1257 reset(); \
1258 } while (0)
1259
1260 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \
1261 do { \
1262 static constexpr char TestString[] = \
1263 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \
1264 static constexpr Operand0Type_##Type##Size Operand0 = \
1265 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \
1266 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \
1267 static constexpr Type##Size##_t Operand0Hi = \
1268 (Operand0 >> Size) & Mask##Size; \
1269 const uint32_t T0 = allocateDword(); \
1270 static constexpr Type##Size##_t V0 = \
1271 static_cast<Type##Size##_t>(Value1) & Mask##Size; \
1272 if (Size == 8) { \
1273 /* mov Operand0Hi|Operand0Lo, %ah|%al */ \
1274 __ mov( \
1275 IceType_i16, Encoded_GPR_eax(), \
1276 Immediate((static_cast<uint16_t>(Operand0Hi) << 8 | Operand0Lo))); \
1277 } else { \
1278 __ mov(IceType_i##Size, Encoded_GPR_eax(), Immediate(Operand0Lo)); \
1279 __ mov(IceType_i##Size, Encoded_GPR_edx(), Immediate(Operand0Hi)); \
1280 } \
1281 __ Inst(IceType_i##Size, dwordAddress(T0)); \
1282 if (Size == 8) { \
1283 /* mov %ah, %dl */ \
1284 __ mov(IceType_i16, Encoded_GPR_dx(), Encoded_GPR_ax()); \
1285 __ shr(IceType_i32, Encoded_GPR_edx(), Immediate(8)); \
1286 __ And(IceType_i16, Encoded_GPR_eax(), Immediate(0x00FF)); \
1287 } \
1288 \
1289 AssembledTest test = assemble(); \
1290 test.setDwordTo(T0, static_cast<uint32_t>(V0)); \
1291 test.run(); \
1292 \
1293 static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size; \
1294 static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size; \
1295 ASSERT_EQ(Quocient, test.eax()) << TestString; \
1296 ASSERT_EQ(Reminder, test.edx()) << TestString; \
1297 reset(); \
1298 } while (0)
1299
1300 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \
1301 do { \
1302 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \
1303 TestImplAddr(Inst, Value0, Value1, Type, Size); \
1304 } while (0)
1305
1306 #define TestImplValue(Value0, Src, Value1, Size) \
1307 do { \
1308 TestImplOp(div, Value0, Src, Value1, uint, Size); \
1309 TestImplOp(idiv, Value0, Src, Value1, int, Size); \
1310 } while (0)
1311
1312 #define TestImplSize(Src, Size) \
1313 do { \
1314 TestImplValue(10, Src, 1, Size); \
1315 TestImplValue(10, Src, -1, Size); \
1316 } while (0)
1317
1318 #define TestImpl(Src) \
1319 do { \
1320 TestImplSize(Src, 8); \
1321 TestImplSize(Src, 16); \
1322 TestImplSize(Src, 32); \
1323 } while (0)
1324
1325 TestImpl(r2);
1326 TestImpl(r3);
1327 TestImpl(r5);
1328 TestImpl(r6);
1329 TestImpl(r7);
1330 TestImpl(r8);
1331 TestImpl(r10);
1332 TestImpl(r11);
1333 TestImpl(r12);
1334 TestImpl(r13);
1335 TestImpl(r14);
1336 TestImpl(r15);
1337
1338 #undef TestImpl
1339 #undef TestImplSize
1340 #undef TestImplValue
1341 #undef TestImplOp
1342 #undef TestImplAddr
1343 #undef TestImplReg
1344 }
1345
TEST_F(AssemblerX8664Test,Incl_Decl_Addr)1346 TEST_F(AssemblerX8664Test, Incl_Decl_Addr) {
1347 #define TestImpl(Inst, Value0) \
1348 do { \
1349 const bool IsInc = std::string(#Inst).find("incl") != std::string::npos; \
1350 const uint32_t T0 = allocateDword(); \
1351 const uint32_t V0 = Value0; \
1352 \
1353 __ Inst(dwordAddress(T0)); \
1354 \
1355 AssembledTest test = assemble(); \
1356 test.setDwordTo(T0, V0); \
1357 test.run(); \
1358 \
1359 ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)), \
1360 test.contentsOfDword(T0)); \
1361 reset(); \
1362 } while (0)
1363
1364 #define TestInc(Value0) \
1365 do { \
1366 TestImpl(incl, Value0); \
1367 } while (0)
1368
1369 #define TestDec(Value0) \
1370 do { \
1371 TestImpl(decl, Value0); \
1372 } while (0)
1373
1374 TestInc(230);
1375
1376 TestDec(30);
1377
1378 #undef TestInc
1379 #undef TestDec
1380 #undef TestImpl
1381 }
1382
TEST_F(AssemblerX8664Test,Shifts)1383 TEST_F(AssemblerX8664Test, Shifts) {
1384 static constexpr uint32_t Mask8 = 0x000000FF;
1385 static constexpr uint32_t Mask16 = 0x0000FFFF;
1386 static constexpr uint32_t Mask32 = 0xFFFFFFFF;
1387
1388 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size) \
1389 do { \
1390 static constexpr char TestString[] = \
1391 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type \
1392 ", " #Size ")"; \
1393 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1394 const uint##Size##_t Expected = \
1395 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) | \
1396 (!IsRol ? 0 : (Value0) >> (Size - Imm))); \
1397 \
1398 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1399 Immediate((Value0)&Mask##Size)); \
1400 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), \
1401 Immediate((Imm)&Mask##Size)); \
1402 \
1403 AssembledTest test = assemble(); \
1404 test.run(); \
1405 \
1406 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1407 reset(); \
1408 } while (0)
1409
1410 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
1411 Type, Size) \
1412 do { \
1413 static constexpr char TestString[] = \
1414 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \
1415 ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1416 const uint##Size##_t Expected = \
1417 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1418 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1419 \
1420 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1421 Immediate((Value0)&Mask##Size)); \
1422 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1423 Immediate((Value1)&Mask##Size)); \
1424 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src(), \
1425 Immediate(Count)); \
1426 \
1427 AssembledTest test = assemble(); \
1428 test.run(); \
1429 \
1430 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1431 reset(); \
1432 } while (0)
1433
1434 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size) \
1435 do { \
1436 static constexpr char TestString[] = \
1437 "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type \
1438 ", " #Size ")"; \
1439 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1440 const uint##Size##_t Expected = \
1441 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
1442 (!IsRol ? 0 : Value0 >> (Size - Count))); \
1443 \
1444 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1445 Immediate((Value0)&Mask##Size)); \
1446 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
1447 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_ecx()); \
1448 \
1449 AssembledTest test = assemble(); \
1450 test.run(); \
1451 \
1452 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1453 reset(); \
1454 } while (0)
1455
1456 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \
1457 Type, Size) \
1458 do { \
1459 static constexpr char TestString[] = \
1460 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count \
1461 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1462 const uint##Size##_t Expected = \
1463 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1464 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1465 \
1466 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1467 Immediate((Value0)&Mask##Size)); \
1468 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1469 Immediate((Value1)&Mask##Size)); \
1470 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
1471 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1472 \
1473 AssembledTest test = assemble(); \
1474 test.run(); \
1475 \
1476 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \
1477 reset(); \
1478 } while (0)
1479
1480 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size) \
1481 do { \
1482 static constexpr char TestString[] = \
1483 "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type \
1484 ", " #Size ")"; \
1485 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \
1486 const uint##Size##_t Expected = \
1487 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \
1488 (!IsRol ? 0 : Value0 >> (Size - Count))); \
1489 const uint32_t T0 = allocateDword(); \
1490 const uint32_t V0 = Value0; \
1491 \
1492 __ mov(IceType_i8, Encoded_GPR_ecx(), Immediate((Count)&Mask##Size)); \
1493 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_ecx()); \
1494 \
1495 AssembledTest test = assemble(); \
1496 test.setDwordTo(T0, V0); \
1497 test.run(); \
1498 \
1499 ASSERT_EQ(static_cast<uint32_t>(Expected), \
1500 Mask##Size &test.contentsOfDword(T0)) \
1501 << TestString; \
1502 reset(); \
1503 } while (0)
1504
1505 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1506 Size) \
1507 do { \
1508 static constexpr char TestString[] = \
1509 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count \
1510 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \
1511 const uint##Size##_t Expected = \
1512 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \
1513 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \
1514 const uint32_t T0 = allocateDword(); \
1515 \
1516 __ mov(IceType_i##Size, Encoded_GPR_##Src(), \
1517 Immediate((Value1)&Mask##Size)); \
1518 __ mov(IceType_i##Size, Encoded_GPR_ecx(), Immediate((Count)&0x7F)); \
1519 __ Inst(IceType_i##Size, dwordAddress(T0), Encoded_GPR_##Src()); \
1520 \
1521 AssembledTest test = assemble(); \
1522 test.setDwordTo(T0, static_cast<uint32_t>(Value0)); \
1523 test.run(); \
1524 \
1525 ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0)) \
1526 << TestString; \
1527 reset(); \
1528 } while (0)
1529
1530 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size) \
1531 do { \
1532 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
1533 "ecx should not be specified as Dst"); \
1534 TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size); \
1535 TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size); \
1536 TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size); \
1537 TestImplAddrCl(Inst, Value0, Count, Op, Type, Size); \
1538 } while (0)
1539
1540 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0, \
1541 Op1, Type, Size) \
1542 do { \
1543 static_assert(Encoded_GPR_##Dst() != Encoded_GPR_ecx(), \
1544 "ecx should not be specified as Dst"); \
1545 static_assert(Encoded_GPR_##Src() != Encoded_GPR_ecx(), \
1546 "ecx should not be specified as Src"); \
1547 TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1548 Size); \
1549 TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \
1550 Size); \
1551 TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \
1552 } while (0)
1553
1554 #define TestImplValue(Dst, Value0, Count, Size) \
1555 do { \
1556 TestImplOp(rol, Dst, Value0, Count, <<, uint, Size); \
1557 TestImplOp(shl, Dst, Value0, Count, <<, uint, Size); \
1558 TestImplOp(shr, Dst, Value0, Count, >>, uint, Size); \
1559 TestImplOp(sar, Dst, Value0, Count, >>, int, Size); \
1560 } while (0)
1561
1562 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size) \
1563 do { \
1564 TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>, \
1565 uint, Size); \
1566 TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<, \
1567 uint, Size); \
1568 } while (0)
1569
1570 #define TestImplSize(Dst, Size) \
1571 do { \
1572 TestImplValue(Dst, 0x8F, 3, Size); \
1573 TestImplValue(Dst, 0x8FFF, 7, Size); \
1574 TestImplValue(Dst, 0x8FFFF, 7, Size); \
1575 } while (0)
1576
1577 #define TestImplThreeOperandSize(Dst, Src, Size) \
1578 do { \
1579 TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size); \
1580 } while (0)
1581
1582 #define TestImpl(Dst, Src) \
1583 do { \
1584 TestImplSize(Dst, 8); \
1585 TestImplSize(Dst, 16); \
1586 TestImplThreeOperandSize(Dst, Src, 16); \
1587 TestImplSize(Dst, 32); \
1588 TestImplThreeOperandSize(Dst, Src, 32); \
1589 } while (0)
1590
1591 TestImpl(r1, r2);
1592 TestImpl(r2, r4);
1593 TestImpl(r4, r5);
1594 TestImpl(r5, r6);
1595 TestImpl(r6, r7);
1596 TestImpl(r7, r8);
1597 TestImpl(r8, r10);
1598 TestImpl(r10, r11);
1599 TestImpl(r11, r12);
1600 TestImpl(r12, r13);
1601 TestImpl(r13, r14);
1602 TestImpl(r14, r15);
1603 TestImpl(r15, r1);
1604
1605 #undef TestImpl
1606 #undef TestImplThreeOperandSize
1607 #undef TestImplSize
1608 #undef TestImplValue
1609 #undef TestImplThreeOperandValue
1610 #undef TestImplOp
1611 #undef TestImplThreeOperandOp
1612 #undef TestImplAddrCl
1613 #undef TestImplRegRegCl
1614 #undef TestImplRegCl
1615 #undef TestImplRegRegImm
1616 #undef TestImplRegImm
1617 }
1618
TEST_F(AssemblerX8664Test,Neg)1619 TEST_F(AssemblerX8664Test, Neg) {
1620 static constexpr uint32_t Mask8 = 0x000000ff;
1621 static constexpr uint32_t Mask16 = 0x0000ffff;
1622 static constexpr uint32_t Mask32 = 0xffffffff;
1623
1624 #define TestImplReg(Dst, Size) \
1625 do { \
1626 static constexpr int32_t Value = 0xFF00A543; \
1627 __ mov(IceType_i##Size, Encoded_GPR_##Dst(), \
1628 Immediate(static_cast<int##Size##_t>(Value) & Mask##Size)); \
1629 __ neg(IceType_i##Size, Encoded_GPR_##Dst()); \
1630 __ mov(IceType_i##Size, Encoded_GPR_eax(), Encoded_GPR_##Dst()); \
1631 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(Mask##Size)); \
1632 \
1633 AssembledTest test = assemble(); \
1634 test.run(); \
1635 \
1636 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
1637 test.eax()) \
1638 << "(" #Dst ", " #Size ")"; \
1639 reset(); \
1640 } while (0)
1641
1642 #define TestImplAddr(Size) \
1643 do { \
1644 static constexpr int32_t Value = 0xFF00A543; \
1645 const uint32_t T0 = allocateDword(); \
1646 __ neg(IceType_i##Size, dwordAddress(T0)); \
1647 \
1648 AssembledTest test = assemble(); \
1649 test.setDwordTo(T0, Value &Mask##Size); \
1650 test.run(); \
1651 \
1652 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \
1653 test.contentsOfDword(T0)) \
1654 << "(Addr, " #Size ")"; \
1655 reset(); \
1656 } while (0)
1657
1658 #define TestImpl(Size) \
1659 do { \
1660 TestImplAddr(Size); \
1661 TestImplReg(r1, Size); \
1662 TestImplReg(r2, Size); \
1663 TestImplReg(r3, Size); \
1664 TestImplReg(r4, Size); \
1665 TestImplReg(r5, Size); \
1666 TestImplReg(r6, Size); \
1667 TestImplReg(r7, Size); \
1668 TestImplReg(r8, Size); \
1669 TestImplReg(r10, Size); \
1670 TestImplReg(r11, Size); \
1671 TestImplReg(r12, Size); \
1672 TestImplReg(r13, Size); \
1673 TestImplReg(r14, Size); \
1674 TestImplReg(r15, Size); \
1675 } while (0)
1676
1677 TestImpl(8);
1678 TestImpl(16);
1679 TestImpl(32);
1680
1681 #undef TestImpl
1682 #undef TestImplAddr
1683 #undef TestImplReg
1684 }
1685
TEST_F(AssemblerX8664Test,Not)1686 TEST_F(AssemblerX8664Test, Not) {
1687 #define TestImpl(Dst) \
1688 do { \
1689 static constexpr uint32_t Value = 0xFF00A543; \
1690 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
1691 __ notl(Encoded_GPR_##Dst()); \
1692 \
1693 AssembledTest test = assemble(); \
1694 test.run(); \
1695 \
1696 ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")"; \
1697 reset(); \
1698 } while (0)
1699
1700 TestImpl(r1);
1701 TestImpl(r2);
1702 TestImpl(r3);
1703 TestImpl(r4);
1704 TestImpl(r5);
1705 TestImpl(r6);
1706 TestImpl(r7);
1707 TestImpl(r8);
1708 TestImpl(r10);
1709 TestImpl(r11);
1710 TestImpl(r12);
1711 TestImpl(r13);
1712 TestImpl(r14);
1713 TestImpl(r15);
1714
1715 #undef TestImpl
1716 }
1717
TEST_F(AssemblerX8664Test,Bswap)1718 TEST_F(AssemblerX8664Test, Bswap) {
1719 #define TestImpl(Dst) \
1720 do { \
1721 static constexpr uint32_t Value = 0xFF00A543; \
1722 static constexpr uint32_t Expected = 0x43A500FF; \
1723 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value)); \
1724 __ bswap(IceType_i32, Encoded_GPR_##Dst()); \
1725 \
1726 AssembledTest test = assemble(); \
1727 test.run(); \
1728 \
1729 ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")"; \
1730 reset(); \
1731 } while (0)
1732
1733 TestImpl(r1);
1734 TestImpl(r2);
1735 TestImpl(r3);
1736 TestImpl(r4);
1737 TestImpl(r5);
1738 TestImpl(r6);
1739 TestImpl(r7);
1740 TestImpl(r8);
1741 TestImpl(r10);
1742 TestImpl(r11);
1743 TestImpl(r12);
1744 TestImpl(r13);
1745 TestImpl(r14);
1746 TestImpl(r15);
1747
1748 #undef TestImpl
1749 }
1750
TEST_F(AssemblerX8664Test,Bt)1751 TEST_F(AssemblerX8664Test, Bt) {
1752 #define TestImpl(Dst, Value0, Src, Value1) \
1753 do { \
1754 static constexpr char TestString[] = \
1755 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")"; \
1756 static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0; \
1757 \
1758 __ mov(IceType_i32, Encoded_GPR_##Dst(), Immediate(Value0)); \
1759 __ mov(IceType_i32, Encoded_GPR_##Src(), Immediate(Value1)); \
1760 __ bt(Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1761 __ setcc(Cond::Br_b, ByteRegister::Encoded_8_Reg_al); \
1762 __ And(IceType_i32, Encoded_GPR_eax(), Immediate(0xFFu)); \
1763 \
1764 AssembledTest test = assemble(); \
1765 test.run(); \
1766 \
1767 ASSERT_EQ(Expected, test.eax()) << TestString; \
1768 reset(); \
1769 } while (0)
1770
1771 TestImpl(r1, 0x08000000, r2, 27u);
1772 TestImpl(r2, 0x08000000, r3, 23u);
1773 TestImpl(r3, 0x00000000, r4, 1u);
1774 TestImpl(r4, 0x08000300, r5, 9u);
1775 TestImpl(r5, 0x08000300, r6, 10u);
1776 TestImpl(r6, 0x7FFFEFFF, r7, 13u);
1777 TestImpl(r7, 0x08000000, r8, 27u);
1778 TestImpl(r8, 0x08000000, r10, 23u);
1779 TestImpl(r10, 0x00000000, r11, 1u);
1780 TestImpl(r11, 0x08000300, r12, 9u);
1781 TestImpl(r12, 0x08000300, r13, 10u);
1782 TestImpl(r13, 0x7FFFEFFF, r14, 13u);
1783 TestImpl(r14, 0x08000000, r15, 27u);
1784 TestImpl(r15, 0x08000000, r1, 23u);
1785
1786 #undef TestImpl
1787 }
1788
1789 template <uint32_t Value, uint32_t Bits> class BitScanHelper {
1790 BitScanHelper() = delete;
1791
1792 public:
1793 static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32");
1794 using ValueType =
1795 typename std::conditional<Bits == 16, uint16_t, uint32_t>::type;
1796
1797 private:
BitIndex(bool Forward,ValueType Index)1798 static constexpr ValueType BitIndex(bool Forward, ValueType Index) {
1799 return (Value == 0)
1800 ? BitScanHelper<Value, Bits>::NoBitSet
1801 : (Value & (1u << Index)
1802 ? Index
1803 : BitIndex(Forward, (Forward ? Index + 1 : Index - 1)));
1804 }
1805
1806 public:
1807 static constexpr ValueType NoBitSet = static_cast<ValueType>(-1);
1808 static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0);
1809 static constexpr ValueType bsr =
1810 BitIndex(/*Forward*/ false, /*Index=*/Bits - 1);
1811 };
1812
TEST_F(AssemblerX8664Test,BitScanOperations)1813 TEST_F(AssemblerX8664Test, BitScanOperations) {
1814 #define TestImplRegReg(Inst, Dst, Src, Value1, Size) \
1815 do { \
1816 static constexpr char TestString[] = \
1817 "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")"; \
1818 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
1819 const uint32_t ZeroFlag = allocateDword(); \
1820 __ mov(IceType_i##Size, Encoded_GPR_##Src(), Immediate(Value1)); \
1821 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), Encoded_GPR_##Src()); \
1822 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
1823 \
1824 AssembledTest test = assemble(); \
1825 test.setDwordTo(ZeroFlag, 0u); \
1826 test.run(); \
1827 \
1828 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
1829 test.contentsOfDword(ZeroFlag)) \
1830 << TestString; \
1831 if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) { \
1832 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1833 } \
1834 reset(); \
1835 } while (0)
1836
1837 #define TestImplRegAddr(Inst, Dst, Value1, Size) \
1838 do { \
1839 static constexpr char TestString[] = \
1840 "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")"; \
1841 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \
1842 const uint32_t T0 = allocateDword(); \
1843 const uint32_t ZeroFlag = allocateDword(); \
1844 __ Inst(IceType_i##Size, Encoded_GPR_##Dst(), dwordAddress(T0)); \
1845 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
1846 \
1847 AssembledTest test = assemble(); \
1848 test.setDwordTo(T0, Value1); \
1849 test.setDwordTo(ZeroFlag, 0u); \
1850 test.run(); \
1851 \
1852 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \
1853 test.contentsOfDword(ZeroFlag)) \
1854 << TestString; \
1855 if (Expected != BitScanHelper<Value1, Size>::NoBitSet) { \
1856 ASSERT_EQ(Expected, test.Dst()) << TestString; \
1857 } \
1858 reset(); \
1859 } while (0)
1860
1861 #define TestImplSize(Dst, Src, Value1, Size) \
1862 do { \
1863 TestImplRegReg(bsf, Dst, Src, Value1, Size); \
1864 TestImplRegAddr(bsf, Dst, Value1, Size); \
1865 TestImplRegReg(bsr, Dst, Src, Value1, Size); \
1866 TestImplRegAddr(bsf, Dst, Value1, Size); \
1867 } while (0)
1868
1869 #define TestImplValue(Dst, Src, Value1) \
1870 do { \
1871 TestImplSize(Dst, Src, Value1, 16); \
1872 TestImplSize(Dst, Src, Value1, 32); \
1873 } while (0)
1874
1875 #define TestImpl(Dst, Src) \
1876 do { \
1877 TestImplValue(Dst, Src, 0x80000001); \
1878 TestImplValue(Dst, Src, 0x00000000); \
1879 TestImplValue(Dst, Src, 0x80001000); \
1880 TestImplValue(Dst, Src, 0x00FFFF00); \
1881 } while (0)
1882
1883 TestImpl(r1, r2);
1884 TestImpl(r2, r3);
1885 TestImpl(r3, r4);
1886 TestImpl(r4, r5);
1887 TestImpl(r5, r6);
1888 TestImpl(r6, r7);
1889 TestImpl(r7, r8);
1890 TestImpl(r8, r10);
1891 TestImpl(r10, r11);
1892 TestImpl(r11, r12);
1893 TestImpl(r12, r13);
1894 TestImpl(r13, r14);
1895 TestImpl(r14, r15);
1896 TestImpl(r15, r1);
1897
1898 #undef TestImpl
1899 #undef TestImplValue
1900 #undef TestImplSize
1901 #undef TestImplRegAddr
1902 #undef TestImplRegReg
1903 }
1904
1905 } // end of anonymous namespace
1906 } // end of namespace Test
1907 } // end of namespace X8664
1908 } // end of namespace Ice
1909