1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include <sys/mman.h>
20 
21 #include <cstring>
22 #include <iterator>
23 #include <string>
24 
25 #include "berberis/assembler/machine_code.h"
26 #include "berberis/assembler/rv32e.h"
27 #include "berberis/assembler/rv32i.h"
28 #include "berberis/assembler/rv64i.h"
29 #include "berberis/assembler/x86_32.h"
30 #include "berberis/assembler/x86_64.h"
31 #include "berberis/base/bit_util.h"
32 #include "berberis/base/logging.h"
33 #include "berberis/test_utils/scoped_exec_region.h"
34 
35 #if defined(__i386__)
36 using CodeEmitter = berberis::x86_32::Assembler;
37 #elif defined(__amd64__)
38 using CodeEmitter = berberis::x86_64::Assembler;
39 #elif defined(__riscv)
40 using CodeEmitter = berberis::rv64::Assembler;
41 #else
42 #error "Unsupported platform"
43 #endif
44 
45 namespace berberis {
46 
47 enum class CPUArch {
48   kX86_64,
49   kRiscv64,
50 };
51 
Callee()52 int Callee() {
53   return 239;
54 }
55 
FloatFunc(float f1,float f2)56 float FloatFunc(float f1, float f2) {
57   return f1 - f2;
58 }
59 
IsInstructionEqual(std::string code_str1,std::string code_str2,uint32_t insn,uint32_t insn_size)60 inline bool IsInstructionEqual(std::string code_str1,
61                                std::string code_str2,
62                                uint32_t insn,
63                                uint32_t insn_size) {
64   return code_str1.compare(
65              insn * (insn_size + 1), insn_size, code_str2, insn * (insn_size + 1), insn_size) == 0;
66 }
67 
68 template <typename ParcelInt>
CompareCode(const ParcelInt * code_template_begin,const ParcelInt * code_template_end,const MachineCode & code,CPUArch arch)69 inline bool CompareCode(const ParcelInt* code_template_begin,
70                         const ParcelInt* code_template_end,
71                         const MachineCode& code,
72                         CPUArch arch) {
73   if ((code_template_end - code_template_begin) * sizeof(ParcelInt) != code.install_size()) {
74     ALOGE("Code size mismatch: %zd != %u",
75           (code_template_end - code_template_begin) * static_cast<unsigned>(sizeof(ParcelInt)),
76           code.install_size());
77     return false;
78   }
79 
80   if (memcmp(code_template_begin, code.AddrAs<uint8_t>(0), code.install_size()) != 0) {
81     ALOGE("Code mismatch");
82     MachineCode code2;
83     code2.AddSequence(code_template_begin, code_template_end - code_template_begin);
84     std::string code_str1, code_str2;
85     uint32_t insn_size = 0;
86     switch (arch) {
87       case CPUArch::kRiscv64:
88         insn_size = 8;
89         code.AsString(&code_str1, InstructionSize::FourBytes);
90         code2.AsString(&code_str2, InstructionSize::FourBytes);
91         break;
92       case CPUArch::kX86_64:
93         insn_size = 2;
94         code.AsString(&code_str1, InstructionSize::OneByte);
95         code2.AsString(&code_str2, InstructionSize::OneByte);
96         break;
97     }
98     CHECK_EQ(code_str1.size() % (insn_size + 1), 0);
99     CHECK_EQ(code_str2.size() % (insn_size + 1), 0);
100     uint32_t number_of_instructions = code_str1.size() / (insn_size + 1);
101     // Skip identical part.
102     uint32_t insn = 0;
103     while (insn < number_of_instructions &&
104            IsInstructionEqual(code_str1, code_str2, insn, insn_size)) {
105       insn++;
106     }
107     for (uint32_t i = insn; i < insn + 20 && i < number_of_instructions; i++) {
108       ALOGE("Assembler generated: %s, should be %s\n",
109             code_str1.substr(i * (insn_size + 1), insn_size).c_str(),
110             code_str2.substr(i * (insn_size + 1), insn_size).c_str());
111     }
112 
113     return false;
114   }
115   return true;
116 }
117 
118 namespace rv32 {
119 
AssemblerTest()120 bool AssemblerTest() {
121   MachineCode code;
122   Assembler assembler(&code);
123   Assembler::Label data_begin, data_end, label;
124   assembler.Bind(&data_begin);
125   // We test loads and stores twice to ensure that both positive and negative immediates are
126   // present both in auipc and in the follow-up load/store instructions.
127   assembler.Fld(Assembler::f1, data_end, Assembler::x2);
128   assembler.Flw(Assembler::f3, data_end, Assembler::x4);
129   assembler.Fsd(Assembler::f5, data_end, Assembler::x6);
130   assembler.Fsw(Assembler::f7, data_end, Assembler::x8);
131   assembler.Lb(Assembler::x9, data_end);
132   assembler.Lbu(Assembler::x10, data_end);
133   assembler.Lh(Assembler::x11, data_end);
134   assembler.Lhu(Assembler::x12, data_end);
135   assembler.Lw(Assembler::x13, data_end);
136   assembler.Sb(Assembler::x14, data_end, Assembler::x15);
137   assembler.Sh(Assembler::x16, data_end, Assembler::x17);
138   assembler.Sw(Assembler::x18, data_end, Assembler::x19);
139   assembler.La(Assembler::x20, data_end);
140   assembler.Bcc(Assembler::Condition::kEqual, Assembler::x1, Assembler::x2, label);
141   assembler.Bcc(Assembler::Condition::kNotEqual, Assembler::x3, Assembler::x4, label);
142   assembler.Bcc(Assembler::Condition::kLess, Assembler::x5, Assembler::x6, label);
143   assembler.Bcc(Assembler::Condition::kGreaterEqual, Assembler::x7, Assembler::x8, label);
144   assembler.Bcc(Assembler::Condition::kBelow, Assembler::x9, Assembler::x10, label);
145   assembler.Bcc(Assembler::Condition::kAboveEqual, Assembler::x11, Assembler::x12, label);
146   assembler.Jal(Assembler::x1, label);
147   assembler.Add(Assembler::x1, Assembler::x2, Assembler::x3);
148   assembler.Addi(Assembler::x1, Assembler::x2, 42);
149   assembler.Bind(&label);
150   // Jalr have two alternate forms.
151   assembler.Jalr(Assembler::x1, Assembler::x2, 42);
152   assembler.Jalr(Assembler::x3, {.base = Assembler::x4, .disp = 42});
153   assembler.Sw(Assembler::x1, {.base = Assembler::x2, .disp = 42});
154   assembler.Jal(Assembler::x2, label);
155   assembler.Beq(Assembler::x1, Assembler::x2, label);
156   assembler.Bne(Assembler::x3, Assembler::x4, label);
157   assembler.Blt(Assembler::x5, Assembler::x6, label);
158   assembler.Bge(Assembler::x7, Assembler::x8, label);
159   assembler.Bltu(Assembler::x9, Assembler::x10, label);
160   assembler.Bgeu(Assembler::x11, Assembler::x12, label);
161   assembler.Csrrc(Assembler::x1, Assembler::Csr::kVl, Assembler::x2);
162   assembler.Csrrs(Assembler::x3, Assembler::Csr::kVtype, Assembler::x4);
163   assembler.Csrrw(Assembler::x5, Assembler::Csr::kVlenb, Assembler::x6);
164   assembler.Slli(Assembler::x1, Assembler::x2, 3);
165   assembler.Srai(Assembler::x4, Assembler::x5, 6);
166   assembler.Srli(Assembler::x7, Assembler::x8, 9);
167   assembler.FcvtSW(Assembler::f1, Assembler::x2, Assembler::Rounding::kRmm);
168   assembler.FcvtSWu(Assembler::f3, Assembler::x4);
169   assembler.FcvtWS(Assembler::x1, Assembler::f2, Assembler::Rounding::kRmm);
170   assembler.FcvtWuS(Assembler::x3, Assembler::f4);
171   assembler.FsqrtS(Assembler::f1, Assembler::f2, Assembler::Rounding::kRmm);
172   assembler.FsqrtD(Assembler::f3, Assembler::f4);
173   assembler.PrefetchI({.base = Assembler::x1, .disp = 32});
174   assembler.PrefetchR({.base = Assembler::x2, .disp = 64});
175   assembler.PrefetchW({.base = Assembler::x3, .disp = 96});
176   assembler.Li(Assembler::x15, static_cast<int32_t>(0xaf));
177   assembler.Seqz(Assembler::x20, Assembler::x10);
178   assembler.Snez(Assembler::x2, Assembler::x9);
179   assembler.Sltz(Assembler::x30, Assembler::x1);
180   assembler.Sgtz(Assembler::x25, Assembler::x16);
181   assembler.J(0x42);
182   assembler.Jal(-0x26);
183   assembler.Jr(Assembler::x19);
184   assembler.Jalr(Assembler::x7);
185   // Move target position for more than 2048 bytes down to ensure auipc would use non-zero
186   // immediate.
187   for (size_t index = 138; index < 1200; ++index) {
188     assembler.TwoByte(uint16_t{0});
189   }
190   assembler.Fld(Assembler::f1, data_begin, Assembler::x2);
191   assembler.Flw(Assembler::f3, data_begin, Assembler::x4);
192   assembler.Fsd(Assembler::f5, data_begin, Assembler::x6);
193   assembler.Fsw(Assembler::f7, data_begin, Assembler::x8);
194   assembler.Lb(Assembler::x9, data_begin);
195   assembler.Lbu(Assembler::x10, data_begin);
196   assembler.Lh(Assembler::x11, data_begin);
197   assembler.Lhu(Assembler::x12, data_begin);
198   assembler.Lw(Assembler::x13, data_begin);
199   assembler.Sb(Assembler::x14, data_begin, Assembler::x15);
200   assembler.Sh(Assembler::x16, data_begin, Assembler::x17);
201   assembler.Sw(Assembler::x18, data_begin, Assembler::x19);
202   assembler.La(Assembler::x20, data_begin);
203   assembler.Bind(&data_end);
204   assembler.Bexti(Assembler::x16, Assembler::x1, 20);
205   assembler.Rori(Assembler::x5, Assembler::x3, 5);
206   assembler.Finalize();
207 
208   // clang-format off
209   static const uint16_t kCodeTemplate[] = {
210     0x1117, 0x0000,     // begin: auipc   x2, 4096
211     0x3087, 0x9c81,     //        fld     f1, -1592(x2)
212     0x1217, 0x0000,     //        auipc   x4, 4096
213     0x2187, 0x9c02,     //        flw     f3, -1600(x4)
214     0x1317, 0x0000,     //        auipc   x6, 4096
215     0x3c27, 0x9a53,     //        fsd     f5, -1608(x6)
216     0x1417, 0x0000,     //        auipc   x8, 4096
217     0x2827, 0x9a74,     //        fsw     f7, -1616(x8)
218     0x1497, 0x0000,     //        auipc   x9, 4096
219     0x8483, 0x9a84,     //        lb      x9, -1624(x9)
220     0x1517, 0x0000,     //        auipc   x10, 4096
221     0x4503, 0x9a05,     //        lbu     x10, -1632(x10)
222     0x1597, 0x0000,     //        auipc   x11, 4096
223     0x9583, 0x9985,     //        lh      x11, -1640(x11)
224     0x1617, 0x0000,     //        auipc   x12, 4096
225     0x5603, 0x9906,     //        lhu     x12, -1648(x12)
226     0x1697, 0x0000,     //        auipc   x13, 4096
227     0xa683, 0x9886,     //        lw      x13, -1656(x13)
228     0x1797, 0x0000,     //        auipc   x15, 4096
229     0x8023, 0x98e7,     //        sb      x14, -1664(x15)
230     0x1897, 0x0000,     //        auipc   x17, 4096
231     0x9c23, 0x9708,     //        sh      x16, -1672(x17)
232     0x1997, 0x0000,     //        auipc   x19, 4096
233     0xa823, 0x9729,     //        sw      x18, -1680(x19)
234     0x1a17, 0x0000,     //        auipc   x20, 4096
235     0x0a13, 0x968a,     //        addi    x20, x20, -1688
236     0x8263, 0x0220,     //        beq     x1, x2, label
237     0x9063, 0x0241,     //        bne     x3, x4, label
238     0xce63, 0x0062,     //        blt     x5, x6, label
239     0xdc63, 0x0083,     //        bge     x7, x8, label
240     0xea63, 0x00a4,     //        bltu    x9, x10, label
241     0xf863, 0x00c5,     //        bgeu    x11, x12, label
242     0x00ef, 0x00c0,     //        jal     x1, label
243     0x00b3, 0x0031,     //        add     x1, x2, x3
244     0x0093, 0x02a1,     //        addi    x1, x2, 42
245     0x00e7, 0x02a1,     // label: jalr    x1, x2, 42
246     0x01e7, 0x02a2,     //        jalr    x3, 42(x4)
247     0x2523, 0x0211,     //        sw      x1, 42(x2)
248     0xf16f, 0xff5f,     //        jal     x2, label
249     0x88e3, 0xfe20,     //        beq     x1, x2, label
250     0x96e3, 0xfe41,     //        bne     x3, x4, label
251     0xc4e3, 0xfe62,     //        blt     x5, x6, label
252     0xd2e3, 0xfe83,     //        bge     x7, x8, label
253     0xe0e3, 0xfea4,     //        bltu    x9, x10, label
254     0xfee3, 0xfcc5,     //        bgeu    x11, x12, label
255     0x30f3, 0xc201,     //        csrrc   x1, vl, x2
256     0x21f3, 0xc212,     //        csrrs   x3, vtype, x4
257     0x12f3, 0xc223,     //        csrrw   x5, vlenb, x6
258     0x1093, 0x0031,     //        slli    x1, x2, 3
259     0xd213, 0x4062,     //        srai    x4, x5, 6
260     0x5393, 0x0094,     //        srli    x7, x8, 9
261     0x40d3, 0xd001,     //        fcvt.s.w f1, x2, rmm
262     0x71d3, 0xd012,     //        fcvt.s.wu f3, x4
263     0x40d3, 0xc001,     //        fcvt.w.s x1, f2, rmm
264     0x71d3, 0xc012,     //        fcvt.wu.s x3, f4
265     0x40d3, 0x5801,     //        fsqrt.s f1, f2, rmm
266     0x71d3, 0x5a02,     //        fsqrt.d f3, f4
267     0xe013, 0x0200,     //        prefetch.i 32(x1)
268     0x6013, 0x0411,     //        prefetch.r 64(x2)
269     0xe013, 0x0631,     //        prefetch.w 96(x3)
270     0x0793, 0x0af0,     //        addi x15, x15, 0xaf
271     0x3a13, 0x0015,     //        sltiu x20, x10, 1
272     0x3133, 0x0090,     //        sltu x2, x0, x9
273     0xaf33, 0x0000,     //        slt x30, x1, x0
274     0x2cb3, 0x0100,     //        slt x25, x0, x16
275     0x006f, 0x0420,     //        jal zero, 0x42
276     0xf0ef, 0xfdbf,     //        jal x1, -0x26
277     0x8067, 0x0009,     //        jalr zero, x19, 0
278     0x80e7, 0x0003,     //        jalr x1, x7, 0
279     [ 138 ... 1199 ] = 0,//       padding
280     0xf117, 0xffff,     //        auipc   x2, -4096
281     0x3087, 0x6a01,     //        fld     f1,1696(x2)
282     0xf217, 0xffff,     //        auipc   x4, -4096
283     0x2187, 0x6982,     //        flw     f3,1688(x4)
284     0xf317, 0xffff,     //        auipc   x6, -4096
285     0x3827, 0x6853,     //        fsd     f5,1680(x6)
286     0xf417, 0xffff,     //        auipc   x8, -4096
287     0x2427, 0x6874,     //        fsw     f7,1672(x8)
288     0xf497, 0xffff,     //        auipc   x9, -4096
289     0x8483, 0x6804,     //        lb      x9,1664(x9)
290     0xf517, 0xffff,     //        auipc   x10, -4096
291     0x4503, 0x6785,     //        lbu     x10,1656(x10)
292     0xf597, 0xffff,     //        auipc   x11, -4096
293     0x9583, 0x6705,     //        lh      x11,1648(x11)
294     0xf617, 0xffff,     //        auipc   x12, -4096
295     0x5603, 0x6686,     //        lhu     x12,1640(x12)
296     0xf697, 0xffff,     //        auipc   x13, -4096
297     0xa683, 0x6606,     //        lw      x13,1632(x13)
298     0xf797, 0xffff,     //        auipc   x15, -4096
299     0x8c23, 0x64e7,     //        sb      x14,1624(x15)
300     0xf897, 0xffff,     //        auipc   x17, -4096
301     0x9823, 0x6508,     //        sh      x16,1616(x17)
302     0xf997, 0xffff,     //        auipc   x19, -4096
303     0xa423, 0x6529,     //        sw      x18,1608(x19)
304     0xfa17, 0xffff,     //        auipc   x20, -4096
305     0x0a13, 0x640a,     //        addi    x20,x20,1600
306     0xd813, 0x4940,     //        bexti    x16,x1,20
307     0xd293, 0x6051,     //        rori    x5, x3, 5
308   };                    // end:
309   // clang-format on
310 
311   return CompareCode(std::begin(kCodeTemplate), std::end(kCodeTemplate), code, CPUArch::kRiscv64);
312 }
313 
314 }  // namespace rv32
315 
316 namespace rv64 {
317 
AssemblerTest()318 bool AssemblerTest() {
319   MachineCode code;
320   Assembler assembler(&code);
321   Assembler::Label data_begin, data_end;
322   assembler.Bind(&data_begin);
323   // We test loads and stores twice to ensure that both positive and negative immediates are
324   // present both in auipc and in the follow-up load/store instructions.
325   assembler.Ld(Assembler::x1, data_end);
326   assembler.Lwu(Assembler::x2, data_end);
327   assembler.Sd(Assembler::x3, data_end, Assembler::x4);
328   assembler.Bcc(Assembler::Condition::kAlways, Assembler::x1, Assembler::x2, 48);
329   assembler.Bcc(Assembler::Condition::kEqual, Assembler::x3, Assembler::x4, 44);
330   assembler.Bcc(Assembler::Condition::kNotEqual, Assembler::x5, Assembler::x6, 40);
331   assembler.Bcc(Assembler::Condition::kLess, Assembler::x7, Assembler::x8, 36);
332   assembler.Bcc(Assembler::Condition::kGreaterEqual, Assembler::x9, Assembler::x10, 32);
333   assembler.Bcc(Assembler::Condition::kBelow, Assembler::x11, Assembler::x12, 28);
334   assembler.Bcc(Assembler::Condition::kAboveEqual, Assembler::x13, Assembler::x14, 24);
335   assembler.Jal(Assembler::x1, 20);
336   assembler.Add(Assembler::x1, Assembler::x2, Assembler::x3);
337   assembler.Addw(Assembler::x1, Assembler::x2, Assembler::x3);
338   assembler.Addi(Assembler::x1, Assembler::x2, 42);
339   assembler.Addiw(Assembler::x1, Assembler::x2, 42);
340   // Jalr have two alternate forms.
341   assembler.Jalr(Assembler::x1, Assembler::x2, 42);
342   assembler.Jalr(Assembler::x3, {.base = Assembler::x4, .disp = 42});
343   assembler.Sw(Assembler::x1, {.base = Assembler::x2, .disp = 42});
344   assembler.Sd(Assembler::x3, {.base = Assembler::x4, .disp = 42});
345   assembler.Jal(Assembler::x2, -16);
346   assembler.Beq(Assembler::x1, Assembler::x2, -20);
347   assembler.Bne(Assembler::x3, Assembler::x4, -24);
348   assembler.Blt(Assembler::x5, Assembler::x6, -28);
349   assembler.Bge(Assembler::x7, Assembler::x8, -32);
350   assembler.Bltu(Assembler::x9, Assembler::x10, -36);
351   assembler.Bgeu(Assembler::x11, Assembler::x12, -40);
352   assembler.Bcc(Assembler::Condition::kAlways, Assembler::x13, Assembler::x14, -44);
353   assembler.Csrrc(Assembler::x1, Assembler::Csr::kVl, 2);
354   assembler.Csrrs(Assembler::x3, Assembler::Csr::kVtype, 4);
355   assembler.Csrrw(Assembler::x5, Assembler::Csr::kVlenb, 6);
356   assembler.Csrrci(Assembler::x7, Assembler::Csr::kVl, 8);
357   assembler.Csrrsi(Assembler::x9, Assembler::Csr::kVtype, 10);
358   assembler.Csrrwi(Assembler::x11, Assembler::Csr::kVlenb, 12);
359   assembler.Slliw(Assembler::x1, Assembler::x2, 3);
360   assembler.Sraiw(Assembler::x4, Assembler::x5, 6);
361   assembler.Srliw(Assembler::x7, Assembler::x8, 9);
362   assembler.FcvtDL(Assembler::f1, Assembler::x2, Assembler::Rounding::kRmm);
363   assembler.FcvtDLu(Assembler::f3, Assembler::x4);
364   assembler.FcvtLD(Assembler::x1, Assembler::f2, Assembler::Rounding::kRmm);
365   assembler.FcvtLuD(Assembler::x3, Assembler::f4);
366   assembler.FsqrtS(Assembler::f1, Assembler::f2, Assembler::Rounding::kRmm);
367   assembler.FsqrtD(Assembler::f3, Assembler::f4);
368   assembler.PrefetchI({.base = Assembler::x1, .disp = 32});
369   assembler.PrefetchR({.base = Assembler::x2, .disp = 64});
370   assembler.PrefetchW({.base = Assembler::x3, .disp = 96});
371   assembler.Li(Assembler::x10, static_cast<int64_t>(0xaaaa'0aa0'aaa0'0aaa));
372   assembler.Ret();
373   assembler.Call(data_end);
374   assembler.Tail(data_end);
375   assembler.Bgt(Assembler::x4, Assembler::x0, data_end);
376   assembler.Bgtu(Assembler::x2, Assembler::x20, data_end);
377   assembler.Ble(Assembler::x1, Assembler::x30, data_end);
378   assembler.Bleu(Assembler::x8, Assembler::x16, data_end);
379   assembler.Beqz(Assembler::x5, data_end);
380   assembler.Bnez(Assembler::x4, data_end);
381   assembler.Blez(Assembler::x2, data_end);
382   assembler.Bgez(Assembler::x3, data_end);
383   assembler.Bltz(Assembler::x9, data_end);
384   assembler.Bgtz(Assembler::x12, data_end);
385   // Move target position for more than 2048 bytes down to ensure auipc would use non-zero
386   // immediate.
387   for (size_t index = 142; index < 1200; ++index) {
388     assembler.TwoByte(uint16_t{0});
389   }
390   assembler.Ld(Assembler::x1, data_begin);
391   assembler.Lwu(Assembler::x2, data_begin);
392   assembler.Sd(Assembler::x3, data_begin, Assembler::x4);
393   assembler.Bind(&data_end);
394   assembler.SextW(Assembler::x15, Assembler::x12);
395   assembler.AddUW(Assembler::x14, Assembler::x22, Assembler::x29);
396   assembler.ZextW(Assembler::x13, Assembler::x21);
397   assembler.Sh3add(Assembler::x13, Assembler::x9, Assembler::x10);
398   assembler.Bexti(Assembler::x16, Assembler::x1, 53);
399   assembler.Rori(Assembler::x22, Assembler::x30, 43);
400   assembler.Roriw(Assembler::x29, Assembler::x2, 30);
401   assembler.Ror(Assembler::x14, Assembler::x1, Assembler::x10);
402   assembler.Rorw(Assembler::x25, Assembler::x5, Assembler::x4);
403   assembler.Not(Assembler::x10, Assembler::x4);
404   assembler.Neg(Assembler::x11, Assembler::x3);
405   assembler.Negw(Assembler::x12, Assembler::x2);
406   assembler.SextB(Assembler::x22, Assembler::x7);
407   assembler.SextH(Assembler::x23, Assembler::x8);
408   assembler.Finalize();
409 
410   // clang-format off
411   static const uint16_t kCodeTemplate[] = {
412     0x1097, 0x0000,     // begin: auipc   x1, 4096
413     0xb083, 0x9780,     //        ld,     x1, -1672(x1)
414     0x1117, 0x0000,     //        auipc   x2, 4096
415     0x6103, 0x9701,     //        lwu     x2,-1680(x2)
416     0x1217, 0x0000,     //        auipc   x4, 4096
417     0x3423, 0x9632,     //        sd      x3,-1688(x4)
418     0x006f, 0x0300,     //        jal     x0, label
419     0x8663, 0x0241,     //        beq     x1, x2, label
420     0x9463, 0x0262,     //        bne     x3, x4, label
421     0xc263, 0x0283,     //        blt     x5, x6, label
422     0xd063, 0x02a4,     //        bge     x7, x8, label
423     0xee63, 0x00c5,     //        bltu    x9, x10, label
424     0xfc63, 0x00e6,     //        bgeu    x11, x12, label
425     0x00ef, 0x0140,     //        jal     x1, label
426     0x00b3, 0x0031,     //        add     x1, x2, x3
427     0x00bb, 0x0031,     //        addw    x1, x2, x3
428     0x0093, 0x02a1,     //        addi    x1, x2, 42
429     0x009b, 0x02a1,     //        addiw   x1, x2, 42
430     0x00e7, 0x02a1,     // label: jalr    x1, x2, 42
431     0x01e7, 0x02a2,     //        jalr    x3, 42(x4)
432     0x2523, 0x0211,     //        sw      x1, 42(x2)
433     0x3523, 0x0232,     //        sd      x3, 42(x4)
434     0xf16f, 0xff1f,     //        jal     x2, label
435     0x86e3, 0xfe20,     //        beq     x1, x2, label
436     0x94e3, 0xfe41,     //        bne     x3, x4, label
437     0xc2e3, 0xfe62,     //        blt     x5, x6, label
438     0xd0e3, 0xfe83,     //        bge     x7, x8, label
439     0xeee3, 0xfca4,     //        bltu    x9, x10, label
440     0xfce3, 0xfcc5,     //        bgeu    x11, x12, label
441     0xf06f, 0xfd5f,     //        jal     x0, label
442     0x70f3, 0xc201,     //        csrrc   x1, vl, 2
443     0x61f3, 0xc212,     //        csrrs   x3, vtype, 4
444     0x52f3, 0xc223,     //        csrrw   x5, vlenb, 6
445     0x73f3, 0xc204,     //        csrrci  x7, vl, 8
446     0x64f3, 0xc215,     //        csrrsi  x9, vtype, 10
447     0x55f3, 0xc226,     //        csrrwi  x11, vlenb, 12
448     0x109b, 0x0031,     //        slliw   x1, x2, 3
449     0xd21b, 0x4062,     //        sraiw   x4, x5, 6
450     0x539b, 0x0094,     //        srliw   x7, x8, 9
451     0x40d3, 0xd221,     //        fcvt.d.l f1, x2, rmm
452     0x71d3, 0xd232,     //        fcvt.d.lu f3, x4
453     0x40d3, 0xc221,     //        fcvt.l.d x1, f2, rmm
454     0x71d3, 0xc232,     //        fcvt.lu.d x3, f4
455     0x40d3, 0x5801,     //        fsqrt.s f1, f2, rmm
456     0x71d3, 0x5a02,     //        fsqrt.d f3, f4
457     0xe013, 0x0200,     //        prefetch.i 32(x1)
458     0x6013, 0x0411,     //        prefetch.r 64(x2)
459     0xe013, 0x0631,     //        prefetch.w 96(x3)
460     0x5537,0xfd55,      //        lui a0, 0xfd555
461     0x0513, 0x0555,     //        addi a0, a0, 85
462     0x1513, 0x00d5,     //        slli a0, a0, 0xd
463     0x0513, 0x0ab5,     //        addi a0, a0, 171
464     0x1513, 0x00c5,     //        slli a0, a0, 0xc
465     0x0513, 0xa015,     //        addi a0, a0, -1535
466     0x1513, 0x00c5,     //        slli a0, a0, 0xc
467     0x0513, 0xaaa5,     //        addi a0,a0,-1366
468     0x8067, 0x0000,     //        ret
469     0x1317, 0x0000,     //        auipc x6, 0x1
470     0x00e7, 0x8943,     //        jalr x1, x6, -1900
471     0x1317, 0x0000,     //        auipc x6, 0x1
472     0x0067, 0x88c3,     //        jalr x0, x6, -1908
473     0x42e3, 0x0840,     //        blt x0, x4, 0x884
474     0x60e3, 0x082a,     //        bltu x20, x2, 0x880
475     0x5ee3, 0x061f,     //        bge x30, x1, 0x87c
476     0x7ce3, 0x0688,     //        bgeu x16, x8, 0x878
477     0x8ae3, 0x0602,     //        beq x5, 0x874
478     0x18e3, 0x0602,     //        bne x4, 0x870
479     0x56e3, 0x0620,     //        ble x2, 0x86c
480     0xd4e3, 0x0601,     //        bge x3, 0x868
481     0xc2e3, 0x0604,     //        blt x9, 0x864
482     0x40e3, 0x06c0,     //        bgt x12, 0x860
483     [ 142 ... 1199 ] = 0,//        padding
484     0xf097, 0xffff,     //        auipc   x1, -4096
485     0xb083, 0x6a00,     //        ld      x1, 1696(x1)
486     0xf117, 0xffff,     //        auipc   x2, -4096
487     0x6103, 0x6981,     //        lwu     x2, 1688(x2)
488     0xf217, 0xffff,     //        auipc   x4, -4096
489     0x3823, 0x6832,     //        sd      x3, 1680(x4)
490     0x079b, 0x0006,     //        addi.w x15, x12, 0
491     0x073b, 0x09db,     //        add.uw x14, x22, x29
492     0x86bb, 0x080a,     //        add.uw x13, x21, zero
493     0xe6b3, 0x20a4,     //        sh3add x13, x9, x10
494     0xd813, 0x4b50,     //        bexti x16, x1, 53
495     0x5b13, 0x62bf,     //        rori x22, x30, 43
496     0x5e9b, 0x61e1,     //        roriw x29, x2, 30
497     0xd733, 0x60a0,     //        ror x14, x1, x10
498     0xdcbb, 0x6042,     //        rorw x25, x5, x4
499     0x4513, 0xfff2,     //        xori x10, x4, -1
500     0x05b3, 0x4030,     //        sub x11, zero, x3
501     0x063b, 0x4020,     //        subw x12, zero, x2
502     0x9b13, 0x6043,     //        sext.b x22, x7
503     0x1b93, 0x6054,     //        sext.h x23, x8
504   };                    // end:
505   // clang-format on
506 
507   return CompareCode(std::begin(kCodeTemplate), std::end(kCodeTemplate), code, CPUArch::kRiscv64);
508 }
509 
510 }  // namespace rv64
511 
512 namespace x86_32 {
513 
AssemblerTest()514 bool AssemblerTest() {
515   MachineCode code;
516   Assembler assembler(&code);
517   assembler.Movl(Assembler::eax, {.base = Assembler::esp, .disp = 4});
518   assembler.CmpXchgl({.base = Assembler::esp, .disp = 4}, Assembler::eax);
519   assembler.Subl(Assembler::esp, 16);
520   assembler.Movl({.base = Assembler::esp}, Assembler::eax);
521   assembler.Push(Assembler::esp);
522   assembler.Push(0xcccccccc);
523   assembler.Pushl({.base = Assembler::esp, .disp = 0x428});
524   assembler.Popl({.base = Assembler::esp, .disp = 0x428});
525   assembler.Movl(Assembler::ecx, 0xcccccccc);
526   assembler.Call(Assembler::ecx);
527   assembler.Movl(Assembler::eax, {.base = Assembler::esp, .disp = 8});
528   assembler.Addl(Assembler::esp, 24);
529   assembler.Ret();
530   assembler.Finalize();
531 
532   // clang-format off
533   static const uint8_t kCodeTemplate[] = {
534     0x8b, 0x44, 0x24, 0x04,                    // mov     0x4(%esp),%eax
535     0x0f, 0xb1, 0x44, 0x24, 0x04,              // cmpxchg 0x4(%esp),%eax
536     0x83, 0xec, 0x10,                          // sub     $16, %esp
537     0x89, 0x04, 0x24,                          // mov     %eax,(%esp)
538     0x54,                                      // push    %esp
539     0x68, 0xcc, 0xcc, 0xcc, 0xcc,              // push    $cccccccc
540     0xff, 0xb4, 0x24, 0x28, 0x04, 0x00, 0x00,  // pushl   0x428(%esp)
541     0x8f, 0x84, 0x24, 0x28, 0x04, 0x00, 0x00,  // popl    0x428(%esp)
542     0xb9, 0xcc, 0xcc, 0xcc, 0xcc,              // mov     $cccccccc, %ecx
543     0xff, 0xd1,                                // call    *%ecx
544     0x8b, 0x44, 0x24, 0x08,                    // mov     0x8(%esp),%eax
545     0x83, 0xc4, 0x18,                          // add     $24, %esp
546     0xc3                                       //  ret
547   };
548   // clang-format on
549 
550   return CompareCode(std::begin(kCodeTemplate), std::end(kCodeTemplate), code, CPUArch::kX86_64);
551 }
552 
553 }  // namespace x86_32
554 
555 namespace x86_64 {
556 
AssemblerTest()557 bool AssemblerTest() {
558   MachineCode code;
559   Assembler assembler(&code);
560   assembler.Movq(Assembler::rax, Assembler::rdi);
561   assembler.Subq(Assembler::rsp, 16);
562   assembler.Movq({.base = Assembler::rsp}, Assembler::rax);
563   assembler.Movq({.base = Assembler::rsp, .disp = 8}, Assembler::rax);
564   assembler.Movl({.base = Assembler::rax, .disp = 16}, 239);
565   assembler.Movq(Assembler::r11, {.base = Assembler::rsp});
566   assembler.Addq(Assembler::rsp, 16);
567   assembler.Ret();
568   assembler.Finalize();
569 
570   // clang-format off
571   static const uint8_t kCodeTemplate[] = {
572     0x48, 0x89, 0xf8,               // mov %rdi, %rax
573     0x48, 0x83, 0xec, 0x10,         // sub $0x10, %rsp
574     0x48, 0x89, 0x04, 0x24,         // mov rax, (%rsp)
575     0x48, 0x89, 0x44, 0x24, 0x08,   // mov rax, 8(%rsp)
576     0xc7, 0x40, 0x10, 0xef, 0x00,   // movl $239, 0x10(%rax)
577     0x00, 0x00,
578     0x4c, 0x8b, 0x1c, 0x24,         // mov (%rsp), r11
579     0x48, 0x83, 0xc4, 0x10,         // add $0x10, %rsp
580     0xc3                            // ret
581   };
582   // clang-format on
583 
584   return CompareCode(std::begin(kCodeTemplate), std::end(kCodeTemplate), code, CPUArch::kX86_64);
585 }
586 
587 }  // namespace x86_64
588 
589 #if defined(__i386__)
590 
591 namespace x86_32 {
592 
LabelTest()593 bool LabelTest() {
594   MachineCode code;
595   CodeEmitter as(&code);
596   Assembler::Label skip, skip2, back, end;
597   as.Call(bit_cast<const void*>(&Callee));
598   as.Jmp(skip);
599   as.Movl(Assembler::eax, 2);
600   as.Bind(&skip);
601   as.Addl(Assembler::eax, 8);
602   as.Jmp(skip2);
603   as.Bind(&back);
604   as.Addl(Assembler::eax, 12);
605   as.Jmp(end);
606   as.Bind(&skip2);
607   as.Jmp(back);
608   as.Bind(&end);
609   as.Ret();
610   as.Finalize();
611 
612   ScopedExecRegion exec(&code);
613 
614   int result = exec.get<int()>()();
615   return result == 239 + 8 + 12;
616 }
617 
CondTest1()618 bool CondTest1() {
619   MachineCode code;
620   CodeEmitter as(&code);
621   as.Movl(Assembler::eax, 0xcccccccc);
622   as.Movl(Assembler::edx, {.base = Assembler::esp, .disp = 4});  // arg1.
623   as.Movl(Assembler::ecx, {.base = Assembler::esp, .disp = 8});  // arg2.
624   as.Cmpl(Assembler::edx, Assembler::ecx);
625   as.Setcc(Assembler::Condition::kEqual, Assembler::eax);
626   as.Ret();
627   as.Finalize();
628 
629   ScopedExecRegion exec(&code);
630 
631   using TestFunc = uint32_t(int, int);
632   auto target_func = exec.get<TestFunc>();
633   uint32_t result = target_func(1, 2);
634   if (result != 0xcccccc00) {
635     ALOGE("Bug in seteq(not equal): %x", result);
636     return false;
637   }
638   result = target_func(-1, -1);
639   if (result != 0xcccccc01) {
640     ALOGE("Bug in seteq(equal): %x", result);
641     return false;
642   }
643   return true;
644 }
645 
CondTest2()646 bool CondTest2() {
647   MachineCode code;
648   CodeEmitter as(&code);
649   as.Movl(Assembler::edx, {.base = Assembler::esp, .disp = 4});  // arg1.
650   as.Movl(Assembler::ecx, {.base = Assembler::esp, .disp = 8});  // arg2.
651   as.Xorl(Assembler::eax, Assembler::eax);
652   as.Testb(Assembler::edx, Assembler::ecx);
653   as.Setcc(Assembler::Condition::kNotZero, Assembler::eax);
654   as.Xchgl(Assembler::eax, Assembler::ecx);
655   as.Xchgl(Assembler::ecx, Assembler::eax);
656   as.Ret();
657   as.Finalize();
658 
659   ScopedExecRegion exec(&code);
660 
661   using TestFunc = uint32_t(int, int);
662   auto target_func = exec.get<TestFunc>();
663   uint32_t result = target_func(0x11, 1);
664   if (result != 0x1) {
665     ALOGE("Bug in testb(not zero): %x", result);
666     return false;
667   }
668   result = target_func(0x11, 0x8);
669   if (result != 0x0) {
670     ALOGE("Bug in testb(zero): %x", result);
671     return false;
672   }
673   return true;
674 }
675 
JccTest()676 bool JccTest() {
677   MachineCode code;
678   CodeEmitter as(&code);
679   Assembler::Label equal, above, below, done;
680   as.Movl(Assembler::edx, {.base = Assembler::esp, .disp = 4});  // arg1.
681   as.Movl(Assembler::ecx, {.base = Assembler::esp, .disp = 8});  // arg2.
682   as.Cmpl(Assembler::edx, Assembler::ecx);
683   as.Jcc(Assembler::Condition::kEqual, equal);
684   as.Jcc(Assembler::Condition::kBelow, below);
685   as.Jcc(Assembler::Condition::kAbove, above);
686 
687   as.Movl(Assembler::eax, 13);
688   as.Jmp(done);
689 
690   as.Bind(&equal);
691   as.Movl(Assembler::eax, 0u);
692   as.Jmp(done);
693 
694   as.Bind(&below);
695   as.Movl(Assembler::eax, -1);
696   as.Jmp(done);
697 
698   as.Bind(&above);
699   as.Movl(Assembler::eax, 1);
700   as.Jmp(done);
701 
702   as.Bind(&done);
703   as.Ret();
704   as.Finalize();
705 
706   ScopedExecRegion exec(&code);
707 
708   using TestFunc = int(int, int);
709   auto target_func = exec.get<TestFunc>();
710   int result = target_func(1, 1);
711   if (result != 0) {
712     ALOGE("Bug in jcc(equal): %x", result);
713     return false;
714   }
715   result = target_func(1, 0);
716   if (result != 1) {
717     ALOGE("Bug in jcc(above): %x", result);
718     return false;
719   }
720   result = target_func(0, 1);
721   if (result != -1) {
722     ALOGE("Bug in jcc(below): %x", result);
723     return false;
724   }
725   return true;
726 }
727 
ShiftTest()728 bool ShiftTest() {
729   MachineCode code;
730   CodeEmitter as(&code);
731   as.Movl(Assembler::eax, {.base = Assembler::esp, .disp = 4});
732   as.Shll(Assembler::eax, int8_t{2});
733   as.Shrl(Assembler::eax, int8_t{1});
734   as.Movl(Assembler::ecx, 3);
735   as.ShllByCl(Assembler::eax);
736   as.Ret();
737   as.Finalize();
738 
739   ScopedExecRegion exec(&code);
740 
741   using TestFunc = uint32_t(uint32_t);
742   uint32_t result = exec.get<TestFunc>()(22);
743   return result == (22 << 4);
744 }
745 
LogicTest()746 bool LogicTest() {
747   MachineCode code;
748   CodeEmitter as(&code);
749   as.Movl(Assembler::eax, {.base = Assembler::esp, .disp = 4});
750   as.Movl(Assembler::ecx, 0x1);
751   as.Xorl(Assembler::eax, Assembler::ecx);
752   as.Movl(Assembler::ecx, 0xf);
753   as.Andl(Assembler::eax, Assembler::ecx);
754   as.Ret();
755   as.Finalize();
756 
757   ScopedExecRegion exec(&code);
758 
759   using TestFunc = uint32_t(uint32_t);
760   uint32_t result = exec.get<TestFunc>()(239);
761   return result == ((239 ^ 1) & 0xf);
762 }
763 
BsrTest()764 bool BsrTest() {
765   MachineCode code;
766   CodeEmitter as(&code);
767 
768   as.Movl(Assembler::ecx, {.base = Assembler::esp, .disp = 4});
769   as.Movl(Assembler::edx, 239);
770   as.Bsrl(Assembler::eax, Assembler::ecx);
771   as.Cmovl(Assembler::Condition::kZero, Assembler::eax, Assembler::edx);
772   as.Ret();
773   as.Finalize();
774 
775   ScopedExecRegion exec(&code);
776 
777   using TestFunc = uint32_t(uint32_t arg);
778   auto func = exec.get<TestFunc>();
779   return func(0) == 239 && func(1 << 15) == 15;
780 }
781 
CallFPTest()782 bool CallFPTest() {
783   MachineCode code;
784   CodeEmitter as(&code);
785   as.Push(0x3f800000);
786   as.Push(0x40000000);
787   as.Call(bit_cast<const void*>(&FloatFunc));
788   as.Fstps({.base = Assembler::esp});
789   as.Pop(Assembler::eax);
790   as.Addl(Assembler::esp, 4);
791   as.Ret();
792   as.Finalize();
793 
794   ScopedExecRegion exec(&code);
795 
796   using TestFunc = uint32_t();
797   uint32_t result = exec.get<TestFunc>()();
798   return result == 0x3f800000;
799 }
800 
XmmTest()801 bool XmmTest() {
802   MachineCode code;
803   CodeEmitter as(&code);
804   as.Movl(Assembler::eax, 0x3f800000);
805   as.Movd(Assembler::xmm0, Assembler::eax);
806   as.Movl(Assembler::eax, 0x40000000);
807   as.Movd(Assembler::xmm5, Assembler::eax);
808   as.Addss(Assembler::xmm0, Assembler::xmm5);
809   as.Movd(Assembler::eax, Assembler::xmm0);
810   as.Ret();
811   as.Finalize();
812 
813   ScopedExecRegion exec(&code);
814 
815   using TestFunc = uint32_t();
816   uint32_t result = exec.get<TestFunc>()();
817   return result == 0x40400000;
818 }
819 
ReadGlobalTest()820 bool ReadGlobalTest() {
821   MachineCode code;
822   CodeEmitter as(&code);
823   static const uint32_t kData[] __attribute__((aligned(16))) =  // NOLINT
824       {0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff};
825   as.Movsd(Assembler::xmm0, {.disp = bit_cast<int32_t>(&kData)});
826   as.Movdqa(Assembler::xmm1, {.disp = bit_cast<int32_t>(&kData)});
827   as.Movl(Assembler::eax, {.base = Assembler::esp, .disp = 4});
828   as.Movl(Assembler::ecx, {.base = Assembler::esp, .disp = 8});
829   as.Movsd({.base = Assembler::eax}, Assembler::xmm0);
830   as.Movdqu({.base = Assembler::ecx}, Assembler::xmm1);
831 
832   as.Ret();
833   as.Finalize();
834 
835   ScopedExecRegion exec(&code);
836 
837   using TestFunc = void(void*, void*);
838   uint8_t res1[8];
839   uint8_t res2[16];
840   exec.get<TestFunc>()(res1, res2);
841 
842   return (memcmp(res1, kData, 8) == 0) && (memcmp(res2, kData, 16) == 0);
843 }
844 
845 }  // namespace x86_32
846 
847 #elif defined(__amd64__)
848 
849 namespace x86_64 {
850 
LabelTest()851 bool LabelTest() {
852   MachineCode code;
853   CodeEmitter as(&code);
854   Assembler::Label skip, skip2, back, end;
855   as.Call(bit_cast<const void*>(&Callee));
856   as.Jmp(skip);
857   as.Movl(Assembler::rax, 2);
858   as.Bind(&skip);
859   as.Addb(Assembler::rax, {end});
860   as.Jmp(skip2);
861   as.Bind(&back);
862   as.Addl(Assembler::rax, 12);
863   as.Jmp(end);
864   as.Bind(&skip2);
865   as.Jmp(back);
866   as.Bind(&end);
867   as.Ret();
868   as.Finalize();
869 
870   ScopedExecRegion exec(&code);
871 
872   using TestFunc = int();
873   int result = exec.get<TestFunc>()();
874   return result == uint8_t(239 + 0xc3) + 12;
875 }
876 
CondTest1()877 bool CondTest1() {
878   MachineCode code;
879   CodeEmitter as(&code);
880   as.Movl(Assembler::rax, 0xcccccccc);
881   as.Cmpl(Assembler::rdi, Assembler::rsi);
882   as.Setcc(Assembler::Condition::kEqual, Assembler::rax);
883   as.Ret();
884   as.Finalize();
885 
886   ScopedExecRegion exec(&code);
887 
888   std::string code_str;
889   code.AsString(&code_str, InstructionSize::OneByte);
890   using TestFunc = uint32_t(int, int);
891   auto target_func = exec.get<TestFunc>();
892   uint32_t result;
893   result = target_func(1, 2);
894   if (result != 0xcccccc00) {
895     ALOGE("Bug in seteq(not equal): %x", result);
896     return false;
897   }
898   result = target_func(-1, -1);
899   if (result != 0xcccccc01) {
900     ALOGE("Bug in seteq(equal): %x", result);
901     return false;
902   }
903   return true;
904 }
905 
CondTest2()906 bool CondTest2() {
907   MachineCode code;
908   CodeEmitter as(&code);
909   as.Movl(Assembler::rdx, Assembler::rdi);  // arg1.
910   as.Movl(Assembler::rcx, Assembler::rsi);  // arg2.
911   as.Xorl(Assembler::rax, Assembler::rax);
912   as.Testb(Assembler::rdx, Assembler::rcx);
913   as.Setcc(Assembler::Condition::kNotZero, Assembler::rax);
914   as.Xchgq(Assembler::rax, Assembler::rcx);
915   as.Xchgq(Assembler::rcx, Assembler::rax);
916   as.Xchgq(Assembler::rcx, Assembler::r11);
917   as.Xchgq(Assembler::r11, Assembler::rcx);
918   as.Ret();
919   as.Finalize();
920 
921   ScopedExecRegion exec(&code);
922 
923   using TestFunc = uint32_t(int, int);
924   auto target_func = exec.get<TestFunc>();
925   uint32_t result = target_func(0x11, 1);
926   if (result != 0x1) {
927     printf("Bug in testb(not zero): %x", result);
928     return false;
929   }
930   result = target_func(0x11, 0x8);
931   if (result != 0x0) {
932     printf("Bug in testb(zero): %x", result);
933     return false;
934   }
935   return true;
936 }
937 
JccTest()938 bool JccTest() {
939   MachineCode code;
940   CodeEmitter as(&code);
941   Assembler::Label equal, above, below, done;
942   as.Cmpl(Assembler::rdi, Assembler::rsi);
943   as.Jcc(Assembler::Condition::kEqual, equal);
944   as.Jcc(Assembler::Condition::kBelow, below);
945   as.Jcc(Assembler::Condition::kAbove, above);
946 
947   as.Movl(Assembler::rax, 13);
948   as.Jmp(done);
949 
950   as.Bind(&equal);
951   as.Movq(Assembler::rax, 0);
952   as.Jmp(done);
953 
954   as.Bind(&below);
955   as.Movl(Assembler::rax, -1);
956   as.Jmp(done);
957 
958   as.Bind(&above);
959   as.Movl(Assembler::rax, 1);
960   as.Jmp(done);
961 
962   as.Bind(&done);
963   as.Ret();
964   as.Finalize();
965 
966   ScopedExecRegion exec(&code);
967 
968   using TestFunc = int(int, int);
969   auto target_func = exec.get<TestFunc>();
970   int result;
971   result = target_func(1, 1);
972   if (result != 0) {
973     ALOGE("Bug in jcc(equal): %x", result);
974     return false;
975   }
976   result = target_func(1, 0);
977   if (result != 1) {
978     ALOGE("Bug in jcc(above): %x", result);
979     return false;
980   }
981   result = target_func(0, 1);
982   if (result != -1) {
983     ALOGE("Bug in jcc(below): %x", result);
984     return false;
985   }
986   return true;
987 }
988 
ReadWriteTest()989 bool ReadWriteTest() {
990   MachineCode code;
991   CodeEmitter as(&code);
992 
993   as.Movq(Assembler::rax, 0);
994   as.Movb(Assembler::rax, {.base = Assembler::rdi});
995   as.Movl(Assembler::rcx, {.base = Assembler::rsi});
996   as.Addl(Assembler::rax, Assembler::rcx);
997   as.Movl({.base = Assembler::rsi}, Assembler::rax);
998   as.Ret();
999   as.Finalize();
1000 
1001   ScopedExecRegion exec(&code);
1002 
1003   using TestFunc = uint32_t(uint8_t*, uint32_t*);
1004   uint8_t p1[4] = {0x12, 0x34, 0x56, 0x78};
1005   uint32_t p2 = 0x239;
1006   uint32_t result = exec.get<TestFunc>()(p1, &p2);
1007   return (result == 0x239 + 0x12) && (p2 == result);
1008 }
1009 
CallFPTest()1010 bool CallFPTest() {
1011   MachineCode code;
1012   CodeEmitter as(&code);
1013   as.Movl(Assembler::rax, 0x40000000);
1014   as.Movd(Assembler::xmm0, Assembler::rax);
1015   as.Movl(Assembler::rax, 0x3f800000);
1016   as.Movd(Assembler::xmm1, Assembler::rax);
1017   as.Call(bit_cast<const void*>(&FloatFunc));
1018   as.Movd(Assembler::rax, Assembler::xmm0);
1019   as.Ret();
1020   as.Finalize();
1021 
1022   ScopedExecRegion exec(&code);
1023 
1024   using TestFunc = uint32_t();
1025   uint32_t result = exec.get<TestFunc>()();
1026   return result == 0x3f800000;
1027 }
1028 
XmmTest()1029 bool XmmTest() {
1030   MachineCode code;
1031   CodeEmitter as(&code);
1032   as.Movl(Assembler::rax, 0x40000000);
1033   as.Movd(Assembler::xmm0, Assembler::rax);
1034   as.Movl(Assembler::rax, 0x3f800000);
1035   as.Movd(Assembler::xmm11, Assembler::rax);
1036   as.Addss(Assembler::xmm0, Assembler::xmm11);
1037   as.Movaps(Assembler::xmm12, Assembler::xmm0);
1038   as.Addss(Assembler::xmm0, Assembler::xmm12);
1039   as.Movapd(Assembler::xmm14, Assembler::xmm1);
1040   as.Movd(Assembler::rax, Assembler::xmm0);
1041   as.Ret();
1042   as.Finalize();
1043 
1044   ScopedExecRegion exec(&code);
1045 
1046   using TestFunc = uint32_t();
1047   uint32_t result = exec.get<TestFunc>()();
1048   return result == 0x40c00000;
1049 }
1050 
XmmMemTest()1051 bool XmmMemTest() {
1052   MachineCode code;
1053   CodeEmitter as(&code);
1054 
1055   as.Movsd(Assembler::xmm0, {.base = Assembler::rdi});
1056   as.Movaps(Assembler::xmm12, Assembler::xmm0);
1057   as.Addsd(Assembler::xmm12, Assembler::xmm12);
1058   as.Movsd({.base = Assembler::rdi}, Assembler::xmm12);
1059   as.Movq(Assembler::rax, Assembler::xmm0);
1060   as.Ret();
1061   as.Finalize();
1062 
1063   ScopedExecRegion exec(&code);
1064 
1065   double d = 239.0;
1066   char bits[16], *p = bits + 5;
1067   memcpy(p, &d, sizeof(d));
1068 
1069   using TestFunc = uint64_t(char* p);
1070   uint64_t result = exec.get<TestFunc>()(p);
1071   uint64_t doubled = *reinterpret_cast<uint64_t*>(p);
1072   return result == 0x406de00000000000ULL && doubled == 0x407de00000000000ULL;
1073 }
1074 
MovsxblRexTest()1075 bool MovsxblRexTest() {
1076   MachineCode code;
1077   CodeEmitter as(&code);
1078 
1079   as.Xorl(Assembler::rdx, Assembler::rdx);
1080   as.Movl(Assembler::rsi, 0xdeadff);
1081   // CodeEmitter should use REX prefix to encode SIL.
1082   // Without REX DH is used.
1083   as.Movsxbl(Assembler::rax, Assembler::rsi);
1084   as.Ret();
1085   as.Finalize();
1086 
1087   ScopedExecRegion exec(&code);
1088 
1089   using TestFunc = uint32_t();
1090   uint32_t result = exec.get<TestFunc>()();
1091 
1092   return result == 0xffffffff;
1093 }
1094 
MovzxblRexTest()1095 bool MovzxblRexTest() {
1096   MachineCode code;
1097   CodeEmitter as(&code);
1098 
1099   as.Xorl(Assembler::rdx, Assembler::rdx);
1100   as.Movl(Assembler::rsi, 0xdeadff);
1101   // CodeEmitter should use REX prefix to encode SIL.
1102   // Without REX DH is used.
1103   as.Movzxbl(Assembler::rax, Assembler::rsi);
1104   as.Ret();
1105   as.Finalize();
1106 
1107   ScopedExecRegion exec(&code);
1108 
1109   using TestFunc = uint32_t();
1110   uint32_t result = exec.get<TestFunc>()();
1111 
1112   return result == 0x000000ff;
1113 }
1114 
ShldlRexTest()1115 bool ShldlRexTest() {
1116   MachineCode code;
1117   CodeEmitter as(&code);
1118 
1119   as.Movl(Assembler::rdx, 0x12345678);
1120   // If most-significant bit is not encoded correctly with REX
1121   // RAX can be used instead R8 and R10 can be used instead RDX.
1122   // Init them all:
1123   as.Xorl(Assembler::r8, Assembler::r8);
1124   as.Movl(Assembler::rax, 0xdeadbeef);
1125   as.Movl(Assembler::r10, 0xdeadbeef);
1126 
1127   as.Shldl(Assembler::r8, Assembler::rdx, int8_t{8});
1128   as.Movl(Assembler::rcx, 8);
1129   as.ShldlByCl(Assembler::r8, Assembler::rdx);
1130 
1131   as.Movl(Assembler::rax, Assembler::r8);
1132 
1133   as.Ret();
1134   as.Finalize();
1135 
1136   ScopedExecRegion exec(&code);
1137 
1138   using TestFunc = uint32_t();
1139   uint32_t result = exec.get<TestFunc>()();
1140 
1141   return result == 0x1212;
1142 }
1143 
ShrdlRexTest()1144 bool ShrdlRexTest() {
1145   MachineCode code;
1146   CodeEmitter as(&code);
1147 
1148   as.Movl(Assembler::rdx, 0x12345678);
1149   // If most-significant bit is not encoded correctly with REX
1150   // RAX can be used instead R8 and R10 can be used instead RDX.
1151   // Init them all:
1152   as.Xorl(Assembler::r8, Assembler::r8);
1153   as.Movl(Assembler::rax, 0xdeadbeef);
1154   as.Movl(Assembler::r10, 0xdeadbeef);
1155 
1156   as.Shrdl(Assembler::r8, Assembler::rdx, int8_t{8});
1157   as.Movl(Assembler::rcx, 8);
1158   as.ShrdlByCl(Assembler::r8, Assembler::rdx);
1159 
1160   as.Movl(Assembler::rax, Assembler::r8);
1161 
1162   as.Ret();
1163   as.Finalize();
1164 
1165   ScopedExecRegion exec(&code);
1166 
1167   using TestFunc = uint32_t();
1168   uint32_t result = exec.get<TestFunc>()();
1169 
1170   return result == 0x78780000;
1171 }
1172 
ReadGlobalTest()1173 bool ReadGlobalTest() {
1174   MachineCode code;
1175   CodeEmitter as(&code);
1176   static const uint32_t kData[] __attribute__((aligned(16))) =  // NOLINT
1177       {0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff};
1178   // We couldn't read data from arbitrary address on x86_64, need address in first 2GiB.
1179   void* data =
1180       mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
1181   // Copy our global there.
1182   memcpy(data, kData, 16);
1183   int32_t data_offset = static_cast<int32_t>(bit_cast<intptr_t>(data));
1184   as.Movsd(Assembler::xmm0, {.disp = data_offset});
1185   as.Movdqa(Assembler::xmm1, {.disp = data_offset});
1186   as.Movsd({.base = Assembler::rdi}, Assembler::xmm0);
1187   as.Movdqu({.base = Assembler::rsi}, Assembler::xmm1);
1188 
1189   as.Ret();
1190   as.Finalize();
1191 
1192   ScopedExecRegion exec(&code);
1193 
1194   using TestFunc = void(void*, void*);
1195   uint8_t res1[8];
1196   uint8_t res2[16];
1197   exec.get<TestFunc>()(res1, res2);
1198 
1199   munmap(data, 4096);
1200 
1201   return (memcmp(res1, kData, 8) == 0) && (memcmp(res2, kData, 16) == 0);
1202 }
1203 
MemShiftTest()1204 bool MemShiftTest() {
1205   MachineCode code;
1206   CodeEmitter as(&code);
1207 
1208   as.Push(Assembler::rdi);
1209   as.Movl(Assembler::rcx, 1);
1210   as.ShrlByCl({.base = Assembler::rsp});
1211   as.Addl(Assembler::rcx, 1);
1212   as.Movq(Assembler::rdi, Assembler::rsp);
1213   as.ShllByCl({.base = Assembler::rdi});
1214   as.Pop(Assembler::rax);
1215 
1216   as.Ret();
1217   as.Finalize();
1218 
1219   ScopedExecRegion exec(&code);
1220 
1221   using TestFunc = int(int x);
1222   int result = exec.get<TestFunc>()(0x10);
1223 
1224   return result == 0x20;
1225 }
1226 
1227 }  // namespace x86_64
1228 
1229 #endif
1230 
1231 #if defined(__i386__) || defined(__amd64__)
1232 
1233 #if defined(__i386__)
1234 
1235 extern "C" const uint8_t berberis_gnu_as_output_start[] asm(
1236     "berberis_gnu_as_output_start_x86_32");
1237 extern "C" const uint8_t berberis_gnu_as_output_end[] asm(
1238     "berberis_gnu_as_output_end_x86_32");
1239 
1240 namespace x86_32 {
1241 void GenInsnsCommon(CodeEmitter* as);
1242 void GenInsnsArch(CodeEmitter* as);
1243 }  // namespace x86_32
1244 
1245 #else
1246 
1247 extern "C" const uint8_t berberis_gnu_as_output_start[] asm(
1248     "berberis_gnu_as_output_start_x86_64");
1249 extern "C" const uint8_t berberis_gnu_as_output_end[] asm(
1250     "berberis_gnu_as_output_end_x86_64");
1251 
1252 namespace x86_64 {
1253 void GenInsnsCommon(CodeEmitter* as);
1254 void GenInsnsArch(CodeEmitter* as);
1255 }  // namespace x86_64
1256 
1257 #endif
1258 
ExhaustiveTest()1259 bool ExhaustiveTest() {
1260   MachineCode code;
1261   CodeEmitter as(&code);
1262 
1263 #if defined(__i386__)
1264   berberis::x86_32::GenInsnsCommon(&as);
1265   berberis::x86_32::GenInsnsArch(&as);
1266 #else
1267   berberis::x86_64::GenInsnsCommon(&as);
1268   berberis::x86_64::GenInsnsArch(&as);
1269 #endif
1270   as.Finalize();
1271 
1272   return CompareCode(
1273       berberis_gnu_as_output_start, berberis_gnu_as_output_end, code, CPUArch::kX86_64);
1274 }
1275 
MixedAssembler()1276 bool MixedAssembler() {
1277   MachineCode code;
1278   x86_32::Assembler as32(&code);
1279   x86_64::Assembler as64(&code);
1280   x86_32::Assembler::Label lbl32;
1281   x86_64::Assembler::Label lbl64;
1282 
1283   as32.Jmp(lbl32);
1284   as32.Xchgl(x86_32::Assembler::eax, x86_32::Assembler::eax);
1285   as64.Jmp(lbl64);
1286   as64.Xchgl(x86_64::Assembler::rax, x86_64::Assembler::rax);
1287   as32.Bind(&lbl32);
1288   as32.Movl(x86_32::Assembler::eax, {.disp = 0});
1289   as64.Bind(&lbl64);
1290   as32.Finalize();
1291   as64.Finalize();
1292 
1293   // clang-format off
1294   static const uint8_t kCodeTemplate[] = {
1295     0xe9, 0x08, 0x00, 0x00, 0x00,              // jmp lbl32
1296     0x90,                                      // xchg %eax, %eax == nop
1297     0xe9, 0x07, 0x00, 0x00, 0x00,              // jmp lbl64
1298     0x87, 0xc0,                                // xchg %eax, %eax != nop
1299                                                // lbl32:
1300     0xa1, 0x00, 0x00, 0x00, 0x00               // movabs %eax, 0x0
1301                                                // lbl64:
1302   };
1303   // clang-format on
1304 
1305   return CompareCode(std::begin(kCodeTemplate), std::end(kCodeTemplate), code, CPUArch::kX86_64);
1306 }
1307 #endif
1308 
1309 }  // namespace berberis
1310 
TEST(Assembler,AssemblerTest)1311 TEST(Assembler, AssemblerTest) {
1312   EXPECT_TRUE(berberis::rv32::AssemblerTest());
1313   EXPECT_TRUE(berberis::rv64::AssemblerTest());
1314   EXPECT_TRUE(berberis::x86_32::AssemblerTest());
1315   EXPECT_TRUE(berberis::x86_64::AssemblerTest());
1316 #if defined(__i386__)
1317   EXPECT_TRUE(berberis::x86_32::LabelTest());
1318   EXPECT_TRUE(berberis::x86_32::CondTest1());
1319   EXPECT_TRUE(berberis::x86_32::CondTest2());
1320   EXPECT_TRUE(berberis::x86_32::JccTest());
1321   EXPECT_TRUE(berberis::x86_32::ShiftTest());
1322   EXPECT_TRUE(berberis::x86_32::LogicTest());
1323   EXPECT_TRUE(berberis::x86_32::CallFPTest());
1324   EXPECT_TRUE(berberis::x86_32::XmmTest());
1325   EXPECT_TRUE(berberis::x86_32::BsrTest());
1326   EXPECT_TRUE(berberis::x86_32::ReadGlobalTest());
1327 #elif defined(__amd64__)
1328   EXPECT_TRUE(berberis::x86_64::LabelTest());
1329   EXPECT_TRUE(berberis::x86_64::CondTest1());
1330   EXPECT_TRUE(berberis::x86_64::CondTest2());
1331   EXPECT_TRUE(berberis::x86_64::JccTest());
1332   EXPECT_TRUE(berberis::x86_64::ReadWriteTest());
1333   EXPECT_TRUE(berberis::x86_64::CallFPTest());
1334   EXPECT_TRUE(berberis::x86_64::XmmTest());
1335   EXPECT_TRUE(berberis::x86_64::XmmMemTest());
1336   EXPECT_TRUE(berberis::x86_64::MovsxblRexTest());
1337   EXPECT_TRUE(berberis::x86_64::MovzxblRexTest());
1338   EXPECT_TRUE(berberis::x86_64::ShldlRexTest());
1339   EXPECT_TRUE(berberis::x86_64::ShrdlRexTest());
1340   EXPECT_TRUE(berberis::x86_64::ReadGlobalTest());
1341   EXPECT_TRUE(berberis::x86_64::MemShiftTest());
1342 #endif
1343   // Currently we don't support these tests for riscv.
1344   // TODO(b/352784623): Implement for riscv.
1345 #if defined(__i386__) || defined(__x86_64__)
1346   EXPECT_TRUE(berberis::ExhaustiveTest());
1347   EXPECT_TRUE(berberis::MixedAssembler());
1348 #endif
1349 }
1350