Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: unittest/AssemblerX8664/GPRArith.cpp

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

Powered by Google App Engine
This is Rietveld 408576698