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