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