1 /* $NetBSD: disasm.c,v 1.16 2024/02/07 04:20:26 msaitoh Exp $ */
2
3 /*
4 * Copyright (c) 2018 Ryo Shimizu
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: disasm.c,v 1.16 2024/02/07 04:20:26 msaitoh Exp $");
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/bitops.h>
35
36 #include <arch/aarch64/aarch64/disasm.h>
37
38 #ifndef _KERNEL
39 #include <stdio.h>
40 #include <stdbool.h>
41 #endif
42
43 #define PRINTF di->di_printf
44 #define PRINTADDR di->di_printaddr
45
46 #define OPFUNC_DECL(func, a, b, c, d, e, f, g, h) \
47 func(const disasm_interface_t *di, uint64_t pc, uint32_t insn, \
48 uint64_t a, uint64_t b, uint64_t c, uint64_t d, \
49 uint64_t e, uint64_t f, uint64_t g, uint64_t h)
50
51 #define UNUSED0 arg0 __unused
52 #define UNUSED1 arg1 __unused
53 #define UNUSED2 arg2 __unused
54 #define UNUSED3 arg3 __unused
55 #define UNUSED4 arg4 __unused
56 #define UNUSED5 arg5 __unused
57 #define UNUSED6 arg6 __unused
58 #define UNUSED7 arg7 __unused
59
60 #define OP0FUNC(func) \
61 static void \
62 OPFUNC_DECL(func, \
63 UNUSED0, UNUSED1, UNUSED2, UNUSED3, \
64 UNUSED4, UNUSED5, UNUSED6, UNUSED7)
65 #define OP1FUNC(func, a) \
66 static void \
67 OPFUNC_DECL(func, a, \
68 UNUSED1, UNUSED2, UNUSED3, UNUSED4, \
69 UNUSED5, UNUSED6, UNUSED7)
70 #define OP2FUNC(func, a, b) \
71 static void \
72 OPFUNC_DECL(func, a, b, \
73 UNUSED2, UNUSED3, UNUSED4, UNUSED5, \
74 UNUSED6, UNUSED7)
75 #define OP3FUNC(func, a, b, c) \
76 static void \
77 OPFUNC_DECL(func, a, b, c, \
78 UNUSED3, UNUSED4, UNUSED5, UNUSED6, \
79 UNUSED7)
80 #define OP4FUNC(func, a, b, c, d) \
81 static void \
82 OPFUNC_DECL(func, a, b, c, d, \
83 UNUSED4, UNUSED5, UNUSED6, UNUSED7)
84 #define OP5FUNC(func, a, b, c, d, e) \
85 static void \
86 OPFUNC_DECL( func, a, b, c, d, e, \
87 UNUSED5, UNUSED6, UNUSED7)
88 #define OP6FUNC(func, a, b, c, d, e, f) \
89 static void \
90 OPFUNC_DECL(func, a, b, c, d, e, f, \
91 UNUSED6, UNUSED7)
92 #define OP7FUNC(func, a, b, c, d, e, f, g) \
93 static void \
94 OPFUNC_DECL(func, a, b, c, d, e, f, g, \
95 UNUSED7)
96 #define OP8FUNC(func, a, b, c, d, e, f, g, h) \
97 static void \
98 OPFUNC_DECL(func, a, b, c, d, e, f, g, h)
99
100 static const char *z_wxregs[2][32] = {
101 {
102 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
103 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
104 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
105 "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr"
106 },
107 {
108 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
109 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
110 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
111 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "xzr"
112 }
113 };
114
115 static const char *s_wxregs[2][32] = {
116 {
117 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
118 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
119 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
120 "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp"
121 },
122 {
123 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
124 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
125 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
126 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp"
127 }
128 };
129 #define ZREGNAME(s, n) (z_wxregs[(s) & 1][(n) & 31])
130 #define SREGNAME(s, n) (s_wxregs[(s) & 1][(n) & 31])
131
132 static const char *simdregs[5][32] = {
133 {
134 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
135 "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15",
136 "b16", "b17", "b18", "b19", "b20", "b21", "b22", "b23",
137 "b24", "b25", "b26", "b27", "b28", "b29", "b30", "b31"
138 },
139 {
140 "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
141 "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
142 "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
143 "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31"
144 },
145 {
146 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
147 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
148 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
149 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"
150 },
151 {
152 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
153 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
154 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
155 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
156 },
157 {
158 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
159 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
160 "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23",
161 "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31"
162 }
163 };
164 #define FREGSZ_B 0
165 #define FREGSZ_H 1
166 #define FREGSZ_S 2
167 #define FREGSZ_D 3
168 #define FREGSZ_Q 4
169 #define FREGNAME(s, n) (simdregs[(s)][(n) & 31])
170
171 static const char *vecregs[32] = {
172 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
173 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
174 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
175 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
176 };
177 #define VREGNAME(n) vecregs[(n) & 31]
178
179 static const char *cregs[16] = {
180 "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
181 "C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15"
182 };
183 #define CREGNAME(n) cregs[(n) & 15]
184
185 static const char *conditioncode[16] = {
186 "eq", "ne", "cs", "cc",
187 "mi", "pl", "vs", "vc",
188 "hi", "ls", "ge", "lt",
189 "gt", "le", "al", "nv"
190 };
191 #define CONDNAME(c) conditioncode[(c) & 15]
192 #define IVCONDNAME(c) conditioncode[((c) ^ 1) & 15]
193
194 static const char *barrierop[16] = {
195 "#0", "oshld", "oshst", "osh",
196 "#4", "nshld", "nshst", "nsh",
197 "#8", "ishld", "ishst", "ish",
198 "#12", "ld", "st", "sy"
199 };
200 #define BARRIERNAME(op) barrierop[(op) & 15]
201
202 static const char *prefetchop[32] = {
203 "pldl1keep", "pldl1strm", "pldl2keep", "pldl2strm",
204 "pldl3keep", "pldl3strm", "#6", "#7",
205 "plil1keep", "plil1strm", "plil2keep", "plil2strm",
206 "plil3keep", "plil3strm", "#14", "#15",
207 "pstl1keep", "pstl1strm", "pstl2keep", "pstl2strm",
208 "pstl3keep", "pstl3strm", "#22", "#23",
209 "#24", "#25", "#26", "#27",
210 "#28", "#29", "#30", "#31"
211 };
212 #define PREFETCHNAME(op) prefetchop[(op) & 31]
213
214
215 #define SYSREG_ENC(op0, op1, CRn, CRm, op2) \
216 (((op0)<<19)|((op1)<<16)|((CRn)<<12)|((CRm)<<8)|((op2)<<5))
217
218 struct sysreg_table {
219 uint32_t code;
220 const char *regname;
221 };
222
223 /* must be sorted by code */
224 const struct sysreg_table sysreg_table[] = {
225 /* op0 op1 CRn CRm op2 name */
226 { SYSREG_ENC(2, 0, 0, 0, 2), "osdtrrx_el1" },
227 { SYSREG_ENC(2, 0, 0, 0, 4), "dbgbvr0_el1" },
228 { SYSREG_ENC(2, 0, 0, 0, 5), "dbgbcr0_el1" },
229 { SYSREG_ENC(2, 0, 0, 0, 6), "dbgwvr0_el1" },
230 { SYSREG_ENC(2, 0, 0, 0, 7), "dbgwcr0_el1" },
231 { SYSREG_ENC(2, 0, 0, 1, 4), "dbgbvr1_el1" },
232 { SYSREG_ENC(2, 0, 0, 1, 5), "dbgbcr1_el1" },
233 { SYSREG_ENC(2, 0, 0, 1, 6), "dbgwvr1_el1" },
234 { SYSREG_ENC(2, 0, 0, 1, 7), "dbgwcr1_el1" },
235 { SYSREG_ENC(2, 0, 0, 2, 0), "mdccint_el1" },
236 { SYSREG_ENC(2, 0, 0, 2, 2), "mdscr_el1" },
237 { SYSREG_ENC(2, 0, 0, 2, 4), "dbgbvr2_el1" },
238 { SYSREG_ENC(2, 0, 0, 2, 5), "dbgbcr2_el1" },
239 { SYSREG_ENC(2, 0, 0, 2, 6), "dbgwvr2_el1" },
240 { SYSREG_ENC(2, 0, 0, 2, 7), "dbgwcr2_el1" },
241 { SYSREG_ENC(2, 0, 0, 3, 2), "osdtrtx_el1" },
242 { SYSREG_ENC(2, 0, 0, 3, 4), "dbgbvr3_el1" },
243 { SYSREG_ENC(2, 0, 0, 3, 5), "dbgbcr3_el1" },
244 { SYSREG_ENC(2, 0, 0, 3, 6), "dbgwvr3_el1" },
245 { SYSREG_ENC(2, 0, 0, 3, 7), "dbgwcr3_el1" },
246 { SYSREG_ENC(2, 0, 0, 4, 4), "dbgbvr4_el1" },
247 { SYSREG_ENC(2, 0, 0, 4, 5), "dbgbcr4_el1" },
248 { SYSREG_ENC(2, 0, 0, 4, 6), "dbgwvr4_el1" },
249 { SYSREG_ENC(2, 0, 0, 4, 7), "dbgwcr4_el1" },
250 { SYSREG_ENC(2, 0, 0, 5, 4), "dbgbvr5_el1" },
251 { SYSREG_ENC(2, 0, 0, 5, 5), "dbgbcr5_el1" },
252 { SYSREG_ENC(2, 0, 0, 5, 6), "dbgwvr5_el1" },
253 { SYSREG_ENC(2, 0, 0, 5, 7), "dbgwcr5_el1" },
254 { SYSREG_ENC(2, 0, 0, 6, 2), "oseccr_el1" },
255 { SYSREG_ENC(2, 0, 0, 6, 4), "dbgbvr6_el1" },
256 { SYSREG_ENC(2, 0, 0, 6, 5), "dbgbcr6_el1" },
257 { SYSREG_ENC(2, 0, 0, 6, 6), "dbgwvr6_el1" },
258 { SYSREG_ENC(2, 0, 0, 6, 7), "dbgwcr6_el1" },
259 { SYSREG_ENC(2, 0, 0, 7, 4), "dbgbvr7_el1" },
260 { SYSREG_ENC(2, 0, 0, 7, 5), "dbgbcr7_el1" },
261 { SYSREG_ENC(2, 0, 0, 7, 6), "dbgwvr7_el1" },
262 { SYSREG_ENC(2, 0, 0, 7, 7), "dbgwcr7_el1" },
263 { SYSREG_ENC(2, 0, 0, 8, 4), "dbgbvr8_el1" },
264 { SYSREG_ENC(2, 0, 0, 8, 5), "dbgbcr8_el1" },
265 { SYSREG_ENC(2, 0, 0, 8, 6), "dbgwvr8_el1" },
266 { SYSREG_ENC(2, 0, 0, 8, 7), "dbgwcr8_el1" },
267 { SYSREG_ENC(2, 0, 0, 9, 4), "dbgbvr9_el1" },
268 { SYSREG_ENC(2, 0, 0, 9, 5), "dbgbcr9_el1" },
269 { SYSREG_ENC(2, 0, 0, 9, 6), "dbgwvr9_el1" },
270 { SYSREG_ENC(2, 0, 0, 9, 7), "dbgwcr9_el1" },
271 { SYSREG_ENC(2, 0, 0, 10, 4), "dbgbvr10_el1" },
272 { SYSREG_ENC(2, 0, 0, 10, 5), "dbgbcr10_el1" },
273 { SYSREG_ENC(2, 0, 0, 10, 6), "dbgwvr10_el1" },
274 { SYSREG_ENC(2, 0, 0, 10, 7), "dbgwcr10_el1" },
275 { SYSREG_ENC(2, 0, 0, 11, 4), "dbgbvr11_el1" },
276 { SYSREG_ENC(2, 0, 0, 11, 5), "dbgbcr11_el1" },
277 { SYSREG_ENC(2, 0, 0, 11, 6), "dbgwvr11_el1" },
278 { SYSREG_ENC(2, 0, 0, 11, 7), "dbgwcr11_el1" },
279 { SYSREG_ENC(2, 0, 0, 12, 4), "dbgbvr12_el1" },
280 { SYSREG_ENC(2, 0, 0, 12, 5), "dbgbcr12_el1" },
281 { SYSREG_ENC(2, 0, 0, 12, 6), "dbgwvr12_el1" },
282 { SYSREG_ENC(2, 0, 0, 12, 7), "dbgwcr12_el1" },
283 { SYSREG_ENC(2, 0, 0, 13, 4), "dbgbvr13_el1" },
284 { SYSREG_ENC(2, 0, 0, 13, 5), "dbgbcr13_el1" },
285 { SYSREG_ENC(2, 0, 0, 13, 6), "dbgwvr13_el1" },
286 { SYSREG_ENC(2, 0, 0, 13, 7), "dbgwcr13_el1" },
287 { SYSREG_ENC(2, 0, 0, 14, 4), "dbgbvr14_el1" },
288 { SYSREG_ENC(2, 0, 0, 14, 5), "dbgbcr14_el1" },
289 { SYSREG_ENC(2, 0, 0, 14, 6), "dbgwvr14_el1" },
290 { SYSREG_ENC(2, 0, 0, 14, 7), "dbgwcr14_el1" },
291 { SYSREG_ENC(2, 0, 0, 15, 4), "dbgbvr15_el1" },
292 { SYSREG_ENC(2, 0, 0, 15, 5), "dbgbcr15_el1" },
293 { SYSREG_ENC(2, 0, 0, 15, 6), "dbgwvr15_el1" },
294 { SYSREG_ENC(2, 0, 0, 15, 7), "dbgwcr15_el1" },
295 { SYSREG_ENC(2, 0, 1, 0, 0), "mdrar_el1" },
296 { SYSREG_ENC(2, 0, 1, 0, 4), "oslar_el1" },
297 { SYSREG_ENC(2, 0, 1, 1, 4), "oslsr_el1" },
298 { SYSREG_ENC(2, 0, 1, 3, 4), "osdlr_el1" },
299 { SYSREG_ENC(2, 0, 1, 4, 4), "dbgprcr_el1" },
300 { SYSREG_ENC(2, 0, 7, 8, 6), "dbgclaimset_el1" },
301 { SYSREG_ENC(2, 0, 7, 9, 6), "dbgclaimclr_el1" },
302 { SYSREG_ENC(2, 0, 7, 14, 6), "dbgauthstatus_el1" },
303 { SYSREG_ENC(2, 2, 0, 0, 0), "teecr32_el1" },
304 { SYSREG_ENC(2, 2, 1, 0, 0), "teehbr32_el1" },
305 { SYSREG_ENC(2, 3, 0, 1, 0), "mdccsr_el0" },
306 { SYSREG_ENC(2, 3, 0, 4, 0), "dbgdtr_el0" },
307 { SYSREG_ENC(2, 3, 0, 5, 0), "dbgdtrrx_el0" },
308 { SYSREG_ENC(2, 4, 0, 7, 0), "dbgvcr32_el2" },
309 { SYSREG_ENC(3, 0, 0, 0, 0), "midr_el1" },
310 { SYSREG_ENC(3, 0, 0, 0, 5), "mpidr_el1" },
311 { SYSREG_ENC(3, 0, 0, 0, 6), "revidr_el1" },
312 { SYSREG_ENC(3, 0, 0, 1, 0), "id_pfr0_el1" },
313 { SYSREG_ENC(3, 0, 0, 1, 1), "id_pfr1_el1" },
314 { SYSREG_ENC(3, 0, 0, 1, 2), "id_dfr0_el1" },
315 { SYSREG_ENC(3, 0, 0, 1, 3), "id_afr0_el1" },
316 { SYSREG_ENC(3, 0, 0, 1, 4), "id_mmfr0_el1" },
317 { SYSREG_ENC(3, 0, 0, 1, 5), "id_mmfr1_el1" },
318 { SYSREG_ENC(3, 0, 0, 1, 6), "id_mmfr2_el1" },
319 { SYSREG_ENC(3, 0, 0, 1, 7), "id_mmfr3_el1" },
320 { SYSREG_ENC(3, 0, 0, 2, 0), "id_isar0_el1" },
321 { SYSREG_ENC(3, 0, 0, 2, 1), "id_isar1_el1" },
322 { SYSREG_ENC(3, 0, 0, 2, 2), "id_isar2_el1" },
323 { SYSREG_ENC(3, 0, 0, 2, 3), "id_isar3_el1" },
324 { SYSREG_ENC(3, 0, 0, 2, 4), "id_isar4_el1" },
325 { SYSREG_ENC(3, 0, 0, 2, 5), "id_isar5_el1" },
326 { SYSREG_ENC(3, 0, 0, 2, 6), "id_mmfr4_el1" },
327 { SYSREG_ENC(3, 0, 0, 2, 7), "id_isar6_el1" },
328 { SYSREG_ENC(3, 0, 0, 3, 0), "mvfr0_el1" },
329 { SYSREG_ENC(3, 0, 0, 3, 1), "mvfr1_el1" },
330 { SYSREG_ENC(3, 0, 0, 3, 2), "mvfr2_el1" },
331 { SYSREG_ENC(3, 0, 0, 3, 4), "id_pfr2_el1" },
332 { SYSREG_ENC(3, 0, 0, 3, 5), "id_dfr1_el1" },
333 { SYSREG_ENC(3, 0, 0, 3, 6), "id_mmfr5_el1" },
334 { SYSREG_ENC(3, 0, 0, 4, 0), "id_aa64pfr0_el1" },
335 { SYSREG_ENC(3, 0, 0, 4, 1), "id_aa64pfr1_el1" },
336 { SYSREG_ENC(3, 0, 0, 5, 0), "id_aa64dfr0_el1" },
337 { SYSREG_ENC(3, 0, 0, 5, 1), "id_aa64dfr1_el1" },
338 { SYSREG_ENC(3, 0, 0, 5, 4), "id_aa64afr0_el1" },
339 { SYSREG_ENC(3, 0, 0, 5, 5), "id_aa64afr1_el1" },
340 { SYSREG_ENC(3, 0, 0, 6, 0), "id_aa64isar0_el1" },
341 { SYSREG_ENC(3, 0, 0, 6, 1), "id_aa64isar1_el1" },
342 { SYSREG_ENC(3, 0, 0, 7, 0), "id_aa64mmfr0_el1" },
343 { SYSREG_ENC(3, 0, 0, 7, 1), "id_aa64mmfr1_el1" },
344 { SYSREG_ENC(3, 0, 0, 7, 2), "id_aa64mmfr2_el1" },
345 { SYSREG_ENC(3, 0, 1, 0, 0), "sctlr_el1" },
346 { SYSREG_ENC(3, 0, 1, 0, 1), "actlr_el1" },
347 { SYSREG_ENC(3, 0, 1, 0, 2), "cpacr_el1" },
348 { SYSREG_ENC(3, 0, 1, 0, 5), "rgsr_el1" },
349 { SYSREG_ENC(3, 0, 1, 0, 6), "gcr_el1" },
350 { SYSREG_ENC(3, 0, 2, 0, 0), "ttbr0_el1" },
351 { SYSREG_ENC(3, 0, 2, 0, 1), "ttbr1_el1" },
352 { SYSREG_ENC(3, 0, 2, 0, 2), "tcr_el1" },
353 { SYSREG_ENC(3, 0, 2, 1, 0), "apiakeylo_el1" },
354 { SYSREG_ENC(3, 0, 2, 1, 1), "apiakeyhi_el1" },
355 { SYSREG_ENC(3, 0, 2, 1, 2), "apibkeylo_el1" },
356 { SYSREG_ENC(3, 0, 2, 1, 3), "apibkeyhi_el1" },
357 { SYSREG_ENC(3, 0, 2, 2, 0), "apdakeylo_el1" },
358 { SYSREG_ENC(3, 0, 2, 2, 1), "apdakeyhi_el1" },
359 { SYSREG_ENC(3, 0, 2, 2, 2), "apdbkeylo_el1" },
360 { SYSREG_ENC(3, 0, 2, 2, 3), "apdbkeyhi_el1" },
361 { SYSREG_ENC(3, 0, 2, 3, 0), "apgakeylo_el1" },
362 { SYSREG_ENC(3, 0, 2, 3, 1), "apgakeyhi_el1" },
363 { SYSREG_ENC(3, 0, 4, 0, 0), "spsr_el1" },
364 { SYSREG_ENC(3, 0, 4, 0, 1), "elr_el1" },
365 { SYSREG_ENC(3, 0, 4, 1, 0), "sp_el0" },
366 { SYSREG_ENC(3, 0, 4, 2, 0), "spsel" },
367 { SYSREG_ENC(3, 0, 4, 2, 2), "currentel" },
368 { SYSREG_ENC(3, 0, 4, 2, 3), "pan" },
369 { SYSREG_ENC(3, 0, 4, 2, 4), "uao" },
370 { SYSREG_ENC(3, 0, 5, 1, 0), "afsr0_el1" },
371 { SYSREG_ENC(3, 0, 5, 1, 1), "afsr1_el1" },
372 { SYSREG_ENC(3, 0, 5, 2, 0), "esr_el1" },
373 { SYSREG_ENC(3, 0, 5, 6, 0), "tfsr_el1" },
374 { SYSREG_ENC(3, 0, 5, 6, 1), "tfsre0_el1" },
375 { SYSREG_ENC(3, 0, 6, 0, 0), "far_el1" },
376 { SYSREG_ENC(3, 0, 7, 4, 0), "par_el1" },
377 { SYSREG_ENC(3, 0, 9, 14, 1), "pmintenset_el1" },
378 { SYSREG_ENC(3, 0, 9, 14, 2), "pmintenclr_el1" },
379 { SYSREG_ENC(3, 0, 10, 2, 0), "mair_el1" },
380 { SYSREG_ENC(3, 0, 10, 3, 0), "amair_el1" },
381 { SYSREG_ENC(3, 0, 10, 4, 0), "lorsa_el1" },
382 { SYSREG_ENC(3, 0, 10, 4, 1), "lorea_el1" },
383 { SYSREG_ENC(3, 0, 10, 4, 2), "lorn_el1" },
384 { SYSREG_ENC(3, 0, 10, 4, 3), "lorc_el1" },
385 { SYSREG_ENC(3, 0, 10, 4, 7), "lorid_el1" },
386 { SYSREG_ENC(3, 0, 12, 0, 0), "vbar_el1" },
387 { SYSREG_ENC(3, 0, 12, 0, 1), "rvbar_el1" },
388 { SYSREG_ENC(3, 0, 12, 0, 2), "rmr_el1" },
389 { SYSREG_ENC(3, 0, 12, 1, 0), "isr_el1" },
390 { SYSREG_ENC(3, 0, 13, 0, 1), "contextidr_el1" },
391 { SYSREG_ENC(3, 0, 13, 0, 4), "tpidr_el1" },
392 { SYSREG_ENC(3, 0, 13, 0, 7), "scxtnum_el1" },
393 { SYSREG_ENC(3, 0, 14, 1, 0), "cntkctl_el1" },
394 { SYSREG_ENC(3, 1, 0, 0, 0), "ccsidr_el1" },
395 { SYSREG_ENC(3, 1, 0, 0, 1), "clidr_el1" },
396 { SYSREG_ENC(3, 1, 0, 0, 2), "ccsidr2_el1" },
397 { SYSREG_ENC(3, 1, 0, 0, 4), "gmid_el1" },
398 { SYSREG_ENC(3, 1, 0, 0, 7), "aidr_el1" },
399 { SYSREG_ENC(3, 2, 0, 0, 0), "csselr_el1" },
400 { SYSREG_ENC(3, 3, 0, 0, 1), "ctr_el0" },
401 { SYSREG_ENC(3, 3, 0, 0, 7), "dczid_el0" },
402 { SYSREG_ENC(3, 3, 2, 4, 0), "rndr" },
403 { SYSREG_ENC(3, 3, 2, 4, 1), "rndrrs" },
404 { SYSREG_ENC(3, 3, 4, 2, 0), "nzcv" },
405 { SYSREG_ENC(3, 3, 4, 2, 1), "daif" },
406 { SYSREG_ENC(3, 3, 4, 2, 5), "dit" },
407 { SYSREG_ENC(3, 3, 4, 2, 6), "ssbs" },
408 { SYSREG_ENC(3, 3, 4, 2, 7), "tco" },
409 { SYSREG_ENC(3, 3, 4, 4, 0), "fpcr" },
410 { SYSREG_ENC(3, 3, 4, 4, 1), "fpsr" },
411 { SYSREG_ENC(3, 3, 4, 5, 0), "dspsr_el0" },
412 { SYSREG_ENC(3, 3, 4, 5, 1), "dlr_el0" },
413 { SYSREG_ENC(3, 3, 9, 12, 0), "pmcr_el0" },
414 { SYSREG_ENC(3, 3, 9, 12, 1), "pmcntenset_el0" },
415 { SYSREG_ENC(3, 3, 9, 12, 2), "pmcntenclr_el0" },
416 { SYSREG_ENC(3, 3, 9, 12, 3), "pmovsclr_el0" },
417 { SYSREG_ENC(3, 3, 9, 12, 4), "pmswinc_el0" },
418 { SYSREG_ENC(3, 3, 9, 12, 5), "pmselr_el0" },
419 { SYSREG_ENC(3, 3, 9, 12, 6), "pmceid0_el0" },
420 { SYSREG_ENC(3, 3, 9, 12, 7), "pmceid1_el0" },
421 { SYSREG_ENC(3, 3, 9, 13, 0), "pmccntr_el0" },
422 { SYSREG_ENC(3, 3, 9, 13, 1), "pmxevtyper_el0" },
423 { SYSREG_ENC(3, 3, 9, 13, 2), "pmxevcntr_el0" },
424 { SYSREG_ENC(3, 3, 9, 14, 0), "pmuserenr_el0" },
425 { SYSREG_ENC(3, 3, 9, 14, 3), "pmovsset_el0" },
426 { SYSREG_ENC(3, 3, 13, 0, 2), "tpidr_el0" },
427 { SYSREG_ENC(3, 3, 13, 0, 3), "tpidrro_el0" },
428 { SYSREG_ENC(3, 3, 13, 0, 7), "scxtnum_el0" },
429 { SYSREG_ENC(3, 3, 14, 0, 0), "cntfrq_el0" },
430 { SYSREG_ENC(3, 3, 14, 0, 1), "cntpct_el0" },
431 { SYSREG_ENC(3, 3, 14, 0, 2), "cntvct_el0" },
432 { SYSREG_ENC(3, 3, 14, 2, 0), "cntp_tval_el0" },
433 { SYSREG_ENC(3, 3, 14, 2, 1), "cntp_ctl_el0" },
434 { SYSREG_ENC(3, 3, 14, 2, 2), "cntp_cval_el0" },
435 { SYSREG_ENC(3, 3, 14, 3, 0), "cntv_tval_el0" },
436 { SYSREG_ENC(3, 3, 14, 3, 1), "cntv_ctl_el0" },
437 { SYSREG_ENC(3, 3, 14, 3, 2), "cntv_cval_el0" },
438 { SYSREG_ENC(3, 3, 14, 8, 0), "pmevcntr0_el0" },
439 { SYSREG_ENC(3, 3, 14, 8, 1), "pmevcntr1_el0" },
440 { SYSREG_ENC(3, 3, 14, 8, 2), "pmevcntr2_el0" },
441 { SYSREG_ENC(3, 3, 14, 8, 3), "pmevcntr3_el0" },
442 { SYSREG_ENC(3, 3, 14, 8, 4), "pmevcntr4_el0" },
443 { SYSREG_ENC(3, 3, 14, 8, 5), "pmevcntr5_el0" },
444 { SYSREG_ENC(3, 3, 14, 8, 6), "pmevcntr6_el0" },
445 { SYSREG_ENC(3, 3, 14, 8, 7), "pmevcntr7_el0" },
446 { SYSREG_ENC(3, 3, 14, 9, 0), "pmevcntr8_el0" },
447 { SYSREG_ENC(3, 3, 14, 9, 1), "pmevcntr9_el0" },
448 { SYSREG_ENC(3, 3, 14, 9, 2), "pmevcntr10_el0" },
449 { SYSREG_ENC(3, 3, 14, 9, 3), "pmevcntr11_el0" },
450 { SYSREG_ENC(3, 3, 14, 9, 4), "pmevcntr12_el0" },
451 { SYSREG_ENC(3, 3, 14, 9, 5), "pmevcntr13_el0" },
452 { SYSREG_ENC(3, 3, 14, 9, 6), "pmevcntr14_el0" },
453 { SYSREG_ENC(3, 3, 14, 9, 7), "pmevcntr15_el0" },
454 { SYSREG_ENC(3, 3, 14, 10, 0), "pmevcntr16_el0" },
455 { SYSREG_ENC(3, 3, 14, 10, 1), "pmevcntr17_el0" },
456 { SYSREG_ENC(3, 3, 14, 10, 2), "pmevcntr18_el0" },
457 { SYSREG_ENC(3, 3, 14, 10, 3), "pmevcntr19_el0" },
458 { SYSREG_ENC(3, 3, 14, 10, 4), "pmevcntr20_el0" },
459 { SYSREG_ENC(3, 3, 14, 10, 5), "pmevcntr21_el0" },
460 { SYSREG_ENC(3, 3, 14, 10, 6), "pmevcntr22_el0" },
461 { SYSREG_ENC(3, 3, 14, 10, 7), "pmevcntr23_el0" },
462 { SYSREG_ENC(3, 3, 14, 11, 0), "pmevcntr24_el0" },
463 { SYSREG_ENC(3, 3, 14, 11, 1), "pmevcntr25_el0" },
464 { SYSREG_ENC(3, 3, 14, 11, 2), "pmevcntr26_el0" },
465 { SYSREG_ENC(3, 3, 14, 11, 3), "pmevcntr27_el0" },
466 { SYSREG_ENC(3, 3, 14, 11, 4), "pmevcntr28_el0" },
467 { SYSREG_ENC(3, 3, 14, 11, 5), "pmevcntr29_el0" },
468 { SYSREG_ENC(3, 3, 14, 11, 6), "pmevcntr30_el0" },
469 { SYSREG_ENC(3, 3, 14, 12, 0), "pmevtyper0_el0" },
470 { SYSREG_ENC(3, 3, 14, 12, 1), "pmevtyper1_el0" },
471 { SYSREG_ENC(3, 3, 14, 12, 2), "pmevtyper2_el0" },
472 { SYSREG_ENC(3, 3, 14, 12, 3), "pmevtyper3_el0" },
473 { SYSREG_ENC(3, 3, 14, 12, 4), "pmevtyper4_el0" },
474 { SYSREG_ENC(3, 3, 14, 12, 5), "pmevtyper5_el0" },
475 { SYSREG_ENC(3, 3, 14, 12, 6), "pmevtyper6_el0" },
476 { SYSREG_ENC(3, 3, 14, 12, 7), "pmevtyper7_el0" },
477 { SYSREG_ENC(3, 3, 14, 13, 0), "pmevtyper8_el0" },
478 { SYSREG_ENC(3, 3, 14, 13, 1), "pmevtyper9_el0" },
479 { SYSREG_ENC(3, 3, 14, 13, 2), "pmevtyper10_el0" },
480 { SYSREG_ENC(3, 3, 14, 13, 3), "pmevtyper11_el0" },
481 { SYSREG_ENC(3, 3, 14, 13, 4), "pmevtyper12_el0" },
482 { SYSREG_ENC(3, 3, 14, 13, 5), "pmevtyper13_el0" },
483 { SYSREG_ENC(3, 3, 14, 13, 6), "pmevtyper14_el0" },
484 { SYSREG_ENC(3, 3, 14, 13, 7), "pmevtyper15_el0" },
485 { SYSREG_ENC(3, 3, 14, 14, 0), "pmevtyper16_el0" },
486 { SYSREG_ENC(3, 3, 14, 14, 1), "pmevtyper17_el0" },
487 { SYSREG_ENC(3, 3, 14, 14, 2), "pmevtyper18_el0" },
488 { SYSREG_ENC(3, 3, 14, 14, 3), "pmevtyper19_el0" },
489 { SYSREG_ENC(3, 3, 14, 14, 4), "pmevtyper20_el0" },
490 { SYSREG_ENC(3, 3, 14, 14, 5), "pmevtyper21_el0" },
491 { SYSREG_ENC(3, 3, 14, 14, 6), "pmevtyper22_el0" },
492 { SYSREG_ENC(3, 3, 14, 14, 7), "pmevtyper23_el0" },
493 { SYSREG_ENC(3, 3, 14, 15, 0), "pmevtyper24_el0" },
494 { SYSREG_ENC(3, 3, 14, 15, 1), "pmevtyper25_el0" },
495 { SYSREG_ENC(3, 3, 14, 15, 2), "pmevtyper26_el0" },
496 { SYSREG_ENC(3, 3, 14, 15, 3), "pmevtyper27_el0" },
497 { SYSREG_ENC(3, 3, 14, 15, 4), "pmevtyper28_el0" },
498 { SYSREG_ENC(3, 3, 14, 15, 5), "pmevtyper29_el0" },
499 { SYSREG_ENC(3, 3, 14, 15, 6), "pmevtyper30_el0" },
500 { SYSREG_ENC(3, 3, 14, 15, 7), "pmccfiltr_el0" },
501 { SYSREG_ENC(3, 4, 0, 0, 0), "vpidr_el2" },
502 { SYSREG_ENC(3, 4, 0, 0, 5), "vmpidr_el2" },
503 { SYSREG_ENC(3, 4, 1, 0, 0), "sctlr_el2" },
504 { SYSREG_ENC(3, 4, 1, 0, 1), "actlr_el2" },
505 { SYSREG_ENC(3, 4, 1, 1, 0), "hcr_el2" },
506 { SYSREG_ENC(3, 4, 1, 1, 1), "mdcr_el2" },
507 { SYSREG_ENC(3, 4, 1, 1, 2), "cptr_el2" },
508 { SYSREG_ENC(3, 4, 1, 1, 3), "hstr_el2" },
509 { SYSREG_ENC(3, 4, 1, 1, 4), "hfgrtr_el2" },
510 { SYSREG_ENC(3, 4, 1, 1, 5), "hfgwtr_el2" },
511 { SYSREG_ENC(3, 4, 1, 1, 6), "hfgitr_el2" },
512 { SYSREG_ENC(3, 4, 1, 1, 7), "hacr_el2" },
513 { SYSREG_ENC(3, 4, 2, 0, 0), "ttbr0_el2" },
514 { SYSREG_ENC(3, 4, 2, 0, 1), "ttbr1_el2" },
515 { SYSREG_ENC(3, 4, 2, 0, 2), "tcr_el2" },
516 { SYSREG_ENC(3, 4, 2, 1, 0), "vttbr_el2" },
517 { SYSREG_ENC(3, 4, 2, 1, 2), "vtcr_el2" },
518 { SYSREG_ENC(3, 4, 2, 2, 0), "vncr_el2" },
519 { SYSREG_ENC(3, 4, 2, 6, 0), "vsttbr_el2" },
520 { SYSREG_ENC(3, 4, 2, 6, 2), "vstcr_el2" },
521 { SYSREG_ENC(3, 4, 3, 0, 0), "dacr32_el2" },
522 { SYSREG_ENC(3, 4, 3, 1, 4), "hdfgrtr_el2" },
523 { SYSREG_ENC(3, 4, 3, 1, 5), "hdfgwtr_el2" },
524 { SYSREG_ENC(3, 4, 3, 1, 6), "hafgrtr_el2" },
525 { SYSREG_ENC(3, 4, 4, 0, 0), "spsr_el2" },
526 { SYSREG_ENC(3, 4, 4, 0, 1), "elr_el2" },
527 { SYSREG_ENC(3, 4, 4, 1, 0), "sp_el1" },
528 { SYSREG_ENC(3, 4, 4, 3, 0), "spsr_irq" },
529 { SYSREG_ENC(3, 4, 4, 3, 1), "spsr_abt" },
530 { SYSREG_ENC(3, 4, 4, 3, 2), "spsr_und" },
531 { SYSREG_ENC(3, 4, 4, 3, 3), "spsr_fiq" },
532 { SYSREG_ENC(3, 4, 5, 0, 1), "ifsr32_el2" },
533 { SYSREG_ENC(3, 4, 5, 1, 0), "afsr0_el2" },
534 { SYSREG_ENC(3, 4, 5, 1, 1), "afsr1_el2" },
535 { SYSREG_ENC(3, 4, 5, 2, 0), "esr_el2" },
536 { SYSREG_ENC(3, 4, 5, 3, 0), "fpexc32_el2" },
537 { SYSREG_ENC(3, 4, 5, 6, 0), "tfsr_el2" },
538 { SYSREG_ENC(3, 4, 6, 0, 0), "far_el2" },
539 { SYSREG_ENC(3, 4, 6, 0, 4), "hpfar_el2" },
540 { SYSREG_ENC(3, 4, 10, 2, 0), "mair_el2" },
541 { SYSREG_ENC(3, 4, 10, 3, 0), "amair_el2" },
542 { SYSREG_ENC(3, 4, 12, 0, 0), "vbar_el2" },
543 { SYSREG_ENC(3, 4, 12, 0, 1), "rvbar_el2" },
544 { SYSREG_ENC(3, 4, 12, 0, 2), "rmr_el2" },
545 { SYSREG_ENC(3, 4, 13, 0, 1), "contextidr_el2" },
546 { SYSREG_ENC(3, 4, 13, 0, 2), "tpidr_el2" },
547 { SYSREG_ENC(3, 4, 13, 0, 7), "scxtnum_el2" },
548 { SYSREG_ENC(3, 4, 14, 0, 3), "cntvoff_el2" },
549 { SYSREG_ENC(3, 4, 14, 1, 0), "cnthctl_el2" },
550 { SYSREG_ENC(3, 4, 14, 2, 0), "cnthp_tval_el2" },
551 { SYSREG_ENC(3, 4, 14, 2, 1), "cnthp_ctl_el2" },
552 { SYSREG_ENC(3, 4, 14, 2, 2), "cnthp_cval_el2" },
553 { SYSREG_ENC(3, 4, 14, 3, 0), "cnthv_tval_el2" },
554 { SYSREG_ENC(3, 4, 14, 3, 1), "cnthv_ctl_el2" },
555 { SYSREG_ENC(3, 4, 14, 3, 2), "cnthv_cval_el2" },
556 { SYSREG_ENC(3, 4, 14, 4, 0), "cnthvs_tval_el2" },
557 { SYSREG_ENC(3, 4, 14, 4, 1), "cnthvs_ctl_el2" },
558 { SYSREG_ENC(3, 4, 14, 4, 2), "cnthvs_cval_el2" },
559 { SYSREG_ENC(3, 4, 14, 5, 0), "cnthps_tval_el2" },
560 { SYSREG_ENC(3, 4, 14, 5, 1), "cnthps_ctl_el2" },
561 { SYSREG_ENC(3, 4, 14, 5, 2), "cnthps_cval_el2" },
562 { SYSREG_ENC(3, 6, 1, 0, 0), "sctlr_el3" },
563 { SYSREG_ENC(3, 6, 1, 0, 1), "actlr_el3" },
564 { SYSREG_ENC(3, 6, 1, 1, 0), "scr_el3" },
565 { SYSREG_ENC(3, 6, 1, 1, 1), "sder32_el3" },
566 { SYSREG_ENC(3, 6, 1, 1, 2), "cptr_el3" },
567 { SYSREG_ENC(3, 6, 1, 3, 1), "mdcr_el3" },
568 { SYSREG_ENC(3, 6, 2, 0, 0), "ttbr0_el3" },
569 { SYSREG_ENC(3, 6, 2, 0, 2), "tcr_el3" },
570 { SYSREG_ENC(3, 6, 4, 0, 0), "spsr_el3" },
571 { SYSREG_ENC(3, 6, 4, 0, 1), "elr_el3" },
572 { SYSREG_ENC(3, 6, 4, 1, 0), "sp_el2" },
573 { SYSREG_ENC(3, 6, 5, 1, 0), "afsr0_el3" },
574 { SYSREG_ENC(3, 6, 5, 1, 1), "afsr1_el3" },
575 { SYSREG_ENC(3, 6, 5, 2, 0), "esr_el3" },
576 { SYSREG_ENC(3, 6, 5, 6, 0), "tfsr_el3" },
577 { SYSREG_ENC(3, 6, 6, 0, 0), "far_el3" },
578 { SYSREG_ENC(3, 6, 10, 2, 0), "mair_el3" },
579 { SYSREG_ENC(3, 6, 10, 3, 0), "amair_el3" },
580 { SYSREG_ENC(3, 6, 12, 0, 0), "vbar_el3" },
581 { SYSREG_ENC(3, 6, 12, 0, 1), "rvbar_el3" },
582 { SYSREG_ENC(3, 6, 12, 0, 2), "rmr_el3" },
583 { SYSREG_ENC(3, 6, 13, 0, 2), "tpidr_el3" },
584 { SYSREG_ENC(3, 6, 13, 0, 7), "scxtnum_el3" },
585 { SYSREG_ENC(3, 7, 14, 2, 0), "cntps_tval_el1" },
586 { SYSREG_ENC(3, 7, 14, 2, 1), "cntps_ctl_el1" },
587 { SYSREG_ENC(3, 7, 14, 2, 2), "cntps_cval_el1" }
588 };
589
590 static const char *
sysregname_bsearch(uint32_t code)591 sysregname_bsearch(uint32_t code)
592 {
593 const struct sysreg_table *base, *p;
594 unsigned int lim;
595 int32_t cmp;
596
597 base = sysreg_table;
598 for (lim = __arraycount(sysreg_table); lim != 0; lim >>= 1) {
599 p = base + (lim >> 1);
600 cmp = code - p->code;
601 if (cmp == 0)
602 return p->regname;
603 if (cmp > 0) {
604 base = p + 1;
605 lim--;
606 }
607 }
608 return NULL;
609 }
610
611 #define SYSREG_OP_READ 0x01
612 #define SYSREG_OP_WRITE 0x02
613
614 static const char *
sysregname(char * buf,size_t buflen,uint32_t rw,uint64_t op0,uint64_t op1,uint64_t CRn,uint64_t CRm,uint64_t op2)615 sysregname(char *buf, size_t buflen, uint32_t rw,
616 uint64_t op0, uint64_t op1, uint64_t CRn, uint64_t CRm, uint64_t op2)
617 {
618 const char *name;
619 uint32_t code;
620
621 code = SYSREG_ENC(op0, op1, CRn, CRm, op2);
622
623 /* special case for dbgdtrrx_el0(RO) and dbgdtrtx_el0(WO) */
624 if (code == SYSREG_ENC(2,3,0,5,0)) {
625 if (rw & SYSREG_OP_WRITE)
626 return "dbgdtrtx_el0";
627 return "dbgdtrrx_el0";
628 }
629
630 name = sysregname_bsearch(code);
631 if (name == NULL) {
632 #define SYSREGNAMEBUFLEN sizeof("s99_99_c99_c99_99")
633 snprintf(buf, buflen, "s%u_%u_c%u_c%u_%u",
634 (u_int)op0, (u_int)op1, (u_int)CRn, (u_int)CRm, (u_int)op2);
635 return buf;
636 }
637 return name;
638 }
639 #define RSYSREGNAME(buf, buflen, op0, op1, CRn, CRm, op2) \
640 sysregname(buf, buflen, SYSREG_OP_READ, op0, op1, CRn, CRm, op2)
641 #define WSYSREGNAME(buf, buflen, op0, op1, CRn, CRm, op2) \
642 sysregname(buf, buflen, SYSREG_OP_WRITE, op0, op1, CRn, CRm, op2)
643
644
645 static uint64_t
SignExtend(int bitwidth,uint64_t imm,unsigned int multiply)646 SignExtend(int bitwidth, uint64_t imm, unsigned int multiply)
647 {
648 const uint64_t signbit = ((uint64_t)1 << (bitwidth - 1));
649 const uint64_t immmax = signbit << 1;
650
651 if (imm & signbit)
652 imm -= immmax;
653 return imm * multiply;
654 }
655
656 static uint64_t
ZeroExtend(int bitwidth,uint64_t imm,unsigned int multiply)657 ZeroExtend(int bitwidth, uint64_t imm, unsigned int multiply)
658 {
659 return imm * multiply;
660 }
661
662 /* rotate right. if n < 0, rotate left. */
663 static uint64_t
rotate(int bitwidth,uint64_t v,int n)664 rotate(int bitwidth, uint64_t v, int n)
665 {
666 uint64_t result;
667
668 n &= (bitwidth - 1);
669 result = (((v << (bitwidth - n)) | (v >> n)));
670 if (bitwidth < 64)
671 result &= ((1ULL << bitwidth) - 1);
672 return result;
673 }
674
675 static bool
ValidBitMasks(uint64_t sf,uint64_t n,uint64_t imms,uint64_t immr)676 ValidBitMasks(uint64_t sf, uint64_t n, uint64_t imms, uint64_t immr)
677 {
678 int esize, len;
679
680 if ((sf == 0) && (n != 0))
681 return false;
682
683 len = fls64((n << 6) + (~imms & 0x3f)) - 1;
684 if (len < 0)
685 return false;
686
687 esize = (1 << len);
688 imms &= (esize - 1);
689 if (imms == (uint64_t)(esize - 1))
690 return false;
691
692 return true;
693 }
694
695 static uint64_t
DecodeBitMasks(uint64_t sf,uint64_t n,uint64_t imms,uint64_t immr)696 DecodeBitMasks(uint64_t sf, uint64_t n, uint64_t imms, uint64_t immr)
697 {
698 const int bitwidth = (sf == 0) ? 32 : 64;
699 uint64_t result;
700 int esize, len;
701
702 len = fls64((n << 6) + (~imms & 0x3f)) - 1;
703 esize = (1 << len);
704 imms &= (esize - 1);
705 immr &= (esize - 1);
706 result = rotate(esize, (1ULL << (imms + 1)) - 1, immr);
707 while (esize < bitwidth) {
708 result |= (result << esize);
709 esize <<= 1;
710 }
711 if (sf == 0)
712 result &= ((1ULL << bitwidth) - 1);
713 return result;
714 }
715
716 static bool
MoveWidePreferred(uint64_t sf,uint64_t n,uint64_t imms,uint64_t immr)717 MoveWidePreferred(uint64_t sf, uint64_t n, uint64_t imms, uint64_t immr)
718 {
719 #if 1
720 uint64_t x = DecodeBitMasks(sf, n, imms, immr);
721
722 if (sf == 0)
723 x &= 0xffffffff;
724 if (((x & 0xffffffffffff0000UL) == 0) ||
725 ((x & 0xffffffff0000ffffUL) == 0) ||
726 ((x & 0xffff0000ffffffffUL) == 0) ||
727 ((x & 0x0000ffffffffffffUL) == 0))
728 return true;
729
730 x = ~x;
731 if (sf == 0)
732 x &= 0xffffffff;
733 if (((x & 0xffffffffffff0000UL) == 0) ||
734 ((x & 0xffffffff0000ffffUL) == 0) ||
735 ((x & 0xffff0000ffffffffUL) == 0) ||
736 ((x & 0x0000ffffffffffffUL) == 0))
737 return true;
738
739 return false;
740 #else
741 const int bitwidth = (sf == 0) ? 32 : 64;
742
743 if ((sf != 0) && (n == 0))
744 return false;
745 if ((sf == 0) && ((n != 0) || (immr > 0x1f)))
746 return false;
747 if (imms < 16)
748 return ((-immr & 15) <= (15 - imms));
749 if (imms >= (uint64_t)(bitwidth - 15))
750 return ((immr & 15) <= (imms - (bitwidth - 15)));
751 return false;
752 #endif
753 }
754
755 static bool
BFXPreferred(uint64_t sf,uint64_t opc,uint64_t imms,uint64_t immr)756 BFXPreferred(uint64_t sf, uint64_t opc, uint64_t imms, uint64_t immr)
757 {
758 const uint64_t bitwidth = (sf == 0) ? 32 : 64;
759
760 if (imms < immr)
761 return false;
762 if (imms == (bitwidth - 1))
763 return false;
764 if (immr == 0) {
765 if ((sf == 0) && ((imms == 7) || (imms == 15)))
766 return false;
767 if ((sf != 0) && (opc == 0) &&
768 ((imms == 7) || (imms == 15) || (imms == 31)))
769 return false;
770 }
771
772 return true;
773 }
774
775 #define SHIFTOP2(s, op1, op2) \
776 ((const char *[]){ op1, op2 })[(s) & 1]
777 #define SHIFTOP4(s, op1, op2, op3, op4) \
778 ((const char *[]){ op1, op2, op3, op4 })[(s) & 3]
779 #define SHIFTOP8(s, op1, op2, op3, op4, op5, op6, op7, op8) \
780 ((const char *[]){ op1, op2, op3, op4, op5, op6, op7, op8 })[(s) & 7]
781
782 static const char *
DecodeShift(uint64_t shift)783 DecodeShift(uint64_t shift)
784 {
785 return SHIFTOP4(shift, "lsl", "lsr", "asr", "ror");
786 }
787
788 #ifdef DISASM_WITH_COMMENT
789 #define UNDEFINED(pc, insn, comment) \
790 PRINTF(".insn\t0x%08x\t# %s\n", insn, comment);
791 #else
792 #define UNDEFINED(pc, insn, comment) \
793 PRINTF(".insn\t0x%08x\n", insn);
794 #endif
795
796 static void
extendreg_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t sf,uint64_t Rm,uint64_t option,uint64_t imm3,uint64_t Rn,uint64_t Rd,const char * op,const char * z_op)797 extendreg_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
798 uint64_t sf, uint64_t Rm, uint64_t option, uint64_t imm3,
799 uint64_t Rn, uint64_t Rd,
800 const char *op, const char *z_op)
801 {
802 const int r = (sf == 0) ? 0 : ((option & 3) == 3) ? 1 : 0;
803
804 if ((z_op != NULL) && (Rd == 31)) {
805 PRINTF("%s\t", z_op);
806 } else {
807 PRINTF("%s\t%s, ", op, SREGNAME(sf, Rd));
808 }
809
810 PRINTF("%s, %s", SREGNAME(sf, Rn), ZREGNAME(r, Rm));
811
812 if ((Rd == 31) || (Rn == 31)) {
813 if (imm3 == 0) {
814 if (!((sf == 0) && (option == 2)) &&
815 !((sf != 0) && (option == 3))) {
816 PRINTF(", %s",
817 SHIFTOP8(option,
818 "uxtb", "uxth", "uxtw", "uxtx",
819 "sxtb", "sxth", "sxtw", "sxtx"));
820 }
821 } else {
822 PRINTF(", %s #%u",
823 SHIFTOP8(option,
824 "uxtb", "uxth", "lsl", "lsl",
825 "sxtb", "sxth", "sxtw", "sxtx"),
826 (u_int)imm3);
827 }
828 } else {
829 PRINTF(", %s",
830 SHIFTOP8(option,
831 "uxtb", "uxth", "uxtw", "uxtx",
832 "sxtb", "sxth", "sxtw", "sxtx"));
833 if (imm3 != 0)
834 PRINTF(" #%u", (u_int)imm3);
835 }
836 PRINTF("\n");
837 }
838
839 static void
shiftreg_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t sf,uint64_t shift,uint64_t Rm,uint64_t imm6,uint64_t Rn,uint64_t Rd,const char * dnm_op,const char * dzm_op,const char * znm_op)840 shiftreg_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
841 uint64_t sf, uint64_t shift, uint64_t Rm, uint64_t imm6,
842 uint64_t Rn, uint64_t Rd,
843 const char *dnm_op, const char *dzm_op, const char *znm_op)
844 {
845 if ((sf == 0) && (imm6 >= 32)) {
846 UNDEFINED(pc, insn, "illegal imm6");
847 return;
848 }
849
850 if ((dzm_op != NULL) && (Rn == 31)) {
851 PRINTF("%s\t%s, %s",
852 dzm_op,
853 ZREGNAME(sf, Rd),
854 ZREGNAME(sf, Rm));
855 } else if ((znm_op != NULL) && (Rd == 31)) {
856 PRINTF("%s\t%s, %s",
857 znm_op,
858 ZREGNAME(sf, Rn),
859 ZREGNAME(sf, Rm));
860 } else {
861 PRINTF("%s\t%s, %s, %s",
862 dnm_op,
863 ZREGNAME(sf, Rd),
864 ZREGNAME(sf, Rn),
865 ZREGNAME(sf, Rm));
866 }
867 if (imm6 != 0)
868 PRINTF(", %s #%u", DecodeShift(shift), (u_int)imm6);
869 PRINTF("\n");
870 }
871
872 static inline int
regoffset_option_to_r(uint64_t option)873 regoffset_option_to_r(uint64_t option)
874 {
875 switch (option) {
876 case 2:
877 case 6:
878 return 0;
879 case 3:
880 case 7:
881 return 1;
882 default:
883 return -1;
884 }
885 }
886
887 static void
regoffset_b_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t Rm,uint64_t option,uint64_t shift,uint64_t Rn,uint64_t Rt,const char * op)888 regoffset_b_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
889 uint64_t Rm, uint64_t option, uint64_t shift, uint64_t Rn, uint64_t Rt,
890 const char *op)
891 {
892 int r;
893
894 if ((r = regoffset_option_to_r(option)) < 0) {
895 UNDEFINED(pc, insn, "illegal option");
896 return;
897 }
898
899 if (shift == 0) {
900 PRINTF("%s\t%s, [%s,%s%s]\n",
901 op,
902 ZREGNAME(0, Rt),
903 SREGNAME(1, Rn),
904 ZREGNAME(r, Rm),
905 SHIFTOP8(option,
906 "", "", ",uxtw", "", "", "", ",sxtw", ",sxtx"));
907 } else {
908 PRINTF("%s\t%s, [%s,%s,%s #%d]\n",
909 op,
910 ZREGNAME(0, Rt),
911 SREGNAME(1, Rn),
912 ZREGNAME(r, Rm),
913 SHIFTOP8(option,
914 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
915 0);
916 }
917 }
918
919 static void
regoffset_h_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t Rm,uint64_t option,uint64_t shift,uint64_t Rn,uint64_t Rt,uint64_t RtSz,const char * op)920 regoffset_h_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
921 uint64_t Rm, uint64_t option, uint64_t shift, uint64_t Rn, uint64_t Rt,
922 uint64_t RtSz, const char *op)
923 {
924 int r;
925
926 if ((r = regoffset_option_to_r(option)) < 0) {
927 UNDEFINED(pc, insn, "illegal option");
928 return;
929 }
930
931 if ((shift == 0) && (option == 3)) {
932 PRINTF("%s\t%s, [%s,%s]\n",
933 op,
934 ZREGNAME(RtSz, Rt),
935 SREGNAME(1, Rn),
936 ZREGNAME(r, Rm));
937 } else if (shift == 0) {
938 PRINTF("%s\t%s, [%s,%s,%s]\n",
939 op,
940 ZREGNAME(RtSz, Rt),
941 SREGNAME(1, Rn),
942 ZREGNAME(r, Rm),
943 SHIFTOP8(option,
944 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"));
945 } else {
946 PRINTF("%s\t%s, [%s,%s,%s #%u]\n",
947 op,
948 ZREGNAME(RtSz, Rt),
949 SREGNAME(1, Rn),
950 ZREGNAME(r, Rm),
951 SHIFTOP8(option,
952 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
953 (u_int)shift);
954 }
955 }
956
957 static void
regoffset_w_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t Rm,uint64_t option,uint64_t shift,uint64_t Rn,uint64_t Rt,const char * op)958 regoffset_w_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
959 uint64_t Rm, uint64_t option, uint64_t shift, uint64_t Rn, uint64_t Rt,
960 const char *op)
961 {
962 int r;
963
964 if ((r = regoffset_option_to_r(option)) < 0) {
965 UNDEFINED(pc, insn, "illegal option");
966 return;
967 }
968
969 if ((shift == 0) && (option == 3)) {
970 PRINTF("%s\t%s, [%s,%s]\n",
971 op,
972 ZREGNAME(1, Rt),
973 SREGNAME(1, Rn),
974 ZREGNAME(r, Rm));
975 } else if (shift == 0) {
976 PRINTF("%s\t%s, [%s,%s,%s]\n",
977 op,
978 ZREGNAME(1, Rt),
979 SREGNAME(1, Rn),
980 ZREGNAME(r, Rm),
981 SHIFTOP8(option,
982 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"));
983 } else {
984 PRINTF("%s\t%s, [%s,%s,%s #%u]\n",
985 op,
986 ZREGNAME(1, Rt),
987 SREGNAME(1, Rn),
988 ZREGNAME(r, Rm),
989 SHIFTOP8(option,
990 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
991 (u_int)shift * 2);
992 }
993 }
994
995 static void
regoffset_x_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t size,uint64_t Rm,uint64_t option,uint64_t shift,uint64_t Rn,uint64_t Rt,const char * op)996 regoffset_x_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
997 uint64_t size, uint64_t Rm, uint64_t option, uint64_t shift,
998 uint64_t Rn, uint64_t Rt,
999 const char *op)
1000 {
1001 int r;
1002
1003 if ((r = regoffset_option_to_r(option)) < 0) {
1004 UNDEFINED(pc, insn, "illegal option");
1005 return;
1006 }
1007
1008 if (shift == 0) {
1009 PRINTF("%s\t%s, [%s,%s%s]\n",
1010 op,
1011 ZREGNAME(size, Rt),
1012 SREGNAME(1, Rn),
1013 ZREGNAME(r, Rm),
1014 SHIFTOP8(option,
1015 "", "", ",uxtw", "", "", "", ",sxtw", ",sxtx"));
1016 } else {
1017 uint64_t amount = 2 + size;
1018 PRINTF("%s\t%s, [%s,%s,%s #%u]\n",
1019 op,
1020 ZREGNAME(size, Rt),
1021 SREGNAME(1, Rn),
1022 ZREGNAME(r, Rm),
1023 SHIFTOP8(option,
1024 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
1025 (u_int)amount);
1026 }
1027 }
1028
1029 static void
addsub_imm_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t sf,uint64_t shift,uint64_t imm12,uint64_t Rn,uint64_t Rd,const char * op,const char * zop)1030 addsub_imm_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
1031 uint64_t sf, uint64_t shift, uint64_t imm12, uint64_t Rn, uint64_t Rd,
1032 const char *op, const char *zop)
1033 {
1034 if (shift & 2) {
1035 UNDEFINED(pc, insn, "illegal shift");
1036 return;
1037 }
1038
1039 if (Rd == 31) {
1040 PRINTF("%s\t%s, #0x%"PRIx64"%s\n",
1041 zop,
1042 SREGNAME(sf, Rn),
1043 ZeroExtend(12, imm12, 1),
1044 SHIFTOP4(shift, "", ", lsl #12", "", ""));
1045 } else {
1046 PRINTF("%s\t%s, %s, #0x%"PRIx64"%s\n",
1047 op,
1048 ZREGNAME(sf, Rd),
1049 SREGNAME(sf, Rn),
1050 ZeroExtend(12, imm12, 1),
1051 SHIFTOP4(shift, "", ", lsl #12", "", ""));
1052 }
1053 }
1054
1055 static void
csetsel_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t sf,uint64_t Rm,uint64_t cond,uint64_t Rn,uint64_t Rd,const char * op,const char * op2,const char * op3)1056 csetsel_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
1057 uint64_t sf, uint64_t Rm, uint64_t cond, uint64_t Rn, uint64_t Rd,
1058 const char *op, const char *op2, const char *op3)
1059 {
1060 if ((Rn == Rm) && (Rn != 31) && ((cond & 0xe) != 0x0e)) {
1061 PRINTF("%s\t%s, %s, %s\n",
1062 op3,
1063 ZREGNAME(sf, Rd),
1064 ZREGNAME(sf, Rn),
1065 IVCONDNAME(cond));
1066 } else if ((Rn == Rm) && (Rn == 31) && ((cond & 0xe) != 0x0e)) {
1067 PRINTF("%s\t%s, %s\n",
1068 op2,
1069 ZREGNAME(sf, Rd),
1070 IVCONDNAME(cond));
1071 } else {
1072 PRINTF("%s\t%s, %s, %s, %s\n",
1073 op,
1074 ZREGNAME(sf, Rd),
1075 ZREGNAME(sf, Rn),
1076 ZREGNAME(sf, Rm),
1077 CONDNAME(cond));
1078 }
1079 }
1080
OP0FUNC(op_undefined)1081 OP0FUNC(op_undefined)
1082 {
1083 UNDEFINED(pc, insn, "undefined");
1084 }
1085
OP4FUNC(op_adc,sf,Rm,Rn,Rd)1086 OP4FUNC(op_adc, sf, Rm, Rn, Rd)
1087 {
1088 PRINTF("adc\t%s, %s, %s\n",
1089 ZREGNAME(sf, Rd),
1090 ZREGNAME(sf, Rn),
1091 ZREGNAME(sf, Rm));
1092 }
1093
OP4FUNC(op_adcs,sf,Rm,Rn,Rd)1094 OP4FUNC(op_adcs, sf, Rm, Rn, Rd)
1095 {
1096 PRINTF("adcs\t%s, %s, %s\n",
1097 ZREGNAME(sf, Rd),
1098 ZREGNAME(sf, Rn),
1099 ZREGNAME(sf, Rm));
1100 }
1101
OP6FUNC(op_add_extreg,sf,Rm,option,imm3,Rn,Rd)1102 OP6FUNC(op_add_extreg, sf, Rm, option, imm3, Rn, Rd)
1103 {
1104 extendreg_common(di, pc, insn, sf, Rm, option, imm3, Rn, Rd,
1105 "add", NULL);
1106 }
1107
OP5FUNC(op_add_imm,sf,shift,imm12,Rn,Rd)1108 OP5FUNC(op_add_imm, sf, shift, imm12, Rn, Rd)
1109 {
1110 if (shift & 2) {
1111 UNDEFINED(pc, insn, "illegal shift");
1112 return;
1113 }
1114
1115 /* ALIAS: mov_tofromsp */
1116 if ((Rd == 31 || Rn == 31) && (imm12 == 0)) {
1117 PRINTF("mov\t%s, %s\n",
1118 SREGNAME(sf, Rd),
1119 SREGNAME(sf, Rn));
1120 } else {
1121 PRINTF("add\t%s, %s, #0x%"PRIx64"%s\n",
1122 SREGNAME(sf, Rd),
1123 SREGNAME(sf, Rn),
1124 ZeroExtend(12, imm12, 1),
1125 SHIFTOP2(shift, "", ", lsl #12"));
1126 }
1127 }
1128
OP6FUNC(op_add_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1129 OP6FUNC(op_add_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1130 {
1131 if (shift == 3) {
1132 UNDEFINED(pc, insn, "illegal shift");
1133 return;
1134 }
1135 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1136 "add", NULL, NULL);
1137 }
1138
OP6FUNC(op_adds_extreg,sf,Rm,option,imm3,Rn,Rd)1139 OP6FUNC(op_adds_extreg, sf, Rm, option, imm3, Rn, Rd)
1140 {
1141 /* ALIAS: cmn_extreg */
1142 extendreg_common(di, pc, insn, sf, Rm, option, imm3, Rn, Rd,
1143 "adds", "cmn");
1144 }
1145
OP5FUNC(op_adds_imm,sf,shift,imm12,Rn,Rd)1146 OP5FUNC(op_adds_imm, sf, shift, imm12, Rn, Rd)
1147 {
1148 /* ALIAS: cmn_imm */
1149 addsub_imm_common(di, pc, insn, sf, shift, imm12, Rn, Rd,
1150 "adds", "cmn");
1151 }
1152
OP6FUNC(op_adds_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1153 OP6FUNC(op_adds_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1154 {
1155 if (shift == 3) {
1156 UNDEFINED(pc, insn, "illegal shift");
1157 return;
1158 }
1159 /* ALIAS: cmn_shiftreg */
1160 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1161 "adds", NULL, "cmn");
1162 }
1163
OP3FUNC(op_adr,immlo,immhi,Rd)1164 OP3FUNC(op_adr, immlo, immhi, Rd)
1165 {
1166 uint64_t imm = ((immhi << 2) | immlo);
1167
1168 PRINTF("adr\t%s, ", ZREGNAME(1, Rd));
1169 PRINTADDR(SignExtend(21, imm, 1) + pc);
1170 PRINTF("\n");
1171 }
1172
OP3FUNC(op_adrp,immlo,immhi,Rd)1173 OP3FUNC(op_adrp, immlo, immhi, Rd)
1174 {
1175 uint64_t imm = ((immhi << 2) | immlo);
1176
1177 PRINTF("adrp\t%s, ", ZREGNAME(1, Rd));
1178 PRINTADDR(SignExtend(21, imm, 4096) + (pc & -4096));
1179 PRINTF("\n");
1180 }
1181
OP6FUNC(op_and_imm,sf,n,immr,imms,Rn,Rd)1182 OP6FUNC(op_and_imm, sf, n, immr, imms, Rn, Rd)
1183 {
1184 if (!ValidBitMasks(sf, n, imms, immr)) {
1185 UNDEFINED(pc, insn, "illegal bitmasks");
1186 return;
1187 }
1188
1189 PRINTF("and\t%s, %s, #0x%"PRIx64"\n",
1190 ZREGNAME(sf, Rd),
1191 ZREGNAME(sf, Rn),
1192 DecodeBitMasks(sf, n, imms, immr));
1193 }
1194
OP6FUNC(op_and_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1195 OP6FUNC(op_and_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1196 {
1197 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1198 "and", NULL, NULL);
1199 }
1200
OP6FUNC(op_ands_imm,sf,n,immr,imms,Rn,Rd)1201 OP6FUNC(op_ands_imm, sf, n, immr, imms, Rn, Rd)
1202 {
1203 if (!ValidBitMasks(sf, n, imms, immr)) {
1204 UNDEFINED(pc, insn, "illegal bitmasks");
1205 return;
1206 }
1207
1208 /* ALIAS: tst_imm */
1209 if (Rd == 31) {
1210 PRINTF("tst\t%s, #0x%"PRIx64"\n",
1211 ZREGNAME(sf, Rn),
1212 DecodeBitMasks(sf, n, imms, immr));
1213 } else {
1214 PRINTF("ands\t%s, %s, #0x%"PRIx64"\n",
1215 ZREGNAME(sf, Rd),
1216 ZREGNAME(sf, Rn),
1217 DecodeBitMasks(sf, n, imms, immr));
1218 }
1219 }
1220
OP6FUNC(op_ands_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1221 OP6FUNC(op_ands_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1222 {
1223 /* ALIAS: tst_shiftreg */
1224 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1225 "ands", NULL, "tst");
1226 }
1227
OP6FUNC(op_sbfm,sf,n,immr,imms,Rn,Rd)1228 OP6FUNC(op_sbfm, sf, n, immr, imms, Rn, Rd)
1229 {
1230 const uint64_t bitwidth = (sf == 0) ? 32 : 64;
1231
1232 /* ALIAS: asr_imm,sbfiz,sbfx,sxtb,sxth,sxtw */
1233 if ((imms != (bitwidth - 1)) && ((imms + 1) == immr)) {
1234 PRINTF("asr\t%s, %s, #%"PRIu64"\n",
1235 ZREGNAME(sf, Rd),
1236 ZREGNAME(sf, Rn),
1237 bitwidth - immr);
1238 } else if (imms == (bitwidth - 1)) {
1239 PRINTF("asr\t%s, %s, #%"PRIu64"\n",
1240 ZREGNAME(sf, Rd),
1241 ZREGNAME(sf, Rn),
1242 immr);
1243 } else if (imms < immr) {
1244 PRINTF("sbfiz\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
1245 ZREGNAME(sf, Rd),
1246 ZREGNAME(sf, Rn),
1247 (bitwidth - immr) & (bitwidth - 1),
1248 (imms + 1) & (bitwidth - 1));
1249 } else if (BFXPreferred(sf, 0, imms, immr)) {
1250 PRINTF("sbfx\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
1251 ZREGNAME(sf, Rd),
1252 ZREGNAME(sf, Rn),
1253 immr,
1254 (imms - immr + 1) & (bitwidth - 1));
1255 } else if ((immr == 0) && (imms == 7)) {
1256 PRINTF("sxtb\t%s, %s\n",
1257 ZREGNAME(sf, Rd),
1258 ZREGNAME(0, Rn));
1259 } else if ((immr == 0) && (imms == 15)) {
1260 PRINTF("sxth\t%s, %s\n",
1261 ZREGNAME(sf, Rd),
1262 ZREGNAME(0, Rn));
1263 } else if ((immr == 0) && (imms == 31)) {
1264 PRINTF("sxtw\t%s, %s\n",
1265 ZREGNAME(sf, Rd),
1266 ZREGNAME(0, Rn));
1267 } else {
1268 UNDEFINED(pc, insn, "undefined");
1269 }
1270 }
1271
OP4FUNC(op_asr_reg,sf,Rm,Rn,Rd)1272 OP4FUNC(op_asr_reg, sf, Rm, Rn, Rd)
1273 {
1274 /* ALIAS: asrv */
1275 /* "asr" always the preferred disassembly */
1276 PRINTF("asr\t%s, %s, %s\n",
1277 ZREGNAME(sf, Rd),
1278 ZREGNAME(sf, Rn),
1279 ZREGNAME(sf, Rm));
1280 }
1281
1282 struct op_sys_table {
1283 uint32_t code;
1284 int flags;
1285 #define OPE_NONE 0x00000000
1286 #define OPE_XT 0x00000001
1287 const char *opname;
1288 };
1289
1290 static struct op_sys_table op_sys_table[] = {
1291 { SYSREG_ENC(1, 0, 7, 1, 0), OPE_NONE, "ic\tialluis" },
1292 { SYSREG_ENC(1, 0, 7, 5, 0), OPE_NONE, "ic\tiallu" },
1293 { SYSREG_ENC(1, 3, 7, 5, 1), OPE_XT, "ic\tivau" },
1294 { SYSREG_ENC(1, 0, 7, 6, 1), OPE_XT, "dc\tivac" },
1295 { SYSREG_ENC(1, 0, 7, 6, 2), OPE_XT, "dc\tisw" },
1296 { SYSREG_ENC(1, 0, 7, 10, 2), OPE_XT, "dc\tcsw" },
1297 { SYSREG_ENC(1, 0, 7, 14, 2), OPE_XT, "dc\tcisw" },
1298 { SYSREG_ENC(1, 3, 7, 10, 1), OPE_XT, "dc\tcvac" },
1299 { SYSREG_ENC(1, 3, 7, 11, 1), OPE_XT, "dc\tcvau" },
1300 { SYSREG_ENC(1, 3, 7, 14, 1), OPE_XT, "dc\tcivac" },
1301 { SYSREG_ENC(1, 3, 7, 4, 1), OPE_XT, "dc\tzva" },
1302 { SYSREG_ENC(1, 0, 7, 6, 3), OPE_XT, "dc\tigvac" },
1303 { SYSREG_ENC(1, 0, 7, 6, 4), OPE_XT, "dc\tigsw" },
1304 { SYSREG_ENC(1, 0, 7, 6, 5), OPE_XT, "dc\tigdvac" },
1305 { SYSREG_ENC(1, 0, 7, 6, 6), OPE_XT, "dc\tigdsw" },
1306 { SYSREG_ENC(1, 0, 7, 10, 4), OPE_XT, "dc\tcgsw" },
1307 { SYSREG_ENC(1, 0, 7, 10, 6), OPE_XT, "dc\tcgdsw" },
1308 { SYSREG_ENC(1, 0, 7, 14, 4), OPE_XT, "dc\tcigsw" },
1309 { SYSREG_ENC(1, 0, 7, 14, 6), OPE_XT, "dc\tcigdsw" },
1310 { SYSREG_ENC(1, 3, 7, 4, 3), OPE_XT, "dc\tgva" },
1311 { SYSREG_ENC(1, 3, 7, 4, 4), OPE_XT, "dc\tgzva" },
1312 { SYSREG_ENC(1, 3, 7, 10, 3), OPE_XT, "dc\tcgvac" },
1313 { SYSREG_ENC(1, 3, 7, 10, 5), OPE_XT, "dc\tcgdvac" },
1314 { SYSREG_ENC(1, 3, 7, 12, 3), OPE_XT, "dc\tcgvap" },
1315 { SYSREG_ENC(1, 3, 7, 12, 5), OPE_XT, "dc\tcgdvap" },
1316 { SYSREG_ENC(1, 3, 7, 13, 3), OPE_XT, "dc\tcgvadp" },
1317 { SYSREG_ENC(1, 3, 7, 13, 5), OPE_XT, "dc\tcgdvadp" },
1318 { SYSREG_ENC(1, 3, 7, 14, 3), OPE_XT, "dc\tcigvac" },
1319 { SYSREG_ENC(1, 3, 7, 14, 5), OPE_XT, "dc\tcigdvac" },
1320 { SYSREG_ENC(1, 3, 7, 12, 1), OPE_XT, "dc\tcvap" },
1321 { SYSREG_ENC(1, 3, 7, 13, 1), OPE_XT, "dc\tcvadp" },
1322
1323 { SYSREG_ENC(1, 0, 7, 8, 0), OPE_XT, "at\ts1e1r" },
1324 { SYSREG_ENC(1, 0, 7, 8, 1), OPE_XT, "at\ts1e1w" },
1325 { SYSREG_ENC(1, 0, 7, 8, 2), OPE_XT, "at\ts1e0r" },
1326 { SYSREG_ENC(1, 0, 7, 8, 3), OPE_XT, "at\ts1e0w" },
1327 { SYSREG_ENC(1, 0, 7, 9, 0), OPE_XT, "at\ts1e1rp" },
1328 { SYSREG_ENC(1, 0, 7, 9, 1), OPE_XT, "at\ts1e1wp" },
1329 { SYSREG_ENC(1, 4, 7, 8, 0), OPE_XT, "at\ts1e2r" },
1330 { SYSREG_ENC(1, 4, 7, 8, 1), OPE_XT, "at\ts1e2w" },
1331 { SYSREG_ENC(1, 4, 7, 8, 4), OPE_XT, "at\ts12e1r" },
1332 { SYSREG_ENC(1, 4, 7, 8, 5), OPE_XT, "at\ts12e1w" },
1333 { SYSREG_ENC(1, 4, 7, 8, 6), OPE_XT, "at\ts12e0r" },
1334 { SYSREG_ENC(1, 4, 7, 8, 7), OPE_XT, "at\ts12e0w" },
1335 { SYSREG_ENC(1, 6, 7, 8, 0), OPE_XT, "at\ts1e3r" },
1336 { SYSREG_ENC(1, 6, 7, 8, 1), OPE_XT, "at\ts1e3w" },
1337
1338 { SYSREG_ENC(1, 3, 7, 3, 4), OPE_XT, "cfp\trctx" },
1339 { SYSREG_ENC(1, 3, 7, 3, 5), OPE_XT, "dvp\trctx" },
1340 { SYSREG_ENC(1, 3, 7, 3, 7), OPE_XT, "cpp\trctx" },
1341
1342 { SYSREG_ENC(1, 0, 8, 3, 0), OPE_NONE, "tlbi\tvmalle1is" },
1343 { SYSREG_ENC(1, 0, 8, 3, 1), OPE_XT, "tlbi\tvae1is" },
1344 { SYSREG_ENC(1, 0, 8, 3, 2), OPE_XT, "tlbi\taside1is" },
1345 { SYSREG_ENC(1, 0, 8, 3, 3), OPE_XT, "tlbi\tvaae1is" },
1346 { SYSREG_ENC(1, 0, 8, 3, 5), OPE_XT, "tlbi\tvale1is" },
1347 { SYSREG_ENC(1, 0, 8, 3, 7), OPE_XT, "tlbi\tvaale1is" },
1348 { SYSREG_ENC(1, 0, 8, 7, 0), OPE_NONE, "tlbi\tvmalle1" },
1349 { SYSREG_ENC(1, 0, 8, 7, 1), OPE_XT, "tlbi\tvae1" },
1350 { SYSREG_ENC(1, 0, 8, 7, 2), OPE_XT, "tlbi\taside1" },
1351 { SYSREG_ENC(1, 0, 8, 7, 3), OPE_XT, "tlbi\tvaae1" },
1352 { SYSREG_ENC(1, 0, 8, 7, 5), OPE_XT, "tlbi\tvale1" },
1353 { SYSREG_ENC(1, 0, 8, 7, 7), OPE_XT, "tlbi\tvaale1" },
1354 { SYSREG_ENC(1, 4, 8, 0, 1), OPE_XT, "tlbi\tipas2e1is" },
1355 { SYSREG_ENC(1, 4, 8, 0, 5), OPE_XT, "tlbi\tipas2le1is" },
1356 { SYSREG_ENC(1, 4, 8, 3, 0), OPE_NONE, "tlbi\talle2is" },
1357 { SYSREG_ENC(1, 4, 8, 3, 1), OPE_XT, "tlbi\tvae2is" },
1358 { SYSREG_ENC(1, 4, 8, 3, 4), OPE_NONE, "tlbi\talle1is" },
1359 { SYSREG_ENC(1, 4, 8, 3, 5), OPE_XT, "tlbi\tvale2is" },
1360 { SYSREG_ENC(1, 4, 8, 3, 6), OPE_NONE, "tlbi\tvmalls12e1is" },
1361 { SYSREG_ENC(1, 4, 8, 4, 1), OPE_XT, "tlbi\tipas2e1" },
1362 { SYSREG_ENC(1, 4, 8, 4, 5), OPE_XT, "tlbi\tipas2le1" },
1363 { SYSREG_ENC(1, 4, 8, 7, 0), OPE_NONE, "tlbi\talle2" },
1364 { SYSREG_ENC(1, 4, 8, 7, 1), OPE_XT, "tlbi\tvae2" },
1365 { SYSREG_ENC(1, 4, 8, 7, 4), OPE_NONE, "tlbi\talle1" },
1366 { SYSREG_ENC(1, 4, 8, 7, 5), OPE_XT, "tlbi\tvale2" },
1367 { SYSREG_ENC(1, 4, 8, 7, 6), OPE_NONE, "tlbi\tvmalls12e1" },
1368 { SYSREG_ENC(1, 6, 8, 3, 0), OPE_NONE, "tlbi\talle3is" },
1369 { SYSREG_ENC(1, 6, 8, 3, 1), OPE_XT, "tlbi\tvae3is" },
1370 { SYSREG_ENC(1, 6, 8, 3, 5), OPE_XT, "tlbi\tvale3is" },
1371 { SYSREG_ENC(1, 6, 8, 7, 0), OPE_NONE, "tlbi\talle3" },
1372 { SYSREG_ENC(1, 6, 8, 7, 1), OPE_XT, "tlbi\tvae3" },
1373 { SYSREG_ENC(1, 6, 8, 7, 5), OPE_XT, "tlbi\tvale3" }
1374 };
1375
OP5FUNC(op_sys,op1,CRn,CRm,op2,Rt)1376 OP5FUNC(op_sys, op1, CRn, CRm, op2, Rt)
1377 {
1378 uint32_t code;
1379 size_t i;
1380
1381 /* ALIAS: at,dc,ic,sys,tlbi */
1382 code = SYSREG_ENC(1, op1, CRn, CRm, op2);
1383 for (i = 0; i < __arraycount(op_sys_table); i++) {
1384 if (op_sys_table[i].code != code)
1385 continue;
1386
1387 if (((op_sys_table[i].flags & OPE_XT) != 0) || (Rt != 31)) {
1388 PRINTF("%s, %s\n",
1389 op_sys_table[i].opname,
1390 ZREGNAME(1, Rt));
1391 } else {
1392 PRINTF("%s\n",
1393 op_sys_table[i].opname);
1394 }
1395 return;
1396 }
1397
1398 /* default, sys instruction */
1399 PRINTF("sys\t#%"PRIu64", %s, %s, #%"PRIu64", %s\n",
1400 op1,
1401 CREGNAME(CRn),
1402 CREGNAME(CRm),
1403 op2,
1404 ZREGNAME(1,Rt));
1405 }
1406
OP1FUNC(op_b,imm26)1407 OP1FUNC(op_b, imm26)
1408 {
1409 PRINTF("b\t");
1410 PRINTADDR(SignExtend(26, imm26, 4) + pc);
1411 PRINTF("\n");
1412 }
1413
OP2FUNC(op_b_cond,imm19,cond)1414 OP2FUNC(op_b_cond, imm19, cond)
1415 {
1416 PRINTF("b.%s\t", CONDNAME(cond));
1417 PRINTADDR(SignExtend(19, imm19, 4) + pc);
1418 PRINTF("\n");
1419 }
1420
OP6FUNC(op_bfi,sf,n,immr,imms,Rn,Rd)1421 OP6FUNC(op_bfi, sf, n, immr, imms, Rn, Rd)
1422 {
1423 const uint64_t bitwidth = (sf == 0) ? 32 : 64;
1424
1425 /* ALIAS: bfm,bfxil */
1426 /* it is not disassembled as bfm */
1427
1428 /* XXX: if Rn=31, should be used "bfc"? (armv8.2) */
1429 if (imms < immr) {
1430 PRINTF("bfi\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
1431 ZREGNAME(sf, Rd),
1432 ZREGNAME(sf, Rn),
1433 (bitwidth - immr) & (bitwidth - 1),
1434 (imms + 1) & (bitwidth - 1));
1435 } else {
1436 PRINTF("bfxil\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
1437 ZREGNAME(sf, Rd),
1438 ZREGNAME(sf, Rn),
1439 immr,
1440 (imms -immr + 1) & (bitwidth - 1));
1441 }
1442 }
1443
OP6FUNC(op_bic_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1444 OP6FUNC(op_bic_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1445 {
1446 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1447 "bic", NULL, NULL);
1448 }
1449
OP6FUNC(op_bics_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1450 OP6FUNC(op_bics_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1451 {
1452 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1453 "bics", NULL, NULL);
1454 }
1455
OP1FUNC(op_bl,imm26)1456 OP1FUNC(op_bl, imm26)
1457 {
1458 PRINTF("bl\t");
1459 PRINTADDR(SignExtend(26, imm26, 4) + pc);
1460 PRINTF("\n");
1461 }
1462
OP1FUNC(op_blr,Rn)1463 OP1FUNC(op_blr, Rn)
1464 {
1465 PRINTF("blr\t%s\n", ZREGNAME(1, Rn));
1466 }
1467
OP1FUNC(op_br,Rn)1468 OP1FUNC(op_br, Rn)
1469 {
1470 PRINTF("br\t%s\n", ZREGNAME(1, Rn));
1471 }
1472
OP1FUNC(op_brk,imm16)1473 OP1FUNC(op_brk, imm16)
1474 {
1475 PRINTF("brk\t#0x%"PRIx64"\n", imm16);
1476 }
1477
OP3FUNC(op_cbnz,sf,imm19,Rt)1478 OP3FUNC(op_cbnz, sf, imm19, Rt)
1479 {
1480 PRINTF("cbnz\t%s, ", ZREGNAME(sf, Rt));
1481 PRINTADDR(SignExtend(19, imm19, 4) + pc);
1482 PRINTF("\n");
1483 }
1484
OP3FUNC(op_cbz,sf,imm19,Rt)1485 OP3FUNC(op_cbz, sf, imm19, Rt)
1486 {
1487 PRINTF("cbz\t%s, ", ZREGNAME(sf, Rt));
1488 PRINTADDR(SignExtend(19, imm19, 4) + pc);
1489 PRINTF("\n");
1490 }
1491
OP5FUNC(op_ccmn_imm,sf,imm5,cond,Rn,nzcv)1492 OP5FUNC(op_ccmn_imm, sf, imm5, cond, Rn, nzcv)
1493 {
1494 PRINTF("ccmn\t%s, #0x%"PRIx64", #0x%"PRIx64", %s\n",
1495 ZREGNAME(sf, Rn),
1496 imm5,
1497 nzcv,
1498 CONDNAME(cond));
1499 }
1500
OP5FUNC(op_ccmn_reg,sf,Rm,cond,Rn,nzcv)1501 OP5FUNC(op_ccmn_reg, sf, Rm, cond, Rn, nzcv)
1502 {
1503 PRINTF("ccmn\t%s, %s, #0x%"PRIx64", %s\n",
1504 ZREGNAME(sf, Rn),
1505 ZREGNAME(sf, Rm),
1506 nzcv,
1507 CONDNAME(cond));
1508 }
1509
OP5FUNC(op_ccmp_imm,sf,imm5,cond,Rn,nzcv)1510 OP5FUNC(op_ccmp_imm, sf, imm5, cond, Rn, nzcv)
1511 {
1512 PRINTF("ccmp\t%s, #0x%"PRIx64", #0x%"PRIx64", %s\n",
1513 ZREGNAME(sf, Rn),
1514 imm5,
1515 nzcv,
1516 CONDNAME(cond));
1517 }
1518
OP5FUNC(op_ccmp_reg,sf,Rm,cond,Rn,nzcv)1519 OP5FUNC(op_ccmp_reg, sf, Rm, cond, Rn, nzcv)
1520 {
1521 PRINTF("ccmp\t%s, %s, #0x%"PRIx64", %s\n",
1522 ZREGNAME(sf, Rn),
1523 ZREGNAME(sf, Rm),
1524 nzcv,
1525 CONDNAME(cond));
1526 }
1527
OP5FUNC(op_cinc,sf,Rm,cond,Rn,Rd)1528 OP5FUNC(op_cinc, sf, Rm, cond, Rn, Rd)
1529 {
1530 /* ALIAS: cset,csinc */
1531 csetsel_common(di, pc, insn, sf, Rm, cond, Rn, Rd,
1532 "csinc", "cset", "cinc");
1533 }
1534
OP5FUNC(op_csinv,sf,Rm,cond,Rn,Rd)1535 OP5FUNC(op_csinv, sf, Rm, cond, Rn, Rd)
1536 {
1537 /* ALIAS: csetm,cinv */
1538 csetsel_common(di, pc, insn, sf, Rm, cond, Rn, Rd,
1539 "csinv", "csetm", "cinv");
1540 }
1541
OP1FUNC(op_clrex,CRm)1542 OP1FUNC(op_clrex, CRm)
1543 {
1544 if (CRm == 15) {
1545 PRINTF("clrex\n");
1546 } else {
1547 PRINTF("clrex\t#0x%"PRIx64"\n", CRm);
1548 }
1549 }
1550
OP3FUNC(op_cls,sf,Rn,Rd)1551 OP3FUNC(op_cls, sf, Rn, Rd)
1552 {
1553 PRINTF("cls\t%s, %s\n",
1554 ZREGNAME(sf, Rd),
1555 ZREGNAME(sf, Rn));
1556 }
1557
OP3FUNC(op_clz,sf,Rn,Rd)1558 OP3FUNC(op_clz, sf, Rn, Rd)
1559 {
1560 PRINTF("clz\t%s, %s\n",
1561 ZREGNAME(sf, Rd),
1562 ZREGNAME(sf, Rn));
1563 }
1564
OP6FUNC(op_subs_extreg,sf,Rm,option,imm3,Rn,Rd)1565 OP6FUNC(op_subs_extreg, sf, Rm, option, imm3, Rn, Rd)
1566 {
1567 /* ALIAS: cmp_extreg */
1568 extendreg_common(di, pc, insn, sf, Rm, option, imm3, Rn, Rd,
1569 "subs", "cmp");
1570 }
1571
OP5FUNC(op_subs_imm,sf,shift,imm12,Rn,Rd)1572 OP5FUNC(op_subs_imm, sf, shift, imm12, Rn, Rd)
1573 {
1574 /* ALIAS: cmp_imm */
1575 addsub_imm_common(di, pc, insn, sf, shift, imm12, Rn, Rd,
1576 "subs", "cmp");
1577 }
1578
OP6FUNC(op_subs_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1579 OP6FUNC(op_subs_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1580 {
1581 if (shift == 3) {
1582 UNDEFINED(pc, insn, "illegal shift");
1583 return;
1584 }
1585
1586 /* ALIAS: negs,cmp_shiftreg */
1587 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1588 "subs", "negs", "cmp");
1589 }
1590
OP5FUNC(op_csneg,sf,Rm,cond,Rn,Rd)1591 OP5FUNC(op_csneg, sf, Rm, cond, Rn, Rd)
1592 {
1593 /* ALIAS: cneg */
1594 if ((Rn == Rm) && ((cond & 0xe) != 0x0e)) {
1595 PRINTF("cneg\t%s, %s, %s\n",
1596 ZREGNAME(sf, Rd),
1597 ZREGNAME(sf, Rn),
1598 IVCONDNAME(cond));
1599 } else {
1600 PRINTF("csneg\t%s, %s, %s, %s\n",
1601 ZREGNAME(sf, Rd),
1602 ZREGNAME(sf, Rn),
1603 ZREGNAME(sf, Rm),
1604 CONDNAME(cond));
1605 }
1606 }
1607
1608 static void
crc32_common(const disasm_interface_t * di,uint64_t pc,uint32_t insn,uint64_t sf,uint64_t Rm,uint64_t sz,uint64_t Rn,uint64_t Rd,const char * op)1609 crc32_common(const disasm_interface_t *di, uint64_t pc, uint32_t insn,
1610 uint64_t sf, uint64_t Rm, uint64_t sz, uint64_t Rn, uint64_t Rd,
1611 const char *op)
1612 {
1613 const char bhwx[4] = "bhwx"; /* "crc32x" + SizeChar */
1614
1615 if (((sf != 0) && (sz != 3)) ||
1616 ((sf == 0) && (sz == 3))) {
1617 UNDEFINED(pc, insn, "illegal size");
1618 return;
1619 }
1620
1621 PRINTF("%s%c\t%s, %s, %s\n",
1622 op, bhwx[sz & 3],
1623 ZREGNAME(0, Rd),
1624 ZREGNAME(0, Rn),
1625 ZREGNAME(sf, Rm));
1626 }
1627
OP5FUNC(op_crc32,sf,Rm,sz,Rn,Rd)1628 OP5FUNC(op_crc32, sf, Rm, sz, Rn, Rd)
1629 {
1630 crc32_common(di, pc, insn, sf, Rm, sz, Rn, Rd, "crc32");
1631 }
1632
OP5FUNC(op_crc32c,sf,Rm,sz,Rn,Rd)1633 OP5FUNC(op_crc32c, sf, Rm, sz, Rn, Rd)
1634 {
1635 crc32_common(di, pc, insn, sf, Rm, sz, Rn, Rd, "crc32c");
1636 }
1637
OP5FUNC(op_csel,sf,Rm,cond,Rn,Rd)1638 OP5FUNC(op_csel, sf, Rm, cond, Rn, Rd)
1639 {
1640 PRINTF("csel\t%s, %s, %s, %s\n",
1641 ZREGNAME(sf, Rd),
1642 ZREGNAME(sf, Rn),
1643 ZREGNAME(sf, Rm),
1644 CONDNAME(cond));
1645 }
1646
OP2FUNC(op_dcps,imm16,ll)1647 OP2FUNC(op_dcps, imm16, ll)
1648 {
1649 if (ll == 0) {
1650 UNDEFINED(pc, insn, "illegal level");
1651 return;
1652 }
1653
1654 if (imm16 == 0)
1655 PRINTF("dcps%"PRIu64"\n", ll);
1656 else
1657 PRINTF("dcps%"PRIu64"\t#0x%"PRIx64"\n", ll, imm16);
1658 }
1659
OP0FUNC(op_drps)1660 OP0FUNC(op_drps)
1661 {
1662 PRINTF("drps\n");
1663 }
1664
OP1FUNC(op_dmb,CRm)1665 OP1FUNC(op_dmb, CRm)
1666 {
1667 PRINTF("dmb\t%s\n", BARRIERNAME(CRm));
1668 }
1669
OP1FUNC(op_dsb,CRm)1670 OP1FUNC(op_dsb, CRm)
1671 {
1672 PRINTF("dsb\t%s\n", BARRIERNAME(CRm));
1673 }
1674
OP6FUNC(op_eon_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1675 OP6FUNC(op_eon_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1676 {
1677 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1678 "eon", NULL, NULL);
1679 }
1680
OP6FUNC(op_eor_imm,sf,n,immr,imms,Rn,Rd)1681 OP6FUNC(op_eor_imm, sf, n, immr, imms, Rn, Rd)
1682 {
1683 if (!ValidBitMasks(sf, n, imms, immr)) {
1684 UNDEFINED(pc, insn, "illegal bitmasks");
1685 return;
1686 }
1687
1688 PRINTF("eor\t%s, %s, #0x%"PRIx64"\n",
1689 ZREGNAME(sf, Rd),
1690 ZREGNAME(sf, Rn),
1691 DecodeBitMasks(sf, n, imms, immr));
1692 }
1693
OP6FUNC(op_eor_shiftreg,sf,shift,Rm,imm6,Rn,Rd)1694 OP6FUNC(op_eor_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
1695 {
1696 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
1697 "eor", NULL, NULL);
1698 }
1699
OP0FUNC(op_eret)1700 OP0FUNC(op_eret)
1701 {
1702 PRINTF("eret\n");
1703 }
1704
OP6FUNC(op_ror_imm,sf,n,Rm,imms,Rn,Rd)1705 OP6FUNC(op_ror_imm, sf, n, Rm, imms, Rn, Rd)
1706 {
1707 if (((sf ^ n) != 0) || (n == 0 && imms >= 0x20)) {
1708 UNDEFINED(pc, insn, "illegal sf and N");
1709 return;
1710 }
1711
1712 /* ALIAS: extr */
1713 if (Rn == Rm) {
1714 PRINTF("ror\t%s, %s, #%"PRIu64"\n",
1715 ZREGNAME(sf, Rd),
1716 ZREGNAME(sf, Rn),
1717 imms);
1718 } else {
1719 PRINTF("extr\t%s, %s, %s, #%"PRIu64"\n",
1720 ZREGNAME(sf, Rd),
1721 ZREGNAME(sf, Rn),
1722 ZREGNAME(sf, Rm),
1723 imms);
1724 }
1725 }
1726
1727 #define CRm_OP2(crm,op) ((crm) << 3 | (op))
1728 static const char *hint_table[] = {
1729 [CRm_OP2(0, 0)] = "nop",
1730 [CRm_OP2(0, 1)] = "yield",
1731 [CRm_OP2(0, 2)] = "wfe",
1732 [CRm_OP2(0, 3)] = "wfi",
1733 [CRm_OP2(0, 4)] = "sev",
1734 [CRm_OP2(0, 5)] = "sevl",
1735 [CRm_OP2(0, 7)] = "xpaclri",
1736 [CRm_OP2(1, 0)] = "pacia1716",
1737 [CRm_OP2(1, 2)] = "pacib1716",
1738 [CRm_OP2(1, 4)] = "autia1716",
1739 [CRm_OP2(1, 6)] = "autib1716",
1740 [CRm_OP2(2, 0)] = "esb",
1741 [CRm_OP2(2, 1)] = "psb\tcsync",
1742 [CRm_OP2(2, 2)] = "tsb\tcsync",
1743 [CRm_OP2(2, 4)] = "csdb",
1744 [CRm_OP2(3, 0)] = "paciaz",
1745 [CRm_OP2(3, 1)] = "paciasp",
1746 [CRm_OP2(3, 2)] = "pacibz",
1747 [CRm_OP2(3, 3)] = "pacibsp",
1748 [CRm_OP2(3, 4)] = "autiaz",
1749 [CRm_OP2(3, 5)] = "autiasp",
1750 [CRm_OP2(3, 6)] = "autibz",
1751 [CRm_OP2(3, 7)] = "autibsp",
1752 [CRm_OP2(4, 0)] = "bti",
1753 [CRm_OP2(4, 2)] = "bti\tc",
1754 [CRm_OP2(4, 4)] = "bti\tj",
1755 [CRm_OP2(4, 6)] = "bti\tjc",
1756 };
1757
OP2FUNC(op_hint,CRm,op2)1758 OP2FUNC(op_hint, CRm, op2)
1759 {
1760 const uint64_t op = CRm_OP2(CRm, op2);
1761
1762 /* ALIAS: nop,sev,sevl,wfe,wfi,yield,etc,.. */
1763 if (op < __arraycount(hint_table) &&
1764 hint_table[op] != NULL) {
1765 PRINTF("%s\n", hint_table[op]);
1766 } else {
1767 PRINTF("hint\t#0x%"PRIx64"\n", op);
1768 }
1769 }
1770
OP1FUNC(op_hlt,imm16)1771 OP1FUNC(op_hlt, imm16)
1772 {
1773 PRINTF("hlt\t#0x%"PRIx64"\n", imm16);
1774 }
1775
OP1FUNC(op_hvc,imm16)1776 OP1FUNC(op_hvc, imm16)
1777 {
1778 PRINTF("hvc\t#0x%"PRIx64"\n", imm16);
1779 }
1780
OP1FUNC(op_isb,CRm)1781 OP1FUNC(op_isb, CRm)
1782 {
1783 if (CRm == 15)
1784 PRINTF("isb\n");
1785 else
1786 PRINTF("isb\t#0x%"PRIx64"\n", CRm);
1787 }
1788
OP3FUNC(op_ldar,size,Rn,Rt)1789 OP3FUNC(op_ldar, size, Rn, Rt)
1790 {
1791 PRINTF("ldar\t%s, [%s]\n",
1792 ZREGNAME(size, Rt),
1793 SREGNAME(1, Rn));
1794 }
1795
OP2FUNC(op_ldarb,Rn,Rt)1796 OP2FUNC(op_ldarb, Rn, Rt)
1797 {
1798 PRINTF("ldarb\t%s, [%s]\n",
1799 ZREGNAME(0, Rt),
1800 SREGNAME(1, Rn));
1801 }
1802
OP2FUNC(op_ldarh,Rn,Rt)1803 OP2FUNC(op_ldarh, Rn, Rt)
1804 {
1805 PRINTF("ldarh\t%s, [%s]\n",
1806 ZREGNAME(0, Rt),
1807 SREGNAME(1, Rn));
1808 }
1809
OP4FUNC(op_ldaxp,size,Rt2,Rn,Rt)1810 OP4FUNC(op_ldaxp, size, Rt2, Rn, Rt)
1811 {
1812 PRINTF("ldaxp\t%s, %s, [%s]\n",
1813 ZREGNAME(size, Rt),
1814 ZREGNAME(size, Rt2),
1815 SREGNAME(1, Rn));
1816 }
1817
OP3FUNC(op_ldaxr,size,Rn,Rt)1818 OP3FUNC(op_ldaxr, size, Rn, Rt)
1819 {
1820 PRINTF("ldaxr\t%s, [%s]\n",
1821 ZREGNAME(size, Rt),
1822 SREGNAME(1, Rn));
1823 }
1824
OP2FUNC(op_ldaxrb,Rn,Rt)1825 OP2FUNC(op_ldaxrb, Rn, Rt)
1826 {
1827 PRINTF("ldaxrb\t%s, [%s]\n",
1828 ZREGNAME(0, Rt),
1829 SREGNAME(1, Rn));
1830 }
1831
OP2FUNC(op_ldaxrh,Rn,Rt)1832 OP2FUNC(op_ldaxrh, Rn, Rt)
1833 {
1834 PRINTF("ldaxrh\t%s, [%s]\n",
1835 ZREGNAME(0, Rt),
1836 SREGNAME(1, Rn));
1837 }
1838
OP5FUNC(op_ldnp,sf,imm7,Rt2,Rn,Rt)1839 OP5FUNC(op_ldnp, sf, imm7, Rt2, Rn, Rt)
1840 {
1841 if (imm7 == 0) {
1842 PRINTF("ldnp\t%s, %s, [%s]\n",
1843 ZREGNAME(sf, Rt),
1844 ZREGNAME(sf, Rt2),
1845 SREGNAME(1, Rn));
1846 } else {
1847 PRINTF("ldnp\t%s, %s, [%s,#%"PRId64"]\n",
1848 ZREGNAME(sf, Rt),
1849 ZREGNAME(sf, Rt2),
1850 SREGNAME(1, Rn),
1851 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
1852 }
1853 }
1854
OP5FUNC(op_ldp_postidx,sf,imm7,Rt2,Rn,Rt)1855 OP5FUNC(op_ldp_postidx, sf, imm7, Rt2, Rn, Rt)
1856 {
1857 PRINTF("ldp\t%s, %s, [%s],#%"PRId64"\n",
1858 ZREGNAME(sf, Rt),
1859 ZREGNAME(sf, Rt2),
1860 SREGNAME(1, Rn),
1861 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
1862 }
1863
OP5FUNC(op_ldp_preidx,sf,imm7,Rt2,Rn,Rt)1864 OP5FUNC(op_ldp_preidx, sf, imm7, Rt2, Rn, Rt)
1865 {
1866 PRINTF("ldp\t%s, %s, [%s,#%"PRId64"]!\n",
1867 ZREGNAME(sf, Rt),
1868 ZREGNAME(sf, Rt2),
1869 SREGNAME(1, Rn),
1870 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
1871 }
1872
OP5FUNC(op_ldp_signed,sf,imm7,Rt2,Rn,Rt)1873 OP5FUNC(op_ldp_signed, sf, imm7, Rt2, Rn, Rt)
1874 {
1875 if (imm7 == 0) {
1876 PRINTF("ldp\t%s, %s, [%s]\n",
1877 ZREGNAME(sf, Rt),
1878 ZREGNAME(sf, Rt2),
1879 SREGNAME(1, Rn));
1880 } else {
1881 PRINTF("ldp\t%s, %s, [%s,#%"PRId64"]\n",
1882 ZREGNAME(sf, Rt),
1883 ZREGNAME(sf, Rt2),
1884 SREGNAME(1, Rn),
1885 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
1886 }
1887 }
1888
OP4FUNC(op_ldpsw_postidx,imm7,Rt2,Rn,Rt)1889 OP4FUNC(op_ldpsw_postidx, imm7, Rt2, Rn, Rt)
1890 {
1891 PRINTF("ldpsw\t%s, %s, [%s],#%"PRId64"\n",
1892 ZREGNAME(1, Rt),
1893 ZREGNAME(1, Rt2),
1894 SREGNAME(1, Rn),
1895 SignExtend(7, imm7, 4));
1896 }
1897
OP4FUNC(op_ldpsw_preidx,imm7,Rt2,Rn,Rt)1898 OP4FUNC(op_ldpsw_preidx, imm7, Rt2, Rn, Rt)
1899 {
1900 PRINTF("ldpsw\t%s, %s, [%s,#%"PRId64"]!\n",
1901 ZREGNAME(1, Rt),
1902 ZREGNAME(1, Rt2),
1903 SREGNAME(1, Rn),
1904 SignExtend(7, imm7, 4));
1905 }
1906
OP4FUNC(op_ldpsw_signed,imm7,Rt2,Rn,Rt)1907 OP4FUNC(op_ldpsw_signed, imm7, Rt2, Rn, Rt)
1908 {
1909 if (imm7 == 0) {
1910 PRINTF("ldpsw\t%s, %s, [%s]\n",
1911 ZREGNAME(1, Rt),
1912 ZREGNAME(1, Rt2),
1913 SREGNAME(1, Rn));
1914 } else {
1915 PRINTF("ldpsw\t%s, %s, [%s,#%"PRId64"]\n",
1916 ZREGNAME(1, Rt),
1917 ZREGNAME(1, Rt2),
1918 SREGNAME(1, Rn),
1919 SignExtend(7, imm7, 4));
1920 }
1921 }
1922
OP4FUNC(op_ldr_immpostidx,size,imm9,Rn,Rt)1923 OP4FUNC(op_ldr_immpostidx, size, imm9, Rn, Rt)
1924 {
1925 PRINTF("ldr\t%s, [%s],#%"PRId64"\n",
1926 ZREGNAME(size, Rt),
1927 SREGNAME(1, Rn),
1928 SignExtend(9, imm9, 1));
1929 }
1930
OP4FUNC(op_ldr_immpreidx,size,imm9,Rn,Rt)1931 OP4FUNC(op_ldr_immpreidx, size, imm9, Rn, Rt)
1932 {
1933 PRINTF("ldr\t%s, [%s,#%"PRId64"]!\n",
1934 ZREGNAME(size, Rt),
1935 SREGNAME(1, Rn),
1936 SignExtend(9, imm9, 1));
1937 }
1938
OP4FUNC(op_ldr_immunsign,size,imm12,Rn,Rt)1939 OP4FUNC(op_ldr_immunsign, size, imm12, Rn, Rt)
1940 {
1941 if (imm12 == 0) {
1942 PRINTF("ldr\t%s, [%s]\n",
1943 ZREGNAME(size, Rt),
1944 SREGNAME(1, Rn));
1945 } else {
1946 PRINTF("ldr\t%s, [%s,#%"PRId64"]\n",
1947 ZREGNAME(size, Rt),
1948 SREGNAME(1, Rn),
1949 ZeroExtend(12, imm12, (size == 0) ? 4 : 8));
1950 }
1951 }
1952
OP3FUNC(op_ldr_literal,size,imm19,Rt)1953 OP3FUNC(op_ldr_literal, size, imm19, Rt)
1954 {
1955 PRINTF("ldr\t%s, ", ZREGNAME(size, Rt));
1956 PRINTADDR(SignExtend(19, imm19, 4) + pc);
1957 PRINTF("\n");
1958 }
1959
OP6FUNC(op_ldr_reg,size,Rm,option,shift,Rn,Rt)1960 OP6FUNC(op_ldr_reg, size, Rm, option, shift, Rn, Rt)
1961 {
1962 regoffset_x_common(di, pc, insn, size, Rm, option, shift, Rn, Rt,
1963 "ldr");
1964 }
1965
OP3FUNC(op_ldrb_immpostidx,imm9,Rn,Rt)1966 OP3FUNC(op_ldrb_immpostidx, imm9, Rn, Rt)
1967 {
1968 PRINTF("ldrb\t%s, [%s],#%"PRId64"\n",
1969 ZREGNAME(0, Rt),
1970 SREGNAME(1, Rn),
1971 SignExtend(9, imm9, 1));
1972 }
1973
OP3FUNC(op_ldrb_immpreidx,imm9,Rn,Rt)1974 OP3FUNC(op_ldrb_immpreidx, imm9, Rn, Rt)
1975 {
1976 PRINTF("ldrb\t%s, [%s,#%"PRId64"]!\n",
1977 ZREGNAME(0, Rt),
1978 SREGNAME(1, Rn),
1979 SignExtend(9, imm9, 1));
1980 }
1981
OP3FUNC(op_ldrb_immunsign,imm12,Rn,Rt)1982 OP3FUNC(op_ldrb_immunsign, imm12, Rn, Rt)
1983 {
1984 if (imm12 == 0) {
1985 PRINTF("ldrb\t%s, [%s]\n",
1986 ZREGNAME(0, Rt),
1987 SREGNAME(1, Rn));
1988 } else {
1989 PRINTF("ldrb\t%s, [%s,#%"PRId64"]\n",
1990 ZREGNAME(0, Rt),
1991 SREGNAME(1, Rn),
1992 ZeroExtend(12, imm12, 1));
1993 }
1994 }
1995
OP5FUNC(op_ldrb_reg,Rm,option,shift,Rn,Rt)1996 OP5FUNC(op_ldrb_reg, Rm, option, shift, Rn, Rt)
1997 {
1998 regoffset_b_common(di, pc, insn, Rm, option, shift, Rn, Rt, "ldrb");
1999 }
2000
OP3FUNC(op_ldrh_immpostidx,imm9,Rn,Rt)2001 OP3FUNC(op_ldrh_immpostidx, imm9, Rn, Rt)
2002 {
2003 PRINTF("ldrh\t%s, [%s],#%"PRId64"\n",
2004 ZREGNAME(0, Rt),
2005 SREGNAME(1, Rn),
2006 SignExtend(9, imm9, 1));
2007 }
2008
OP3FUNC(op_ldrh_immpreidx,imm9,Rn,Rt)2009 OP3FUNC(op_ldrh_immpreidx, imm9, Rn, Rt)
2010 {
2011 PRINTF("ldrh\t%s, [%s,#%"PRId64"]!\n",
2012 ZREGNAME(0, Rt),
2013 SREGNAME(1, Rn),
2014 SignExtend(9, imm9, 1));
2015 }
2016
OP3FUNC(op_ldrh_immunsign,imm12,Rn,Rt)2017 OP3FUNC(op_ldrh_immunsign, imm12, Rn, Rt)
2018 {
2019 if (imm12 == 0) {
2020 PRINTF("ldrh\t%s, [%s]\n",
2021 ZREGNAME(0, Rt),
2022 SREGNAME(1, Rn));
2023 } else {
2024 PRINTF("ldrh\t%s, [%s,#%"PRId64"]\n",
2025 ZREGNAME(0, Rt),
2026 SREGNAME(1, Rn),
2027 ZeroExtend(12, imm12, 2));
2028 }
2029 }
2030
OP5FUNC(op_ldrh_reg,Rm,option,shift,Rn,Rt)2031 OP5FUNC(op_ldrh_reg, Rm, option, shift, Rn, Rt)
2032 {
2033 regoffset_h_common(di, pc, insn, Rm, option, shift, Rn, Rt, 0, "ldrh");
2034 }
2035
OP4FUNC(op_ldrsb_immpostidx,opc,imm9,Rn,Rt)2036 OP4FUNC(op_ldrsb_immpostidx, opc, imm9, Rn, Rt)
2037 {
2038 PRINTF("ldrsb\t%s, [%s],#%"PRId64"\n",
2039 ZREGNAME((opc ^ 1), Rt),
2040 SREGNAME(1, Rn),
2041 SignExtend(9, imm9, 1));
2042 }
2043
OP4FUNC(op_ldrsb_immpreidx,opc,imm9,Rn,Rt)2044 OP4FUNC(op_ldrsb_immpreidx, opc, imm9, Rn, Rt)
2045 {
2046 PRINTF("ldrsb\t%s, [%s,#%"PRId64"]!\n",
2047 ZREGNAME((opc ^ 1), Rt),
2048 SREGNAME(1, Rn),
2049 SignExtend(9, imm9, 1));
2050 }
2051
OP4FUNC(op_ldrsb_immunsign,opc,imm12,Rn,Rt)2052 OP4FUNC(op_ldrsb_immunsign, opc, imm12, Rn, Rt)
2053 {
2054 if (imm12 == 0) {
2055 PRINTF("ldrsb\t%s, [%s]\n",
2056 ZREGNAME((opc ^ 1), Rt),
2057 SREGNAME(1, Rn));
2058 } else {
2059 PRINTF("ldrsb\t%s, [%s,#%"PRId64"]\n",
2060 ZREGNAME((opc ^ 1), Rt),
2061 SREGNAME(1, Rn),
2062 ZeroExtend(12, imm12, 1));
2063 }
2064 }
2065
OP6FUNC(op_ldrsb_reg,opc,Rm,option,shift,Rn,Rt)2066 OP6FUNC(op_ldrsb_reg, opc, Rm, option, shift, Rn, Rt)
2067 {
2068 regoffset_b_common(di, pc, insn, Rm, option, shift, Rn, Rt, "ldrsb");
2069 }
2070
OP4FUNC(op_ldrsh_immpostidx,opc,imm9,Rn,Rt)2071 OP4FUNC(op_ldrsh_immpostidx, opc, imm9, Rn, Rt)
2072 {
2073 PRINTF("ldrsh\t%s, [%s],#%"PRId64"\n",
2074 ZREGNAME((opc ^ 1), Rt),
2075 SREGNAME(1, Rn),
2076 SignExtend(9, imm9, 1));
2077 }
2078
OP4FUNC(op_ldrsh_immpreidx,opc,imm9,Rn,Rt)2079 OP4FUNC(op_ldrsh_immpreidx, opc, imm9, Rn, Rt)
2080 {
2081 PRINTF("ldrsh\t%s, [%s,#%"PRId64"]!\n",
2082 ZREGNAME((opc ^ 1), Rt),
2083 SREGNAME(1, Rn),
2084 SignExtend(9, imm9, 1));
2085 }
2086
OP4FUNC(op_ldrsh_immunsign,opc,imm12,Rn,Rt)2087 OP4FUNC(op_ldrsh_immunsign, opc, imm12, Rn, Rt)
2088 {
2089 if (imm12 == 0) {
2090 PRINTF("ldrsh\t%s, [%s]\n",
2091 ZREGNAME((opc ^ 1), Rt),
2092 SREGNAME(1, Rn));
2093 } else {
2094 PRINTF("ldrsh\t%s, [%s,#%"PRId64"]\n",
2095 ZREGNAME((opc ^ 1), Rt),
2096 SREGNAME(1, Rn),
2097 ZeroExtend(12, imm12, 2));
2098 }
2099 }
2100
OP6FUNC(op_ldrsh_reg,opc,Rm,option,shift,Rn,Rt)2101 OP6FUNC(op_ldrsh_reg, opc, Rm, option, shift, Rn, Rt)
2102 {
2103 regoffset_h_common(di, pc, insn, Rm, option, shift, Rn, Rt, opc ^ 1,
2104 "ldrsh");
2105 }
2106
OP3FUNC(op_ldrsw_immpostidx,imm9,Rn,Rt)2107 OP3FUNC(op_ldrsw_immpostidx, imm9, Rn, Rt)
2108 {
2109 PRINTF("ldrsw\t%s, [%s],#%"PRId64"\n",
2110 ZREGNAME(1, Rt),
2111 SREGNAME(1, Rn),
2112 SignExtend(9, imm9, 1));
2113 }
2114
OP3FUNC(op_ldrsw_immpreidx,imm9,Rn,Rt)2115 OP3FUNC(op_ldrsw_immpreidx, imm9, Rn, Rt)
2116 {
2117 PRINTF("ldrsw\t%s, [%s,#%"PRId64"]!\n",
2118 ZREGNAME(1, Rt),
2119 SREGNAME(1, Rn),
2120 SignExtend(9, imm9, 1));
2121 }
2122
OP3FUNC(op_ldrsw_immunsign,imm12,Rn,Rt)2123 OP3FUNC(op_ldrsw_immunsign, imm12, Rn, Rt)
2124 {
2125 if (imm12 == 0) {
2126 PRINTF("ldrsw\t%s, [%s]\n",
2127 ZREGNAME(1, Rt),
2128 SREGNAME(1, Rn));
2129 } else {
2130 PRINTF("ldrsw\t%s, [%s,#%"PRId64"]\n",
2131 ZREGNAME(1, Rt),
2132 SREGNAME(1, Rn),
2133 ZeroExtend(12, imm12, 4));
2134 }
2135 }
2136
OP2FUNC(op_ldrsw_literal,imm19,Rt)2137 OP2FUNC(op_ldrsw_literal, imm19, Rt)
2138 {
2139 PRINTF("ldrsw\t%s, ", ZREGNAME(1, Rt));
2140 PRINTADDR(SignExtend(19, imm19, 4) + pc);
2141 PRINTF("\n");
2142 }
2143
OP5FUNC(op_ldrsw_reg,Rm,option,shift,Rn,Rt)2144 OP5FUNC(op_ldrsw_reg, Rm, option, shift, Rn, Rt)
2145 {
2146 regoffset_w_common(di, pc, insn, Rm, option, shift, Rn, Rt, "ldrsw");
2147 }
2148
OP4FUNC(op_ldtr,size,imm9,Rn,Rt)2149 OP4FUNC(op_ldtr, size, imm9, Rn, Rt)
2150 {
2151 if (imm9 == 0) {
2152 PRINTF("ldtr\t%s, [%s]\n",
2153 ZREGNAME(size, Rt),
2154 SREGNAME(1, Rn));
2155 } else {
2156 PRINTF("ldtr\t%s, [%s,#%"PRId64"]\n",
2157 ZREGNAME(size, Rt),
2158 SREGNAME(1, Rn),
2159 SignExtend(9, imm9, 1));
2160 }
2161 }
2162
OP3FUNC(op_ldtrb,imm9,Rn,Rt)2163 OP3FUNC(op_ldtrb, imm9, Rn, Rt)
2164 {
2165 if (imm9 == 0) {
2166 PRINTF("ldtrb\t%s, [%s]\n",
2167 ZREGNAME(0, Rt),
2168 SREGNAME(1, Rn));
2169 } else {
2170 PRINTF("ldtrb\t%s, [%s,#%"PRId64"]\n",
2171 ZREGNAME(0, Rt),
2172 SREGNAME(1, Rn),
2173 SignExtend(9, imm9, 1));
2174 }
2175 }
2176
OP3FUNC(op_ldtrh,imm9,Rn,Rt)2177 OP3FUNC(op_ldtrh, imm9, Rn, Rt)
2178 {
2179 if (imm9 == 0) {
2180 PRINTF("ldtrh\t%s, [%s]\n",
2181 ZREGNAME(0, Rt),
2182 SREGNAME(1, Rn));
2183 } else {
2184 PRINTF("ldtrh\t%s, [%s,#%"PRId64"]\n",
2185 ZREGNAME(0, Rt),
2186 SREGNAME(1, Rn),
2187 SignExtend(9, imm9, 1));
2188 }
2189 }
2190
OP4FUNC(op_ldtrsb,opc,imm9,Rn,Rt)2191 OP4FUNC(op_ldtrsb, opc, imm9, Rn, Rt)
2192 {
2193 if (imm9 == 0) {
2194 PRINTF("ldtrsb\t%s, [%s]\n",
2195 ZREGNAME((opc ^ 1), Rt),
2196 SREGNAME(1, Rn));
2197 } else {
2198 PRINTF("ldtrsb\t%s, [%s,#%"PRId64"]\n",
2199 ZREGNAME((opc ^ 1), Rt),
2200 SREGNAME(1, Rn),
2201 SignExtend(9, imm9, 1));
2202 }
2203 }
2204
OP4FUNC(op_ldtrsh,opc,imm9,Rn,Rt)2205 OP4FUNC(op_ldtrsh, opc, imm9, Rn, Rt)
2206 {
2207 if (imm9 == 0) {
2208 PRINTF("ldtrsh\t%s, [%s]\n",
2209 ZREGNAME((opc ^ 1), Rt),
2210 SREGNAME(1, Rn));
2211 } else {
2212 PRINTF("ldtrsh\t%s, [%s,#%"PRId64"]\n",
2213 ZREGNAME((opc ^ 1), Rt),
2214 SREGNAME(1, Rn),
2215 SignExtend(9, imm9, 1));
2216 }
2217 }
2218
OP3FUNC(op_ldtrsw,imm9,Rn,Rt)2219 OP3FUNC(op_ldtrsw, imm9, Rn, Rt)
2220 {
2221 if (imm9 == 0) {
2222 PRINTF("ldtrsw\t%s, [%s]\n",
2223 ZREGNAME(1, Rt),
2224 SREGNAME(1, Rn));
2225 } else {
2226 PRINTF("ldtrsw\t%s, [%s,#%"PRId64"]\n",
2227 ZREGNAME(1, Rt),
2228 SREGNAME(1, Rn),
2229 SignExtend(9, imm9, 1));
2230 }
2231 }
2232
OP4FUNC(op_ldur,size,imm9,Rn,Rt)2233 OP4FUNC(op_ldur, size, imm9, Rn, Rt)
2234 {
2235 if (imm9 == 0) {
2236 PRINTF("ldur\t%s, [%s]\n",
2237 ZREGNAME(size, Rt),
2238 SREGNAME(1, Rn));
2239 } else {
2240 PRINTF("ldur\t%s, [%s,#%"PRId64"]\n",
2241 ZREGNAME(size, Rt),
2242 SREGNAME(1, Rn),
2243 SignExtend(9, imm9, 1));
2244 }
2245 }
2246
OP3FUNC(op_ldurb,imm9,Rn,Rt)2247 OP3FUNC(op_ldurb, imm9, Rn, Rt)
2248 {
2249 if (imm9 == 0) {
2250 PRINTF("ldurb\t%s, [%s]\n",
2251 ZREGNAME(0, Rt),
2252 SREGNAME(1, Rn));
2253 } else {
2254 PRINTF("ldurb\t%s, [%s,#%"PRId64"]\n",
2255 ZREGNAME(0, Rt),
2256 SREGNAME(1, Rn),
2257 SignExtend(9, imm9, 1));
2258 }
2259 }
2260
OP3FUNC(op_ldurh,imm9,Rn,Rt)2261 OP3FUNC(op_ldurh, imm9, Rn, Rt)
2262 {
2263 if (imm9 == 0) {
2264 PRINTF("ldurh\t%s, [%s]\n",
2265 ZREGNAME(0, Rt),
2266 SREGNAME(1, Rn));
2267 } else {
2268 PRINTF("ldurh\t%s, [%s,#%"PRId64"]\n",
2269 ZREGNAME(0, Rt),
2270 SREGNAME(1, Rn),
2271 SignExtend(9, imm9, 1));
2272 }
2273 }
2274
OP4FUNC(op_ldursb,opc,imm9,Rn,Rt)2275 OP4FUNC(op_ldursb, opc, imm9, Rn, Rt)
2276 {
2277 if (imm9 == 0) {
2278 PRINTF("ldursb\t%s, [%s]\n",
2279 ZREGNAME((opc ^ 1), Rt),
2280 SREGNAME(1, Rn));
2281 } else {
2282 PRINTF("ldursb\t%s, [%s,#%"PRId64"]\n",
2283 ZREGNAME((opc ^ 1), Rt),
2284 SREGNAME(1, Rn),
2285 SignExtend(9, imm9, 1));
2286 }
2287 }
2288
OP4FUNC(op_ldursh,opc,imm9,Rn,Rt)2289 OP4FUNC(op_ldursh, opc, imm9, Rn, Rt)
2290 {
2291 if (imm9 == 0) {
2292 PRINTF("ldursh\t%s, [%s]\n",
2293 ZREGNAME((opc ^ 1), Rt),
2294 SREGNAME(1, Rn));
2295 } else {
2296 PRINTF("ldursh\t%s, [%s,#%"PRId64"]\n",
2297 ZREGNAME((opc ^ 1), Rt),
2298 SREGNAME(1, Rn),
2299 SignExtend(9, imm9, 1));
2300 }
2301 }
2302
OP3FUNC(op_ldursw,imm9,Rn,Rt)2303 OP3FUNC(op_ldursw, imm9, Rn, Rt)
2304 {
2305 if (imm9 == 0) {
2306 PRINTF("ldursw\t%s, [%s]\n",
2307 ZREGNAME(1, Rt),
2308 SREGNAME(1, Rn));
2309 } else {
2310 PRINTF("ldursw\t%s, [%s,#%"PRId64"]\n",
2311 ZREGNAME(1, Rt),
2312 SREGNAME(1, Rn),
2313 SignExtend(9, imm9, 1));
2314 }
2315 }
2316
OP4FUNC(op_ldxp,size,Rt2,Rn,Rt)2317 OP4FUNC(op_ldxp, size, Rt2, Rn, Rt)
2318 {
2319 PRINTF("ldxp\t%s, %s, [%s]\n",
2320 ZREGNAME(size, Rt),
2321 ZREGNAME(size, Rt2),
2322 SREGNAME(1, Rn));
2323 }
2324
OP3FUNC(op_ldxr,size,Rn,Rt)2325 OP3FUNC(op_ldxr, size, Rn, Rt)
2326 {
2327 PRINTF("ldxr\t%s, [%s]\n",
2328 ZREGNAME(size, Rt),
2329 SREGNAME(1, Rn));
2330 }
2331
OP2FUNC(op_ldxrb,Rn,Rt)2332 OP2FUNC(op_ldxrb, Rn, Rt)
2333 {
2334 PRINTF("ldxrb\t%s, [%s]\n",
2335 ZREGNAME(0, Rt),
2336 SREGNAME(1, Rn));
2337 }
2338
OP2FUNC(op_ldxrh,Rn,Rt)2339 OP2FUNC(op_ldxrh, Rn, Rt)
2340 {
2341 PRINTF("ldxrh\t%s, [%s]\n",
2342 ZREGNAME(0, Rt),
2343 SREGNAME(1, Rn));
2344 }
2345
OP6FUNC(op_ubfm,sf,n,immr,imms,Rn,Rd)2346 OP6FUNC(op_ubfm, sf, n, immr, imms, Rn, Rd)
2347 {
2348 const uint64_t bitwidth = (sf == 0) ? 32 : 64;
2349
2350 /* ALIAS: lsr_imm,ubfiz,ubfm,ubfx,uxtb,uxth */
2351 if ((imms != (bitwidth - 1)) && ((imms + 1) == immr)) {
2352 PRINTF("lsl\t%s, %s, #%"PRIu64"\n",
2353 ZREGNAME(sf, Rd),
2354 ZREGNAME(sf, Rn),
2355 bitwidth - immr);
2356 } else if (imms == (bitwidth - 1)) {
2357 PRINTF("lsr\t%s, %s, #%"PRIu64"\n",
2358 ZREGNAME(sf, Rd),
2359 ZREGNAME(sf, Rn),
2360 immr);
2361 } else if (imms < immr) {
2362 PRINTF("ubfiz\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
2363 ZREGNAME(sf, Rd),
2364 ZREGNAME(sf, Rn),
2365 (bitwidth - immr) & (bitwidth - 1),
2366 (imms + 1) & (bitwidth - 1));
2367 } else if (BFXPreferred(sf, 1, imms, immr)) {
2368 PRINTF("ubfx\t%s, %s, #%"PRIu64", #%"PRIu64"\n",
2369 ZREGNAME(sf, Rd),
2370 ZREGNAME(sf, Rn),
2371 immr,
2372 (imms - immr + 1) & (bitwidth - 1));
2373 } else if ((immr == 0) && (imms == 7)) {
2374 PRINTF("uxtb\t%s, %s\n",
2375 ZREGNAME(0, Rd),
2376 ZREGNAME(0, Rn));
2377 } else if ((immr == 0) && (imms == 15)) {
2378 PRINTF("uxth\t%s, %s\n",
2379 ZREGNAME(0, Rd),
2380 ZREGNAME(0, Rn));
2381 } else {
2382 UNDEFINED(pc, insn, "undefined");
2383 }
2384 }
2385
OP4FUNC(op_lsl_reg,sf,Rm,Rn,Rd)2386 OP4FUNC(op_lsl_reg, sf, Rm, Rn, Rd)
2387 {
2388 /* ALIAS: lslv */
2389 /* "lsl" always the preferred disassembly */
2390 PRINTF("lsl\t%s, %s, %s\n",
2391 ZREGNAME(sf, Rd),
2392 ZREGNAME(sf, Rn),
2393 ZREGNAME(sf, Rm));
2394 }
2395
OP4FUNC(op_lsr_reg,sf,Rm,Rn,Rd)2396 OP4FUNC(op_lsr_reg, sf, Rm, Rn, Rd)
2397 {
2398 /* ALIAS: lsrv */
2399 /* "lsr" always the preferred disassembly */
2400 PRINTF("lsr\t%s, %s, %s\n",
2401 ZREGNAME(sf, Rd),
2402 ZREGNAME(sf, Rn),
2403 ZREGNAME(sf, Rm));
2404 }
2405
OP5FUNC(op_madd,sf,Rm,Ra,Rn,Rd)2406 OP5FUNC(op_madd, sf, Rm, Ra, Rn, Rd)
2407 {
2408 /* ALIAS: mul */
2409 if (Ra == 31) {
2410 PRINTF("mul\t%s, %s, %s\n",
2411 ZREGNAME(sf, Rd),
2412 ZREGNAME(sf, Rn),
2413 ZREGNAME(sf, Rm));
2414 } else {
2415 PRINTF("madd\t%s, %s, %s, %s\n",
2416 ZREGNAME(sf, Rd),
2417 ZREGNAME(sf, Rn),
2418 ZREGNAME(sf, Rm),
2419 ZREGNAME(sf, Ra));
2420 }
2421 }
2422
OP5FUNC(op_msub,sf,Rm,Ra,Rn,Rd)2423 OP5FUNC(op_msub, sf, Rm, Ra, Rn, Rd)
2424 {
2425 /* ALIAS: mneg */
2426 if (Ra == 31) {
2427 PRINTF("mneg\t%s, %s, %s\n",
2428 ZREGNAME(sf, Rd),
2429 ZREGNAME(sf, Rn),
2430 ZREGNAME(sf, Rm));
2431 } else {
2432 PRINTF("msub\t%s, %s, %s, %s\n",
2433 ZREGNAME(sf, Rd),
2434 ZREGNAME(sf, Rn),
2435 ZREGNAME(sf, Rm),
2436 ZREGNAME(sf, Ra));
2437 }
2438 }
2439
OP6FUNC(op_orr_imm,sf,n,immr,imms,Rn,Rd)2440 OP6FUNC(op_orr_imm, sf, n, immr, imms, Rn, Rd)
2441 {
2442 if (!ValidBitMasks(sf, n, imms, immr)) {
2443 UNDEFINED(pc, insn, "illegal bitmasks");
2444 return;
2445 }
2446
2447 /* ALIAS: mov_bmimm */
2448 #if 1
2449 /* to distinguish from mov_iwimm */
2450 if ((Rn == 31) && !MoveWidePreferred(sf, n, imms, immr)) {
2451 #else
2452 /* "orr Rd, XZR, #imm" -> "mov Rd, #imm" */
2453 (void)MoveWidePreferred;
2454 if (Rn == 31) {
2455 #endif
2456 PRINTF("mov\t%s, #0x%"PRIx64"\n",
2457 SREGNAME(sf, Rd),
2458 DecodeBitMasks(sf, n, imms, immr));
2459 } else {
2460 PRINTF("orr\t%s, %s, #0x%"PRIx64"\n",
2461 SREGNAME(sf, Rd),
2462 ZREGNAME(sf, Rn),
2463 DecodeBitMasks(sf, n, imms, immr));
2464 }
2465 }
2466
2467 OP4FUNC(op_movn, sf, hw, imm16, Rd)
2468 {
2469 const uint64_t mask = (sf == 0) ? 0xffffffff : 0xffffffffffffffffUL;
2470
2471 if ((sf == 0) && (hw >= 2)) {
2472 UNDEFINED(pc, insn, "illegal size");
2473 return;
2474 }
2475
2476 /* ALIAS: mov_iwimm */
2477 if ((hw == 0) || (imm16 == 0)) {
2478 PRINTF("mov\t%s, #0x%"PRIx64"\n",
2479 ZREGNAME(sf, Rd),
2480 (~(ZeroExtend(16, imm16, 1) & mask)) & mask);
2481 } else {
2482 /* movn */
2483 const uint64_t shift = hw * 16;
2484 PRINTF("mov\t%s, #0x%"PRIx64"\n",
2485 ZREGNAME(sf, Rd),
2486 ~(ZeroExtend(16, imm16, 1) << shift) & mask);
2487 }
2488 }
2489
2490 OP6FUNC(op_orr_reg, sf, shift, Rm, imm6, Rn, Rd)
2491 {
2492 /* ALIAS: mov_reg */
2493 if ((Rn == 31) && (imm6 == 0)) {
2494 PRINTF("mov\t%s, %s\n",
2495 ZREGNAME(sf, Rd),
2496 ZREGNAME(sf, Rm));
2497 } else {
2498 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
2499 "orr", NULL, NULL);
2500 }
2501 }
2502
2503 OP4FUNC(op_movz, sf, hw, imm16, Rd)
2504 {
2505 /* ALIAS: mov_wimm */
2506 if ((hw == 0) || (imm16 == 0)) {
2507 PRINTF("mov\t%s, #0x%"PRIx64"\n",
2508 ZREGNAME(sf, Rd),
2509 ZeroExtend(16, imm16, 1));
2510 } else {
2511 const int shift = hw * 16;
2512 #if 0
2513 PRINTF("movz\t%s, #0x%lx, lsl #%d\n",
2514 ZREGNAME(sf, Rd),
2515 ZeroExtend(16, imm16, 1), shift);
2516 #else
2517 /* same as objdump */
2518 PRINTF("mov\t%s, #0x%"PRIx64"\n",
2519 ZREGNAME(sf, Rd),
2520 ZeroExtend(16, imm16, 1) << shift);
2521 #endif
2522 }
2523 }
2524
2525 OP4FUNC(op_movk, sf, hw, imm16, Rd)
2526 {
2527 const int shift = hw * 16;
2528
2529 if (hw == 0) {
2530 PRINTF("movk\t%s, #0x%"PRIx64"\n",
2531 ZREGNAME(sf, Rd),
2532 ZeroExtend(16, imm16, 1));
2533 } else {
2534 PRINTF("movk\t%s, #0x%"PRIx64", lsl #%d\n",
2535 ZREGNAME(sf, Rd),
2536 ZeroExtend(16, imm16, 1), shift);
2537 }
2538 }
2539
2540 OP6FUNC(op_mrs, op0, op1, CRn, CRm, op2, Rt)
2541 {
2542 char buf[SYSREGNAMEBUFLEN];
2543
2544 PRINTF("mrs\t%s, %s\n",
2545 ZREGNAME(1, Rt),
2546 RSYSREGNAME(buf, sizeof(buf), op0, op1, CRn, CRm, op2));
2547 }
2548
2549 OP6FUNC(op_msr, op0, op1, CRn, CRm, op2, Rt)
2550 {
2551 char buf[SYSREGNAMEBUFLEN];
2552
2553 PRINTF("msr\t%s, %s\n",
2554 WSYSREGNAME(buf, sizeof(buf), op0, op1, CRn, CRm, op2),
2555 ZREGNAME(1, Rt));
2556 }
2557
2558 OP3FUNC(op_msr_imm, op1, CRm, op2)
2559 {
2560 const char *pstatefield;
2561
2562 #define MSRIMM_OP(op1, op2) (((op1) << 3) | (op2))
2563
2564 switch (MSRIMM_OP(op1, op2)) {
2565 case MSRIMM_OP(0, 0):
2566 PRINTF("cfinv\n");
2567 return;
2568 case MSRIMM_OP(0, 1):
2569 PRINTF("xaflag\n");
2570 return;
2571 case MSRIMM_OP(0, 2):
2572 PRINTF("axflag\n");
2573 return;
2574 case MSRIMM_OP(0, 3):
2575 pstatefield = "uao";
2576 break;
2577 case MSRIMM_OP(0, 4):
2578 pstatefield = "pan";
2579 break;
2580 case MSRIMM_OP(0, 5):
2581 pstatefield = "spsel";
2582 break;
2583 case MSRIMM_OP(3, 1):
2584 pstatefield = "ssbs";
2585 break;
2586 case MSRIMM_OP(3, 2):
2587 pstatefield = "dit";
2588 break;
2589 case MSRIMM_OP(3, 4):
2590 pstatefield = "tco";
2591 break;
2592 case MSRIMM_OP(3, 6):
2593 pstatefield = "daifset";
2594 break;
2595 case MSRIMM_OP(3, 7):
2596 pstatefield = "daifclr";
2597 break;
2598 default:
2599 UNDEFINED(pc, insn, "illegal op1/op2");
2600 return;
2601 }
2602
2603 PRINTF("msr\t%s, #0x%"PRIx64"\n",
2604 pstatefield, CRm);
2605 }
2606
2607 OP6FUNC(op_orn, sf, shift, Rm, imm6, Rn, Rd)
2608 {
2609 /* ALIAS: mvn */
2610 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
2611 "orn", "mvn", NULL);
2612 }
2613
2614 OP6FUNC(op_sub_shiftreg, sf, shift, Rm, imm6, Rn, Rd)
2615 {
2616 /* ALIAS: neg */
2617 shiftreg_common(di, pc, insn, sf, shift, Rm, imm6, Rn, Rd,
2618 "sub", "neg", NULL);
2619 }
2620
2621 OP4FUNC(op_sbc, sf, Rm, Rn, Rd)
2622 {
2623 /* ALIAS: ngc */
2624 if (Rn == 31) {
2625 PRINTF("ngc\t%s, %s\n",
2626 ZREGNAME(sf, Rd),
2627 ZREGNAME(sf, Rm));
2628 } else {
2629 PRINTF("sbc\t%s, %s, %s\n",
2630 ZREGNAME(sf, Rd),
2631 ZREGNAME(sf, Rn),
2632 ZREGNAME(sf, Rm));
2633 }
2634 }
2635
2636 OP4FUNC(op_sbcs, sf, Rm, Rn, Rd)
2637 {
2638 /* ALIAS: ngcs */
2639 if (Rn == 31) {
2640 PRINTF("ngcs\t%s, %s\n",
2641 ZREGNAME(sf, Rd),
2642 ZREGNAME(sf, Rm));
2643 } else {
2644 PRINTF("sbcs\t%s, %s, %s\n",
2645 ZREGNAME(sf, Rd),
2646 ZREGNAME(sf, Rn),
2647 ZREGNAME(sf, Rm));
2648 }
2649 }
2650
2651 OP3FUNC(op_prfm_imm, imm12, Rn, Rt)
2652 {
2653 if (imm12 == 0) {
2654 PRINTF("prfm\t%s, [%s]\n",
2655 PREFETCHNAME(Rt),
2656 SREGNAME(1, Rn));
2657 } else {
2658 PRINTF("prfm\t%s, [%s,#%"PRId64"]\n",
2659 PREFETCHNAME(Rt),
2660 SREGNAME(1, Rn),
2661 SignExtend(12, imm12, 8));
2662 }
2663 }
2664
2665 OP2FUNC(op_prfm_literal, imm19, Rt)
2666 {
2667 PRINTF("prfm\t%s, ", PREFETCHNAME(Rt));
2668 PRINTADDR(SignExtend(19, imm19, 4) + pc);
2669 PRINTF("\n");
2670 }
2671
2672 OP5FUNC(op_prfm_reg, Rm, option, shift, Rn, Rt)
2673 {
2674 int r;
2675
2676 if ((r = regoffset_option_to_r(option)) < 0) {
2677 UNDEFINED(pc, insn, "illegal option");
2678 return;
2679 }
2680
2681 if (shift == 0) {
2682 PRINTF("prfm\t%s, [%s,%s%s]\n",
2683 PREFETCHNAME(Rt),
2684 SREGNAME(1, Rn),
2685 ZREGNAME(r, Rm),
2686 SHIFTOP8(option,
2687 "", "", ",uxtw", "", "", "", ",sxtw", ",sxtx"));
2688 } else {
2689 PRINTF("prfm\t%s, [%s,%s,%s #%d]\n",
2690 PREFETCHNAME(Rt),
2691 SREGNAME(1, Rn),
2692 ZREGNAME(r, Rm),
2693 SHIFTOP8(option,
2694 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
2695 3);
2696 }
2697 }
2698
2699 OP3FUNC(op_prfum, imm9, Rn, Rt)
2700 {
2701 if (imm9 == 0) {
2702 PRINTF("prfum\t%s, [%s]\n",
2703 PREFETCHNAME(Rt),
2704 SREGNAME(1, Rn));
2705 } else {
2706 PRINTF("prfum\t%s, [%s,#%"PRId64"]\n",
2707 PREFETCHNAME(Rt),
2708 SREGNAME(1, Rn),
2709 SignExtend(9, imm9, 1));
2710 }
2711 }
2712
2713 OP1FUNC(op_ret, Rn)
2714 {
2715 if (Rn == 30)
2716 PRINTF("ret\n");
2717 else
2718 PRINTF("ret\t%s\n", ZREGNAME(1, Rn));
2719 }
2720
2721 OP4FUNC(op_rev, sf, opc, Rn, Rd)
2722 {
2723 /*
2724 * sf opc insn
2725 * -- --- -------------
2726 * 0 00 rbit Wd,Wn
2727 * 0 01 rev16 Wd,Wn
2728 * 0 10 rev Wd,Wn
2729 * 0 11 undefined
2730 * 1 00 rbit Xd,Xn
2731 * 1 01 rev16 Xd,Xn
2732 * 1 10 rev32 Xd,Xn
2733 * 1 11 rev Xd,Xn
2734 */
2735 const char *const opcode[2][4] = {
2736 { "rbit", "rev16", "rev", NULL },
2737 { "rbit", "rev16", "rev32", "rev" }
2738 };
2739 const char *const op = opcode[sf][opc];
2740
2741 if (op == NULL) {
2742 UNDEFINED(pc, insn, "undefined");
2743 return;
2744 }
2745
2746 PRINTF("%s\t%s, %s\n",
2747 op,
2748 ZREGNAME(sf, Rd),
2749 ZREGNAME(sf, Rn));
2750 }
2751
2752 OP4FUNC(op_ror_reg, sf, Rm, Rn, Rd)
2753 {
2754 /* ALIAS: rorv */
2755 /* "ror" always the preferred disassembly */
2756 PRINTF("ror\t%s, %s, %s\n",
2757 ZREGNAME(sf, Rd),
2758 ZREGNAME(sf, Rn),
2759 ZREGNAME(sf, Rm));
2760 }
2761
2762 OP4FUNC(op_sdiv, sf, Rm, Rn, Rd)
2763 {
2764 PRINTF("sdiv\t%s, %s, %s\n",
2765 ZREGNAME(sf, Rd),
2766 ZREGNAME(sf, Rn),
2767 ZREGNAME(sf, Rm));
2768 }
2769
2770 OP4FUNC(op_smaddl, Rm, Ra, Rn, Rd)
2771 {
2772 /* ALIAS: smull */
2773 if (Ra == 31) {
2774 PRINTF("smull\t%s, %s, %s\n",
2775 ZREGNAME(1, Rd),
2776 ZREGNAME(0, Rn),
2777 ZREGNAME(0, Rm));
2778 } else {
2779 PRINTF("smaddl\t%s, %s, %s, %s\n",
2780 ZREGNAME(1, Rd),
2781 ZREGNAME(0, Rn),
2782 ZREGNAME(0, Rm),
2783 ZREGNAME(1, Ra));
2784 }
2785 }
2786
2787 OP1FUNC(op_smc, imm16)
2788 {
2789 PRINTF("smc\t#0x%"PRIx64"\n", imm16);
2790 }
2791
2792 OP4FUNC(op_smsubl, Rm, Ra, Rn, Rd)
2793 {
2794 /* ALIAS: smnegl */
2795 if (Ra == 31) {
2796 PRINTF("smnegl\t%s, %s, %s\n",
2797 ZREGNAME(1, Rd),
2798 ZREGNAME(0, Rn),
2799 ZREGNAME(0, Rm));
2800 } else {
2801 PRINTF("smsubl\t%s, %s, %s, %s\n",
2802 ZREGNAME(1, Rd),
2803 ZREGNAME(0, Rn),
2804 ZREGNAME(0, Rm),
2805 ZREGNAME(1, Ra));
2806 }
2807 }
2808
2809 OP3FUNC(op_smulh, Rm, Rn, Rd)
2810 {
2811 PRINTF("smulh\t%s, %s, %s\n",
2812 ZREGNAME(1, Rd),
2813 ZREGNAME(1, Rn),
2814 ZREGNAME(1, Rm));
2815 }
2816
2817 OP3FUNC(op_stlr, size, Rn, Rt)
2818 {
2819 PRINTF("stlr\t%s, [%s]\n",
2820 ZREGNAME(size, Rt),
2821 SREGNAME(1, Rn));
2822 }
2823
2824 OP2FUNC(op_stlrb, Rn, Rt)
2825 {
2826 PRINTF("stlrb\t%s, [%s]\n",
2827 ZREGNAME(0, Rt),
2828 SREGNAME(1, Rn));
2829 }
2830
2831 OP2FUNC(op_stlrh, Rn, Rt)
2832 {
2833 PRINTF("stlrh\t%s, [%s]\n",
2834 ZREGNAME(0, Rt),
2835 SREGNAME(1, Rn));
2836 }
2837
2838 OP5FUNC(op_stlxp, size, Rs, Rt2, Rn, Rt)
2839 {
2840 PRINTF("stlxp\t%s, %s, [%s]\n",
2841 ZREGNAME(size, Rt),
2842 ZREGNAME(size, Rt2),
2843 SREGNAME(1, Rn));
2844 }
2845
2846 OP4FUNC(op_stlxr, size, Rs, Rn, Rt)
2847 {
2848 PRINTF("stlxr\t%s, [%s]\n",
2849 ZREGNAME(size, Rt),
2850 SREGNAME(1, Rn));
2851 }
2852
2853 OP3FUNC(op_stlxrb, Rs, Rn, Rt)
2854 {
2855 PRINTF("stlxrb\t%s, [%s]\n",
2856 ZREGNAME(0, Rt),
2857 SREGNAME(1, Rn));
2858 }
2859
2860 OP3FUNC(op_stlxrh, Rs, Rn, Rt)
2861 {
2862 PRINTF("stlxrh\t%s, [%s]\n",
2863 ZREGNAME(0, Rt),
2864 SREGNAME(1, Rn));
2865 }
2866
2867 OP5FUNC(op_stnp, sf, imm7, Rt2, Rn, Rt)
2868 {
2869 if (imm7 == 0) {
2870 PRINTF("stnp\t%s, %s, [%s]\n",
2871 ZREGNAME(sf, Rt),
2872 ZREGNAME(sf, Rt2),
2873 SREGNAME(1, Rn));
2874 } else {
2875 PRINTF("stnp\t%s, %s, [%s,#%"PRId64"]\n",
2876 ZREGNAME(sf, Rt),
2877 ZREGNAME(sf, Rt2),
2878 SREGNAME(1, Rn),
2879 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
2880 }
2881 }
2882
2883 OP5FUNC(op_stp_postidx, sf, imm7, Rt2, Rn, Rt)
2884 {
2885 PRINTF("stp\t%s, %s, [%s],#%"PRId64"\n",
2886 ZREGNAME(sf, Rt),
2887 ZREGNAME(sf, Rt2),
2888 SREGNAME(1, Rn),
2889 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
2890 }
2891
2892 OP5FUNC(op_stp_preidx, sf, imm7, Rt2, Rn, Rt)
2893 {
2894 PRINTF("stp\t%s, %s, [%s,#%"PRId64"]!\n",
2895 ZREGNAME(sf, Rt),
2896 ZREGNAME(sf, Rt2),
2897 SREGNAME(1, Rn),
2898 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
2899 }
2900
2901 OP5FUNC(op_stp_signed, sf, imm7, Rt2, Rn, Rt)
2902 {
2903 if (imm7 == 0) {
2904 PRINTF("stp\t%s, %s, [%s]\n",
2905 ZREGNAME(sf, Rt),
2906 ZREGNAME(sf, Rt2),
2907 SREGNAME(1, Rn));
2908 } else {
2909 PRINTF("stp\t%s, %s, [%s,#%"PRId64"]\n",
2910 ZREGNAME(sf, Rt),
2911 ZREGNAME(sf, Rt2),
2912 SREGNAME(1, Rn),
2913 SignExtend(7, imm7, (sf == 0) ? 4 : 8));
2914 }
2915 }
2916
2917 OP4FUNC(op_str_immpostidx, size, imm9, Rn, Rt)
2918 {
2919 PRINTF("str\t%s, [%s],#%"PRId64"\n",
2920 ZREGNAME(size, Rt),
2921 SREGNAME(1, Rn),
2922 SignExtend(9, imm9, 1));
2923 }
2924
2925 OP4FUNC(op_str_immpreidx, size, imm9, Rn, Rt)
2926 {
2927 PRINTF("str\t%s, [%s,#%"PRId64"]!\n",
2928 ZREGNAME(size, Rt),
2929 SREGNAME(1, Rn),
2930 SignExtend(9, imm9, 1));
2931 }
2932
2933 OP4FUNC(op_str_immunsign, size, imm12, Rn, Rt)
2934 {
2935 if (imm12 == 0) {
2936 PRINTF("str\t%s, [%s]\n",
2937 ZREGNAME(size, Rt),
2938 SREGNAME(1, Rn));
2939 } else {
2940 PRINTF("str\t%s, [%s,#%"PRIu64"]\n",
2941 ZREGNAME(size, Rt),
2942 SREGNAME(1, Rn),
2943 ZeroExtend(12, imm12, (size == 0) ? 4 : 8));
2944 }
2945 }
2946
2947 OP6FUNC(op_str_reg, size, Rm, option, shift, Rn, Rt)
2948 {
2949 regoffset_x_common(di, pc, insn, size, Rm, option, shift, Rn, Rt,
2950 "str");
2951 }
2952
2953 OP3FUNC(op_strb_immpostidx, imm9, Rn, Rt)
2954 {
2955 PRINTF("strb\t%s, [%s],#%"PRId64"\n",
2956 ZREGNAME(0, Rt),
2957 SREGNAME(1, Rn),
2958 SignExtend(9, imm9, 1));
2959 }
2960
2961 OP3FUNC(op_strb_immpreidx, imm9, Rn, Rt)
2962 {
2963 PRINTF("strb\t%s, [%s,#%"PRId64"]!\n",
2964 ZREGNAME(0, Rt),
2965 SREGNAME(1, Rn),
2966 SignExtend(9, imm9, 1));
2967 }
2968
2969 OP3FUNC(op_strb_immunsign, imm12, Rn, Rt)
2970 {
2971 if (imm12 == 0) {
2972 PRINTF("strb\t%s, [%s]\n",
2973 ZREGNAME(0, Rt),
2974 SREGNAME(1, Rn));
2975 } else {
2976 PRINTF("strb\t%s, [%s,#%"PRIu64"]\n",
2977 ZREGNAME(0, Rt),
2978 SREGNAME(1, Rn),
2979 ZeroExtend(12, imm12, 1));
2980 }
2981 }
2982
2983 OP5FUNC(op_strb_reg, Rm, option, shift, Rn, Rt)
2984 {
2985 regoffset_b_common(di, pc, insn, Rm, option, shift, Rn, Rt, "strb");
2986 }
2987
2988 OP3FUNC(op_strh_immpostidx, imm9, Rn, Rt)
2989 {
2990 PRINTF("strh\t%s, [%s],#%"PRId64"\n",
2991 ZREGNAME(0, Rt),
2992 SREGNAME(1, Rn),
2993 SignExtend(9, imm9, 1));
2994 }
2995
2996 OP3FUNC(op_strh_immpreidx, imm9, Rn, Rt)
2997 {
2998 PRINTF("strh\t%s, [%s,#%"PRId64"]!\n",
2999 ZREGNAME(0, Rt),
3000 SREGNAME(1, Rn),
3001 SignExtend(9, imm9, 1));
3002 }
3003
3004 OP3FUNC(op_strh_immunsign, imm12, Rn, Rt)
3005 {
3006 if (imm12 == 0) {
3007 PRINTF("strh\t%s, [%s]\n",
3008 ZREGNAME(0, Rt),
3009 SREGNAME(1, Rn));
3010 } else {
3011 PRINTF("strh\t%s, [%s,#%"PRId64"]\n",
3012 ZREGNAME(0, Rt),
3013 SREGNAME(1, Rn),
3014 ZeroExtend(12, imm12, 2));
3015 }
3016 }
3017
3018 OP5FUNC(op_strh_reg, Rm, option, shift, Rn, Rt)
3019 {
3020 regoffset_h_common(di, pc, insn, Rm, option, shift, Rn, Rt, 0, "strh");
3021 }
3022
3023 OP4FUNC(op_sttr, size, imm9, Rn, Rt)
3024 {
3025 if (imm9 == 0) {
3026 PRINTF("sttr\t%s, [%s]\n",
3027 ZREGNAME(size, Rt),
3028 SREGNAME(1, Rn));
3029 } else {
3030 PRINTF("sttr\t%s, [%s,#%"PRId64"]\n",
3031 ZREGNAME(size, Rt),
3032 SREGNAME(1, Rn),
3033 SignExtend(9, imm9, 1));
3034 }
3035 }
3036
3037 OP3FUNC(op_sttrb, imm9, Rn, Rt)
3038 {
3039 if (imm9 == 0) {
3040 PRINTF("sttrb\t%s, [%s]\n",
3041 ZREGNAME(0, Rt),
3042 SREGNAME(1, Rn));
3043 } else {
3044 PRINTF("sttrb\t%s, [%s,#%"PRId64"]\n",
3045 ZREGNAME(0, Rt),
3046 SREGNAME(1, Rn),
3047 SignExtend(9, imm9, 1));
3048 }
3049 }
3050
3051 OP3FUNC(op_sttrh, imm9, Rn, Rt)
3052 {
3053 if (imm9 == 0) {
3054 PRINTF("sttrh\t%s, [%s]\n",
3055 ZREGNAME(0, Rt),
3056 SREGNAME(1, Rn));
3057 } else {
3058 PRINTF("sttrh\t%s, [%s,#%"PRId64"]\n",
3059 ZREGNAME(0, Rt),
3060 SREGNAME(1, Rn),
3061 SignExtend(9, imm9, 1));
3062 }
3063 }
3064
3065 OP4FUNC(op_stur, size, imm9, Rn, Rt)
3066 {
3067 if (imm9 == 0) {
3068 PRINTF("stur\t%s, [%s]\n",
3069 ZREGNAME(size, Rt),
3070 SREGNAME(1, Rn));
3071 } else {
3072 PRINTF("stur\t%s, [%s,#%"PRId64"]\n",
3073 ZREGNAME(size, Rt),
3074 SREGNAME(1, Rn),
3075 SignExtend(9, imm9, 1));
3076 }
3077 }
3078
3079 OP3FUNC(op_sturb, imm9, Rn, Rt)
3080 {
3081 if (imm9 == 0) {
3082 PRINTF("sturb\t%s, [%s]\n",
3083 ZREGNAME(0, Rt),
3084 SREGNAME(1, Rn));
3085 } else {
3086 PRINTF("sturb\t%s, [%s,#%"PRId64"]\n",
3087 ZREGNAME(0, Rt),
3088 SREGNAME(1, Rn),
3089 SignExtend(9, imm9, 1));
3090 }
3091 }
3092
3093 OP3FUNC(op_sturh, imm9, Rn, Rt)
3094 {
3095 if (imm9 == 0) {
3096 PRINTF("sturh\t%s, [%s]\n",
3097 ZREGNAME(0, Rt),
3098 SREGNAME(1, Rn));
3099 } else {
3100 PRINTF("sturh\t%s, [%s,#%"PRId64"]\n",
3101 ZREGNAME(0, Rt),
3102 SREGNAME(1, Rn),
3103 SignExtend(9, imm9, 1));
3104 }
3105 }
3106
3107 OP5FUNC(op_stxp, size, Rs, Rt2, Rn, Rt)
3108 {
3109 PRINTF("stxp\t%s, %s, [%s]\n",
3110 ZREGNAME(size, Rt),
3111 ZREGNAME(size, Rt2),
3112 SREGNAME(1, Rn));
3113 }
3114
3115 OP4FUNC(op_stxr, size, Rs, Rn, Rt)
3116 {
3117 PRINTF("stxr\t%s, %s, [%s]\n",
3118 ZREGNAME(0, Rs),
3119 ZREGNAME(size, Rt),
3120 SREGNAME(1, Rn));
3121 }
3122
3123 OP3FUNC(op_stxrb, Rs, Rn, Rt)
3124 {
3125 PRINTF("stxrb\t%s, %s, [%s]\n",
3126 ZREGNAME(0, Rs),
3127 ZREGNAME(0, Rt),
3128 SREGNAME(1, Rn));
3129 }
3130
3131 OP3FUNC(op_stxrh, Rs, Rn, Rt)
3132 {
3133 PRINTF("stxrh\t%s, %s, [%s]\n",
3134 ZREGNAME(0, Rs),
3135 ZREGNAME(0, Rt),
3136 SREGNAME(1, Rn));
3137 }
3138
3139 OP6FUNC(op_sub_extreg, sf, Rm, option, imm3, Rn, Rd)
3140 {
3141 extendreg_common(di, pc, insn, sf, Rm, option, imm3, Rn, Rd,
3142 "sub", NULL);
3143 }
3144
3145 OP5FUNC(op_sub_imm, sf, shift, imm12, Rn, Rd)
3146 {
3147 if (shift & 2) {
3148 UNDEFINED(pc, insn, "illegal shift");
3149 return;
3150 }
3151
3152 PRINTF("sub\t%s, %s, #0x%"PRIx64"%s\n",
3153 SREGNAME(sf, Rd),
3154 SREGNAME(sf, Rn),
3155 ZeroExtend(12, imm12, 1),
3156 SHIFTOP2(shift, "", ", lsl #12"));
3157 }
3158
3159 OP1FUNC(op_svc, imm16)
3160 {
3161 PRINTF("svc\t#0x%"PRIx64"\n",
3162 imm16);
3163 }
3164
3165 OP5FUNC(op_sysl, op1, CRn, CRm, op2, Rt)
3166 {
3167 PRINTF("sysl\t%s, #%"PRIu64", %s, %s, #%"PRIu64"\n",
3168 ZREGNAME(1, Rt),
3169 op1,
3170 CREGNAME(CRn),
3171 CREGNAME(CRm),
3172 op2);
3173 }
3174
3175 OP4FUNC(op_tbnz, b5, b40, imm14, Rt)
3176 {
3177 uint64_t bit = (b5 << 5) + b40;
3178
3179 PRINTF("tbnz\t%s, #%"PRIu64", ",
3180 ZREGNAME(b5, Rt),
3181 bit);
3182 PRINTADDR(SignExtend(14, imm14, 4) + pc);
3183 PRINTF("\n");
3184 }
3185
3186 OP4FUNC(op_tbz, b5, b40, imm14, Rt)
3187 {
3188 uint64_t bit = (b5 << 5) + b40;
3189
3190 PRINTF("tbz\t%s, #%"PRIu64", ",
3191 ZREGNAME(b5, Rt),
3192 bit);
3193 PRINTADDR(SignExtend(14, imm14, 4) + pc);
3194 PRINTF("\n");
3195 }
3196
3197 OP4FUNC(op_udiv, sf, Rm, Rn, Rd)
3198 {
3199 PRINTF("udiv\t%s, %s, %s\n",
3200 ZREGNAME(sf, Rd),
3201 ZREGNAME(sf, Rn),
3202 ZREGNAME(sf, Rm));
3203 }
3204
3205 OP4FUNC(op_umaddl, Rm, Ra, Rn, Rd)
3206 {
3207 /* ALIAS: umull */
3208 if (Ra == 31) {
3209 PRINTF("umull\t%s, %s, %s\n",
3210 ZREGNAME(1, Rd),
3211 ZREGNAME(0, Rn),
3212 ZREGNAME(0, Rm));
3213 } else {
3214 PRINTF("umaddl\t%s, %s, %s, %s\n",
3215 ZREGNAME(1, Rd),
3216 ZREGNAME(0, Rn),
3217 ZREGNAME(0, Rm),
3218 ZREGNAME(1, Ra));
3219 }
3220 }
3221
3222 OP4FUNC(op_umsubl, Rm, Ra, Rn, Rd)
3223 {
3224 /* ALIAS: umnegl */
3225 if (Ra == 31) {
3226 PRINTF("umnegl\t%s, %s, %s\n",
3227 ZREGNAME(1, Rd),
3228 ZREGNAME(1, Rn),
3229 ZREGNAME(1, Rm));
3230 } else {
3231 PRINTF("umsubl\t%s, %s, %s, %s\n",
3232 ZREGNAME(1, Rd),
3233 ZREGNAME(1, Rn),
3234 ZREGNAME(1, Rm),
3235 ZREGNAME(1, Ra));
3236 }
3237 }
3238
3239 OP3FUNC(op_umulh, Rm, Rn, Rd)
3240 {
3241 PRINTF("umulh\t%s, %s, %s\n",
3242 ZREGNAME(1, Rd),
3243 ZREGNAME(1, Rn),
3244 ZREGNAME(1, Rm));
3245 }
3246
3247 /*
3248 * load/store SIMD instructions
3249 */
3250 OP6FUNC(op_simd_ldstnp, opc, l, imm7, Rt2, Rn, Rt)
3251 {
3252 const char *op = (l == 0) ? "stnp" : "ldnp";
3253 const int regsz = (opc & 3) + 2;
3254
3255 if (opc == 3) {
3256 UNDEFINED(pc, insn, "illegal opc");
3257 return;
3258 }
3259
3260 if (imm7 == 0) {
3261 PRINTF("%s\t%s, %s, [%s]\n",
3262 op,
3263 FREGNAME(regsz, Rt),
3264 FREGNAME(regsz, Rt2),
3265 SREGNAME(1, Rn));
3266 } else {
3267 PRINTF("%s\t%s, %s, [%s,#%"PRId64"]\n",
3268 op,
3269 FREGNAME(regsz, Rt),
3270 FREGNAME(regsz, Rt2),
3271 SREGNAME(1, Rn),
3272 SignExtend(7, imm7, (4 << opc)));
3273 }
3274 }
3275
3276 OP6FUNC(op_simd_ldstp_postidx, opc, l, imm7, Rt2, Rn, Rt)
3277 {
3278 const char *op = (l == 0) ? "stp" : "ldp";
3279 const int regsz = (opc & 3) + 2;
3280
3281 PRINTF("%s\t%s, %s, [%s],#%"PRId64"\n",
3282 op,
3283 FREGNAME(regsz, Rt),
3284 FREGNAME(regsz, Rt2),
3285 SREGNAME(1, Rn),
3286 SignExtend(7, imm7, (4 << opc)));
3287 }
3288
3289 OP6FUNC(op_simd_ldstp_preidx, opc, l, imm7, Rt2, Rn, Rt)
3290 {
3291 const char *op = (l == 0) ? "stp" : "ldp";
3292 const int regsz = (opc & 3) + 2;
3293
3294 PRINTF("%s\t%s, %s, [%s,#%"PRId64"]!\n",
3295 op,
3296 FREGNAME(regsz, Rt),
3297 FREGNAME(regsz, Rt2),
3298 SREGNAME(1, Rn),
3299 SignExtend(7, imm7, (4 << opc)));
3300 }
3301
3302 OP6FUNC(op_simd_ldstp_signed, opc, l, imm7, Rt2, Rn, Rt)
3303 {
3304 const char *op = (l == 0) ? "stp" : "ldp";
3305 const int regsz = (opc & 3) + 2;
3306
3307 if (opc == 3) {
3308 UNDEFINED(pc, insn, "illegal opc");
3309 return;
3310 }
3311
3312 if (imm7 == 0) {
3313 PRINTF("%s\t%s, %s, [%s]\n",
3314 op,
3315 FREGNAME(regsz, Rt),
3316 FREGNAME(regsz, Rt2),
3317 SREGNAME(1, Rn));
3318 } else {
3319 PRINTF("%s\t%s, %s, [%s,#%"PRId64"]\n",
3320 op,
3321 FREGNAME(regsz, Rt),
3322 FREGNAME(regsz, Rt2),
3323 SREGNAME(1, Rn),
3324 SignExtend(7, imm7, (4 << opc)));
3325 }
3326 }
3327
3328 static inline int
3329 simd_ldstr_regsz(uint64_t size, uint64_t opc)
3330 {
3331 if ((opc & 2) == 0)
3332 return size;
3333 if (size == 0)
3334 return 4;
3335 return -1;
3336 }
3337
3338 OP5FUNC(op_simd_ldstr_immpostidx, size, opc, imm9, Rn, Rt)
3339 {
3340 const char *op = ((opc & 1) == 0) ? "str" : "ldr";
3341 int regsz;
3342
3343 if ((regsz = simd_ldstr_regsz(size, opc)) < 0) {
3344 UNDEFINED(pc, insn, "illegal size/opc");
3345 return;
3346 }
3347
3348 PRINTF("%s\t%s, [%s],#%"PRId64"\n",
3349 op,
3350 FREGNAME(regsz, Rt),
3351 SREGNAME(1, Rn),
3352 SignExtend(9, imm9, 1));
3353 }
3354
3355 OP5FUNC(op_simd_ldstr_immpreidx, size, opc, imm9, Rn, Rt)
3356 {
3357 const char *op = ((opc & 1) == 0) ? "str" : "ldr";
3358 int regsz;
3359
3360 if ((regsz = simd_ldstr_regsz(size, opc)) < 0) {
3361 UNDEFINED(pc, insn, "illegal size/opc");
3362 return;
3363 }
3364
3365 PRINTF("%s\t%s, [%s,#%"PRId64"]!\n",
3366 op,
3367 FREGNAME(regsz, Rt),
3368 SREGNAME(1, Rn),
3369 SignExtend(9, imm9, 1));
3370 }
3371
3372 OP5FUNC(op_simd_ldstr_immunsign, size, opc, imm12, Rn, Rt)
3373 {
3374 const char *op = ((opc & 1) == 0) ? "str" : "ldr";
3375 int regsz;
3376
3377 if ((regsz = simd_ldstr_regsz(size, opc)) < 0) {
3378 UNDEFINED(pc, insn, "illegal size/opc");
3379 return;
3380 }
3381
3382 if (imm12 == 0) {
3383 PRINTF("%s\t%s, [%s]\n",
3384 op,
3385 FREGNAME(regsz, Rt),
3386 SREGNAME(1, Rn));
3387 } else {
3388 PRINTF("%s\t%s, [%s,#%"PRIu64"]\n",
3389 op,
3390 FREGNAME(regsz, Rt),
3391 SREGNAME(1, Rn),
3392 ZeroExtend(12, imm12, 1 << regsz));
3393 }
3394 }
3395
3396 OP7FUNC(op_simd_ldstr_reg, size, opc, Rm, option, S, Rn, Rt)
3397 {
3398 const char *op = ((opc & 1) == 0) ? "str" : "ldr";
3399 int regsz, r;
3400
3401 if ((regsz = simd_ldstr_regsz(size, opc)) < 0) {
3402 UNDEFINED(pc, insn, "illegal size/opc");
3403 return;
3404 }
3405
3406 if ((r = regoffset_option_to_r(option)) < 0) {
3407 UNDEFINED(pc, insn, "illegal option");
3408 return;
3409 }
3410
3411 if (S == 0) {
3412 PRINTF("%s\t%s, [%s,%s%s]\n",
3413 op,
3414 FREGNAME(regsz, Rt),
3415 SREGNAME(1, Rn),
3416 ZREGNAME(r, Rm),
3417 SHIFTOP8(option,
3418 "", "", ",uxtw", "", "", "", ",sxtw", ",sxtx"));
3419 } else {
3420 u_int amount = regsz;
3421 PRINTF("%s\t%s, [%s,%s,%s #%u]\n",
3422 op,
3423 FREGNAME(regsz, Rt),
3424 SREGNAME(1, Rn),
3425 ZREGNAME(r, Rm),
3426 SHIFTOP8(option,
3427 "", "", "uxtw", "lsl", "", "", "sxtw", "sxtx"),
3428 amount);
3429 }
3430 }
3431
3432 OP4FUNC(op_simd_aes, m, d, Rn, Rt)
3433 {
3434 const char *aesop[2][2] = {
3435 { "aese", "aesd", },
3436 { "aesmc", "aesimc" }
3437 };
3438
3439 PRINTF("%s\t%s.16b, %s.16b\n",
3440 aesop[m & 1][d & 1],
3441 VREGNAME(Rn),
3442 VREGNAME(Rt));
3443 }
3444
3445 OP4FUNC(op_simd_sha_reg3, Rm, op, Rn, Rd)
3446 {
3447 const char *shaop[8] = {
3448 "sha1c", "sha1p", "sha1m", "sha1su0",
3449 "sha256h", "sha256h2", "sha256su1", NULL
3450 };
3451
3452 switch (op) {
3453 case 0:
3454 case 1:
3455 case 2:
3456 PRINTF("%s\t%s, %s, %s.4s\n",
3457 shaop[op],
3458 FREGNAME(FREGSZ_Q, Rd),
3459 FREGNAME(FREGSZ_S, Rn),
3460 VREGNAME(Rm));
3461 break;
3462
3463 case 4:
3464 case 5:
3465 PRINTF("%s\t%s, %s, %s.4s\n",
3466 shaop[op],
3467 FREGNAME(FREGSZ_Q, Rd),
3468 FREGNAME(FREGSZ_Q, Rn),
3469 VREGNAME(Rm));
3470 break;
3471
3472 case 3:
3473 case 6:
3474 PRINTF("%s\t%s.4s, %s.4s, %s.4s\n",
3475 shaop[op],
3476 VREGNAME(Rd),
3477 VREGNAME(Rn),
3478 VREGNAME(Rm));
3479 break;
3480
3481 default:
3482 UNDEFINED(pc, insn, "illegal sha operation");
3483 break;
3484 }
3485 }
3486
3487 OP3FUNC(op_simd_sha_reg2, op, Rn, Rd)
3488 {
3489 const char *shaop[4] = {
3490 "sha1h", "sha1su1", "sha256su0", NULL
3491 };
3492
3493 switch (op) {
3494 case 0:
3495 PRINTF("%s\t%s, %s\n",
3496 shaop[op],
3497 FREGNAME(FREGSZ_S, Rd),
3498 FREGNAME(FREGSZ_S, Rn));
3499 break;
3500 case 1:
3501 case 2:
3502 PRINTF("%s\t%s.4s, %s.4s\n",
3503 shaop[op],
3504 VREGNAME(Rd),
3505 VREGNAME(Rn));
3506 break;
3507 default:
3508 UNDEFINED(pc, insn, "illegal sha operation");
3509 break;
3510 }
3511 }
3512
3513 OP4FUNC(op_simd_sha512_reg3, Rm, op, Rn, Rd)
3514 {
3515 const char *shaop[4] = {
3516 "sha512h", "sha512h2", "sha512su1", "rax1"
3517 };
3518
3519 switch (op) {
3520 case 0:
3521 case 1:
3522 PRINTF("%s\t%s, %s, %s.2d\n",
3523 shaop[op],
3524 FREGNAME(FREGSZ_Q, Rd),
3525 FREGNAME(FREGSZ_Q, Rn),
3526 VREGNAME(Rm));
3527 break;
3528 case 2:
3529 case 3:
3530 PRINTF("%s\t%s.2d, %s,.2d %s.2d\n",
3531 shaop[op],
3532 VREGNAME(Rd),
3533 VREGNAME(Rn),
3534 VREGNAME(Rm));
3535 break;
3536 }
3537 }
3538
3539 OP3FUNC(op_simd_sha512_reg2, op, Rn, Rd)
3540 {
3541 const char *shaop[4] = {
3542 "sha512su0", "sm4e", NULL, NULL
3543 };
3544
3545 switch (op) {
3546 case 0:
3547 case 1:
3548 PRINTF("%s\t%s.2d, %s.2d\n",
3549 shaop[op],
3550 VREGNAME(Rd),
3551 VREGNAME(Rn));
3552 break;
3553 default:
3554 UNDEFINED(pc, insn, "illegal sha512 operation");
3555 break;
3556 }
3557 }
3558
3559 OP5FUNC(op_simd_pmull, q, size, Rm, Rn, Rd)
3560 {
3561 const char *op = (q == 0) ? "pmull" : "pmull2";
3562 const char *regspec_Ta[4] = {
3563 "8h", NULL, NULL, "1q"
3564 };
3565 const char *regspec_Tb[8] = {
3566 "8b", "16b", NULL, NULL,
3567 NULL, NULL, "1d", "2d"
3568 };
3569
3570 if ((regspec_Ta[size & 3] != NULL) &&
3571 (regspec_Tb[((size & 3) << 1) + (q & 1)] != NULL)) {
3572 PRINTF("%s\t%s.%s, %s.%s, %s.%s\n",
3573 op,
3574 VREGNAME(Rd), regspec_Ta[size & 3],
3575 VREGNAME(Rn), regspec_Tb[((size & 3) << 1) + (q & 1)],
3576 VREGNAME(Rd), regspec_Tb[((size & 3) << 1) + (q & 1)]);
3577 } else {
3578 UNDEFINED(pc, insn, "illegal pmull size");
3579 }
3580 }
3581
3582 OP1FUNC(op_eretaa, m)
3583 {
3584 if (m == 0)
3585 PRINTF("eretaa\n");
3586 else
3587 PRINTF("eretab\n");
3588
3589 }
3590
3591 OP1FUNC(op_retaa, m)
3592 {
3593 if (m == 0)
3594 PRINTF("retaa\n");
3595 else
3596 PRINTF("retab\n");
3597 }
3598
3599 OP4FUNC(op_blraa, z, m, Rn, Rm)
3600 {
3601 if (z == 0) {
3602 if (Rm != 31) {
3603 UNDEFINED(pc, insn, "undefined");
3604 } else {
3605 PRINTF("%s\t%s\n",
3606 SHIFTOP2(m, "blraaz", "blrabz"),
3607 SREGNAME(1, Rn));
3608 }
3609 } else {
3610 PRINTF("%s\t%s, %s\n",
3611 SHIFTOP2(m, "blraa", "blrab"),
3612 SREGNAME(1, Rn),
3613 SREGNAME(1, Rm));
3614 }
3615 }
3616
3617 OP4FUNC(op_braa, z, m, Rn, Rm)
3618 {
3619 if (z == 0) {
3620 if (Rm != 31) {
3621 UNDEFINED(pc, insn, "undefined");
3622 } else {
3623 PRINTF("%s\t%s\n",
3624 SHIFTOP2(m, "braaz", "brabz"),
3625 SREGNAME(1, Rn));
3626 }
3627 } else {
3628 PRINTF("%s\t%s, %s\n",
3629 SHIFTOP2(m, "braa", "brab"),
3630 SREGNAME(1, Rn),
3631 SREGNAME(1, Rm));
3632 }
3633 }
3634
3635 OP4FUNC(op_pacda, z, m, Rn, Rd)
3636 {
3637 if (z != 0) {
3638 if (Rn != 31) {
3639 UNDEFINED(pc, insn, "undefined");
3640 } else {
3641 PRINTF("%s\t%s\n",
3642 SHIFTOP2(m, "pacdza", "pacdzb"),
3643 SREGNAME(1, Rd));
3644 }
3645 } else {
3646 PRINTF("%s\t%s, %s\n",
3647 SHIFTOP2(m, "pacda", "pacdb"),
3648 ZREGNAME(1, Rd),
3649 SREGNAME(1, Rn));
3650 }
3651 }
3652
3653 OP4FUNC(op_pacia, z, m, Rn, Rd)
3654 {
3655 if (z != 0) {
3656 if (Rn != 31) {
3657 UNDEFINED(pc, insn, "undefined");
3658 } else {
3659 PRINTF("%s\t%s\n",
3660 SHIFTOP2(m, "paciza", "pacizb"),
3661 SREGNAME(1, Rd));
3662 }
3663 } else {
3664 PRINTF("%s\t%s, %s\n",
3665 SHIFTOP2(m, "pacia", "pacib"),
3666 ZREGNAME(1, Rd),
3667 SREGNAME(1, Rn));
3668 }
3669 }
3670
3671 OP3FUNC(op_pacga, Rm, Rn, Rd)
3672 {
3673 PRINTF("pacga\t%s, %s, %s\n",
3674 ZREGNAME(1, Rd),
3675 ZREGNAME(1, Rn),
3676 SREGNAME(1, Rm));
3677 }
3678
3679 OP1FUNC(op_xpaci, Rd)
3680 {
3681 PRINTF("xpaci\t%s\n",
3682 ZREGNAME(1, Rd));
3683 }
3684
3685 OP1FUNC(op_xpacd, Rd)
3686 {
3687 PRINTF("xpacd\t%s\n",
3688 ZREGNAME(1, Rd));
3689 }
3690
3691 OP0FUNC(op_xpaclri)
3692 {
3693 PRINTF("xpaclri\n");
3694 }
3695
3696 /*
3697 * SIMD instructions are not supported except some insns.
3698 * They are disassembled as '.insn 0xXXXXXXXX'.
3699 */
3700 struct bitpos {
3701 uint8_t pos;
3702 uint8_t width;
3703 };
3704
3705 struct insn_info {
3706 uint32_t mask;
3707 uint32_t pattern;
3708 #define INSN_MAXARG 8
3709 struct bitpos bitinfo[INSN_MAXARG];
3710 OPFUNC_DECL(void (*opfunc),,,,,,,,);
3711 };
3712
3713 /* define code format { {bitpos, bitwidth}, ... (maximum 8 args) } */
3714 #define FMT_NOARG \
3715 {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3716 #define FMT_RD \
3717 {{ 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3718 #define FMT_RN \
3719 {{ 5, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3720 #define FMT_RN_RT \
3721 {{ 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3722 #define FMT_M \
3723 {{10, 1}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3724 #define FMT_CRM \
3725 {{ 8, 4}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3726 #define FMT_CRM_OP2 \
3727 {{ 8, 4}, { 5, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3728 #define FMT_OP2_RN_RD \
3729 {{10, 2}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3730 #define FMT_Z_M_RN_RD \
3731 {{13, 1}, {10, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3732 #define FMT_M_D_RN_RD \
3733 {{13, 1}, {12, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3734 #define FMT_OP3_RN_RD \
3735 {{12, 3}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3736 #define FMT_OP1_CRM_OP2 \
3737 {{16, 3}, { 8, 4}, { 5, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3738 #define FMT_OP1_CRN_CRM_OP2_RT \
3739 {{16, 3}, {12, 4}, { 8, 4}, { 5, 3}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3740 #define FMT_RM_RN_RD \
3741 {{16, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3742 #define FMT_RS_RN_RT \
3743 {{16, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3744 #define FMT_RM_OP2_RN_RD \
3745 {{16, 5}, {10, 2}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3746 #define FMT_RM_OP_RN_RD \
3747 {{16, 5}, {12, 3}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3748 #define FMT_RM_RA_RN_RD \
3749 {{16, 5}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3750 #define FMT_IMM9_RN_RT \
3751 {{12, 9}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3752 #define FMT_RM_OPT_SHIFT_RN_RT \
3753 {{16, 5}, {13, 3}, {12, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3754 #define FMT_IMM16 \
3755 {{ 5,16}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3756 #define FMT_IMM16_LL \
3757 {{ 5,16}, { 0, 2}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3758 #define FMT_OP0_OP1_CRN_CRM_OP2_RT \
3759 {{19, 2}, {16, 3}, {12, 4}, { 8, 4}, { 5, 3}, { 0, 5}, { 0, 0}, { 0, 0}}
3760 #define FMT_IMM7_RT2_RN_RT \
3761 {{15, 7}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3762 #define FMT_IMM12_RN_RT \
3763 {{10,12}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3764 #define FMT_OPC_IMM9_RN_RT \
3765 {{22, 1}, {12, 9}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3766 #define FMT_OPC_RM_OPT_SHIFT_RN_RT \
3767 {{22, 1}, {16, 5}, {13, 3}, {12, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3768 #define FMT_OPC_IMM12_RN_RT \
3769 {{22, 1}, {10,12}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3770 #define FMT_IMM19_COND \
3771 {{ 5,19}, { 0, 4}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3772 #define FMT_IMM19_RT \
3773 {{ 5,19}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3774 #define FMT_Z_M_RN_RM \
3775 {{24, 1}, {10, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3776 #define FMT_IMM26 \
3777 {{ 0,26}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3778 #define FMT_SIZE_RN_RT \
3779 {{30, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3780 #define FMT_SIZE_RT2_RN_RT \
3781 {{30, 1}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3782 #define FMT_SIZE_RS_RN_RT \
3783 {{30, 1}, {16, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3784 #define FMT_SIZE_RS_RT2_RN_RT \
3785 {{30, 1}, {16, 5}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3786 #define FMT_SIZE_IMM9_RN_RT \
3787 {{30, 1}, {12, 9}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3788 #define FMT_SIZE_RM_OPT_SHIFT_RN_RT \
3789 {{30, 1}, {16, 5}, {13, 3}, {12, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3790 #define FMT_SIZE_IMM12_RN_RT \
3791 {{30, 1}, {10,12}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3792 #define FMT_Q_SIZE_RM_RN_RD \
3793 {{30, 1}, {22, 2}, {16, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3794 #define FMT_SIZE_IMM19_RT \
3795 {{30, 1}, { 5,19}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3796 #define FMT_IMMLO_IMMHI_RD \
3797 {{29, 2}, { 5,19}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3798 #define FMT_SF_RN_RD \
3799 {{31, 1}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3800 #define FMT_SF_OPC_RN_RD \
3801 {{31, 1}, {10, 2}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3802 #define FMT_SF_RM_RN_RD \
3803 {{31, 1}, {16, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3804 #define FMT_SF_RM_SZ_RN_RD \
3805 {{31, 1}, {16, 5}, {10, 2}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3806 #define FMT_SF_RM_RA_RN_RD \
3807 {{31, 1}, {16, 5}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3808 #define FMT_SF_IMM5_COND_RN_NZCV \
3809 {{31, 1}, {16, 5}, {12, 4}, { 5, 5}, { 0, 4}, { 0, 0}, { 0, 0}, { 0, 0}}
3810 #define FMT_SF_RM_COND_RN_NZCV \
3811 {{31, 1}, {16, 5}, {12, 4}, { 5, 5}, { 0, 4}, { 0, 0}, { 0, 0}, { 0, 0}}
3812 #define FMT_SF_RM_COND_RN_RD \
3813 {{31, 1}, {16, 5}, {12, 4}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3814 #define FMT_SF_RM_OPT_IMM3_RN_RD \
3815 {{31, 1}, {16, 5}, {13, 3}, {10, 3}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3816 #define FMT_SF_RM_OP_IMM3_RN_RD \
3817 {{31, 1}, {16, 5}, {13, 3}, {10, 3}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3818 #define FMT_SF_IMM7_RT2_RN_RT \
3819 {{31, 1}, {15, 7}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3820 #define FMT_SF_N_RM_IMM6_RN_RD \
3821 {{31, 1}, {22, 1}, {16, 5}, {10, 6}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3822 #define FMT_SF_N_RM_IMMS_RN_RD \
3823 {{31, 1}, {22, 1}, {16, 5}, {10, 6}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3824 #define FMT_SF_HW_IMM16_RD \
3825 {{31, 1}, {21, 2}, { 5,16}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3826 #define FMT_SF_N_IMMR_IMMS_RN_RD \
3827 {{31, 1}, {22, 1}, {16, 6}, {10, 6}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3828 #define FMT_SF_SHIFT_RM_IMM6_RN_RD \
3829 {{31, 1}, {22, 2}, {16, 5}, {10, 6}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3830 #define FMT_SF_SHIFT_IMM12_RN_RD \
3831 {{31, 1}, {22, 2}, {10,12}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3832 #define FMT_SF_IMM19_RT \
3833 {{31, 1}, { 5,19}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3834 #define FMT_B5_B40_IMM14_RT \
3835 {{31, 1}, {19, 5}, { 5,14}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}
3836 #define FMT_OPC_L_IMM7_RT2_RN_RT \
3837 {{30, 2}, {22, 1}, {15, 7}, {10, 5}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}}
3838 #define FMT_SIZE_OPC_IMM9_RN_RT \
3839 {{30, 2}, {22, 2}, {12, 9}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3840 #define FMT_SIZE_OPC_RM_OPT_S_RN_RT \
3841 {{30, 2}, {22, 2}, {16, 5}, {13, 3}, {12, 1}, { 5, 5}, { 0, 5}, { 0, 0}}
3842 #define FMT_SIZE_OPC_IMM12_RN_RT \
3843 {{30, 2}, {22, 2}, {10,12}, { 5, 5}, { 0, 5}, { 0, 0}, { 0, 0}, { 0, 0}}
3844
3845 static const struct insn_info insn_tables[] = {
3846 /* mask, pattern, opcode format, opfunc */
3847 /* --------- ---------- --------------------------- ------------------ */
3848 { 0xffffffff, 0xd6bf03e0, FMT_NOARG, op_drps },
3849 { 0xffffffff, 0xd69f03e0, FMT_NOARG, op_eret },
3850 { 0xffffffff, 0xd50320ff, FMT_NOARG, op_xpaclri },
3851 { 0xffffffe0, 0xdac143e0, FMT_RD, op_xpaci },
3852 { 0xffffffe0, 0xdac147e0, FMT_RD, op_xpacd },
3853 { 0xfffffc1f, 0xd63f0000, FMT_RN, op_blr },
3854 { 0xfffffc1f, 0xd61f0000, FMT_RN, op_br },
3855 { 0xfffffc1f, 0xd65f0000, FMT_RN, op_ret },
3856 { 0xfffffc00, 0x08dffc00, FMT_RN_RT, op_ldarb },
3857 { 0xfffffc00, 0x48dffc00, FMT_RN_RT, op_ldarh },
3858 { 0xfffffc00, 0x085ffc00, FMT_RN_RT, op_ldaxrb },
3859 { 0xfffffc00, 0x485ffc00, FMT_RN_RT, op_ldaxrh },
3860 { 0xfffffc00, 0x085f7c00, FMT_RN_RT, op_ldxrb },
3861 { 0xfffffc00, 0x485f7c00, FMT_RN_RT, op_ldxrh },
3862 { 0xfffffc00, 0x089ffc00, FMT_RN_RT, op_stlrb },
3863 { 0xfffffc00, 0x489ffc00, FMT_RN_RT, op_stlrh },
3864 { 0xfffffbff, 0xd69f0bff, FMT_M, op_eretaa },
3865 { 0xfffffbff, 0xd65f0bff, FMT_M, op_retaa },
3866 { 0xfffff0ff, 0xd503305f, FMT_CRM, op_clrex },
3867 { 0xfffff0ff, 0xd50330bf, FMT_CRM, op_dmb },
3868 { 0xfffff0ff, 0xd503309f, FMT_CRM, op_dsb },
3869 { 0xfffff0ff, 0xd50330df, FMT_CRM, op_isb },
3870 { 0xfffff01f, 0xd503201f, FMT_CRM_OP2, op_hint },
3871 { 0xfffff000, 0xcec08000, FMT_OP2_RN_RD, op_simd_sha512_reg2 },
3872 { 0xffffd800, 0xdac10800, FMT_Z_M_RN_RD, op_pacda },
3873 { 0xffffd800, 0xdac10000, FMT_Z_M_RN_RD, op_pacia },
3874 { 0xffffcc00, 0x4e284800, FMT_M_D_RN_RD, op_simd_aes },
3875 { 0xffff8c00, 0x5e280800, FMT_OP3_RN_RD, op_simd_sha_reg2 },
3876 { 0xfff8f01f, 0xd500401f, FMT_OP1_CRM_OP2, op_msr_imm },
3877 { 0xfff80000, 0xd5080000, FMT_OP1_CRN_CRM_OP2_RT, op_sys },
3878 { 0xfff80000, 0xd5280000, FMT_OP1_CRN_CRM_OP2_RT, op_sysl },
3879 { 0xffe0fc00, 0x9b407c00, FMT_RM_RN_RD, op_smulh },
3880 { 0xffe0fc00, 0x0800fc00, FMT_RS_RN_RT, op_stlxrb },
3881 { 0xffe0fc00, 0x4800fc00, FMT_RS_RN_RT, op_stlxrh },
3882 { 0xffe0fc00, 0x08007c00, FMT_RS_RN_RT, op_stxrb },
3883 { 0xffe0fc00, 0x48007c00, FMT_RS_RN_RT, op_stxrh },
3884 { 0xffe0fc00, 0x9bc07c00, FMT_RM_RN_RD, op_umulh },
3885 { 0xffe0fc00, 0x9ac03000, FMT_RM_RN_RD, op_pacga },
3886 { 0xffe0f000, 0xce608000, FMT_RM_OP2_RN_RD, op_simd_sha512_reg3 },
3887 { 0xffe08c00, 0x5e000000, FMT_RM_OP_RN_RD, op_simd_sha_reg3 },
3888 { 0xffe08000, 0x9b208000, FMT_RM_RA_RN_RD, op_smsubl },
3889 { 0xffe08000, 0x9ba08000, FMT_RM_RA_RN_RD, op_umsubl },
3890 { 0xffe08000, 0x9b200000, FMT_RM_RA_RN_RD, op_smaddl },
3891 { 0xffe08000, 0x9ba00000, FMT_RM_RA_RN_RD, op_umaddl },
3892 { 0xffe00c00, 0x38400400, FMT_IMM9_RN_RT, op_ldrb_immpostidx },
3893 { 0xffe00c00, 0x38400c00, FMT_IMM9_RN_RT, op_ldrb_immpreidx },
3894 { 0xffe00c00, 0x38600800, FMT_RM_OPT_SHIFT_RN_RT, op_ldrb_reg },
3895 { 0xffe00c00, 0x78400400, FMT_IMM9_RN_RT, op_ldrh_immpostidx },
3896 { 0xffe00c00, 0x78400c00, FMT_IMM9_RN_RT, op_ldrh_immpreidx },
3897 { 0xffe00c00, 0x78600800, FMT_RM_OPT_SHIFT_RN_RT, op_ldrh_reg },
3898 { 0xffe00c00, 0xb8800400, FMT_IMM9_RN_RT, op_ldrsw_immpostidx },
3899 { 0xffe00c00, 0xb8800c00, FMT_IMM9_RN_RT, op_ldrsw_immpreidx },
3900 { 0xffe00c00, 0xb8a00800, FMT_RM_OPT_SHIFT_RN_RT, op_ldrsw_reg },
3901 { 0xffe00c00, 0x38400800, FMT_IMM9_RN_RT, op_ldtrb },
3902 { 0xffe00c00, 0x78400800, FMT_IMM9_RN_RT, op_ldtrh },
3903 { 0xffe00c00, 0xb8800800, FMT_IMM9_RN_RT, op_ldtrsw },
3904 { 0xffe00c00, 0x38400000, FMT_IMM9_RN_RT, op_ldurb },
3905 { 0xffe00c00, 0x78400000, FMT_IMM9_RN_RT, op_ldurh },
3906 { 0xffe00c00, 0xb8800000, FMT_IMM9_RN_RT, op_ldursw },
3907 { 0xffe00c00, 0xf8a00800, FMT_RM_OPT_SHIFT_RN_RT, op_prfm_reg },
3908 { 0xffe00c00, 0xf8800000, FMT_IMM9_RN_RT, op_prfum },
3909 { 0xffe00c00, 0x38000400, FMT_IMM9_RN_RT, op_strb_immpostidx },
3910 { 0xffe00c00, 0x38000c00, FMT_IMM9_RN_RT, op_strb_immpreidx },
3911 { 0xffe00c00, 0x38200800, FMT_RM_OPT_SHIFT_RN_RT, op_strb_reg },
3912 { 0xffe00c00, 0x78000400, FMT_IMM9_RN_RT, op_strh_immpostidx },
3913 { 0xffe00c00, 0x78000c00, FMT_IMM9_RN_RT, op_strh_immpreidx },
3914 { 0xffe00c00, 0x78200800, FMT_RM_OPT_SHIFT_RN_RT, op_strh_reg },
3915 { 0xffe00c00, 0x38000800, FMT_IMM9_RN_RT, op_sttrb },
3916 { 0xffe00c00, 0x78000800, FMT_IMM9_RN_RT, op_sttrh },
3917 { 0xffe00c00, 0x38000000, FMT_IMM9_RN_RT, op_sturb },
3918 { 0xffe00c00, 0x78000000, FMT_IMM9_RN_RT, op_sturh },
3919 { 0xffe0001f, 0xd4200000, FMT_IMM16, op_brk },
3920 { 0xffe0001f, 0xd4400000, FMT_IMM16, op_hlt },
3921 { 0xffe0001f, 0xd4000002, FMT_IMM16, op_hvc },
3922 { 0xffe0001f, 0xd4000003, FMT_IMM16, op_smc },
3923 { 0xffe0001f, 0xd4000001, FMT_IMM16, op_svc },
3924 { 0xffe0001c, 0xd4a00000, FMT_IMM16_LL, op_dcps },
3925 { 0xffe00000, 0xd5200000, FMT_OP0_OP1_CRN_CRM_OP2_RT, op_mrs },
3926 { 0xffe00000, 0xd5000000, FMT_OP0_OP1_CRN_CRM_OP2_RT, op_msr },
3927 { 0xffc00000, 0x68c00000, FMT_IMM7_RT2_RN_RT, op_ldpsw_postidx },
3928 { 0xffc00000, 0x69c00000, FMT_IMM7_RT2_RN_RT, op_ldpsw_preidx },
3929 { 0xffc00000, 0x69400000, FMT_IMM7_RT2_RN_RT, op_ldpsw_signed },
3930 { 0xffc00000, 0x39400000, FMT_IMM12_RN_RT, op_ldrb_immunsign },
3931 { 0xffc00000, 0x79400000, FMT_IMM12_RN_RT, op_ldrh_immunsign },
3932 { 0xffc00000, 0xb9800000, FMT_IMM12_RN_RT, op_ldrsw_immunsign },
3933 { 0xffc00000, 0xf9800000, FMT_IMM12_RN_RT, op_prfm_imm },
3934 { 0xffc00000, 0x39000000, FMT_IMM12_RN_RT, op_strb_immunsign },
3935 { 0xffc00000, 0x79000000, FMT_IMM12_RN_RT, op_strh_immunsign },
3936 { 0xffa00c00, 0x38800400, FMT_OPC_IMM9_RN_RT, op_ldrsb_immpostidx },
3937 { 0xffa00c00, 0x38800c00, FMT_OPC_IMM9_RN_RT, op_ldrsb_immpreidx },
3938 { 0xffa00c00, 0x38a00800, FMT_OPC_RM_OPT_SHIFT_RN_RT, op_ldrsb_reg },
3939 { 0xffa00c00, 0x78800400, FMT_OPC_IMM9_RN_RT, op_ldrsh_immpostidx },
3940 { 0xffa00c00, 0x78800c00, FMT_OPC_IMM9_RN_RT, op_ldrsh_immpreidx },
3941 { 0xffa00c00, 0x78a00800, FMT_OPC_RM_OPT_SHIFT_RN_RT, op_ldrsh_reg },
3942 { 0xffa00c00, 0x38800800, FMT_OPC_IMM9_RN_RT, op_ldtrsb },
3943 { 0xffa00c00, 0x78800800, FMT_OPC_IMM9_RN_RT, op_ldtrsh },
3944 { 0xffa00c00, 0x38800000, FMT_OPC_IMM9_RN_RT, op_ldursb },
3945 { 0xffa00c00, 0x78800000, FMT_OPC_IMM9_RN_RT, op_ldursh },
3946 { 0xff800000, 0x39800000, FMT_OPC_IMM12_RN_RT, op_ldrsb_immunsign },
3947 { 0xff800000, 0x79800000, FMT_OPC_IMM12_RN_RT, op_ldrsh_immunsign },
3948 { 0xff000010, 0x54000000, FMT_IMM19_COND, op_b_cond },
3949 { 0xff000000, 0x98000000, FMT_IMM19_RT, op_ldrsw_literal },
3950 { 0xff000000, 0xd8000000, FMT_IMM19_RT, op_prfm_literal },
3951 { 0xfefff800, 0xd63f0800, FMT_Z_M_RN_RM, op_blraa },
3952 { 0xfefff800, 0xd61f0800, FMT_Z_M_RN_RM, op_braa },
3953 { 0xfc000000, 0x14000000, FMT_IMM26, op_b },
3954 { 0xfc000000, 0x94000000, FMT_IMM26, op_bl },
3955 { 0xbffffc00, 0x88dffc00, FMT_SIZE_RN_RT, op_ldar },
3956 { 0xbffffc00, 0x885ffc00, FMT_SIZE_RN_RT, op_ldaxr },
3957 { 0xbffffc00, 0x885f7c00, FMT_SIZE_RN_RT, op_ldxr },
3958 { 0xbffffc00, 0x889ffc00, FMT_SIZE_RN_RT, op_stlr },
3959 { 0xbfff8000, 0x887f8000, FMT_SIZE_RT2_RN_RT, op_ldaxp },
3960 { 0xbfff8000, 0x887f0000, FMT_SIZE_RT2_RN_RT, op_ldxp },
3961 { 0xbfe0fc00, 0x8800fc00, FMT_SIZE_RS_RN_RT, op_stlxr },
3962 { 0xbfe0fc00, 0x88007c00, FMT_SIZE_RS_RN_RT, op_stxr },
3963 { 0xbfe08000, 0x88208000, FMT_SIZE_RS_RT2_RN_RT, op_stlxp },
3964 { 0xbfe08000, 0x88200000, FMT_SIZE_RS_RT2_RN_RT, op_stxp },
3965 { 0xbfe00c00, 0xb8400400, FMT_SIZE_IMM9_RN_RT, op_ldr_immpostidx },
3966 { 0xbfe00c00, 0xb8400c00, FMT_SIZE_IMM9_RN_RT, op_ldr_immpreidx },
3967 { 0xbfe00c00, 0xb8600800, FMT_SIZE_RM_OPT_SHIFT_RN_RT, op_ldr_reg },
3968 { 0xbfe00c00, 0xb8400800, FMT_SIZE_IMM9_RN_RT, op_ldtr },
3969 { 0xbfe00c00, 0xb8400000, FMT_SIZE_IMM9_RN_RT, op_ldur },
3970 { 0xbfe00c00, 0xb8000400, FMT_SIZE_IMM9_RN_RT, op_str_immpostidx },
3971 { 0xbfe00c00, 0xb8000c00, FMT_SIZE_IMM9_RN_RT, op_str_immpreidx },
3972 { 0xbfe00c00, 0xb8200800, FMT_SIZE_RM_OPT_SHIFT_RN_RT, op_str_reg },
3973 { 0xbfe00c00, 0xb8000800, FMT_SIZE_IMM9_RN_RT, op_sttr },
3974 { 0xbfe00c00, 0xb8000000, FMT_SIZE_IMM9_RN_RT, op_stur },
3975 { 0xbfc00000, 0xb9400000, FMT_SIZE_IMM12_RN_RT, op_ldr_immunsign },
3976 { 0xbfc00000, 0xb9000000, FMT_SIZE_IMM12_RN_RT, op_str_immunsign },
3977 { 0xbf20fc00, 0x0e20e000, FMT_Q_SIZE_RM_RN_RD, op_simd_pmull },
3978 { 0xbf000000, 0x18000000, FMT_SIZE_IMM19_RT, op_ldr_literal },
3979 { 0x9f000000, 0x10000000, FMT_IMMLO_IMMHI_RD, op_adr },
3980 { 0x9f000000, 0x90000000, FMT_IMMLO_IMMHI_RD, op_adrp },
3981 { 0x7ffffc00, 0x5ac01400, FMT_SF_RN_RD, op_cls },
3982 { 0x7ffffc00, 0x5ac01000, FMT_SF_RN_RD, op_clz },
3983 { 0x7ffff000, 0x5ac00000, FMT_SF_OPC_RN_RD, op_rev },
3984 { 0x7fe0fc00, 0x5a000000, FMT_SF_RM_RN_RD, op_sbc },
3985 { 0x7fe0fc00, 0x7a000000, FMT_SF_RM_RN_RD, op_sbcs },
3986 { 0x7fe0fc00, 0x1a000000, FMT_SF_RM_RN_RD, op_adc },
3987 { 0x7fe0fc00, 0x3a000000, FMT_SF_RM_RN_RD, op_adcs },
3988 { 0x7fe0fc00, 0x1ac02800, FMT_SF_RM_RN_RD, op_asr_reg },
3989 { 0x7fe0fc00, 0x1ac02000, FMT_SF_RM_RN_RD, op_lsl_reg },
3990 { 0x7fe0fc00, 0x1ac02400, FMT_SF_RM_RN_RD, op_lsr_reg },
3991 { 0x7fe0fc00, 0x1ac02c00, FMT_SF_RM_RN_RD, op_ror_reg },
3992 { 0x7fe0fc00, 0x1ac00c00, FMT_SF_RM_RN_RD, op_sdiv },
3993 { 0x7fe0fc00, 0x1ac00800, FMT_SF_RM_RN_RD, op_udiv },
3994 { 0x7fe0f000, 0x1ac04000, FMT_SF_RM_SZ_RN_RD, op_crc32 },
3995 { 0x7fe0f000, 0x1ac05000, FMT_SF_RM_SZ_RN_RD, op_crc32c },
3996 { 0x7fe08000, 0x1b008000, FMT_SF_RM_RA_RN_RD, op_msub },
3997 { 0x7fe08000, 0x1b000000, FMT_SF_RM_RA_RN_RD, op_madd },
3998 { 0x7fe00c10, 0x3a400800, FMT_SF_IMM5_COND_RN_NZCV, op_ccmn_imm },
3999 { 0x7fe00c10, 0x3a400000, FMT_SF_RM_COND_RN_NZCV, op_ccmn_reg },
4000 { 0x7fe00c10, 0x7a400800, FMT_SF_IMM5_COND_RN_NZCV, op_ccmp_imm },
4001 { 0x7fe00c10, 0x7a400000, FMT_SF_RM_COND_RN_NZCV, op_ccmp_reg },
4002 { 0x7fe00c00, 0x5a800000, FMT_SF_RM_COND_RN_RD, op_csinv },
4003 { 0x7fe00c00, 0x5a800400, FMT_SF_RM_COND_RN_RD, op_csneg },
4004 { 0x7fe00c00, 0x1a800400, FMT_SF_RM_COND_RN_RD, op_cinc },
4005 { 0x7fe00c00, 0x1a800000, FMT_SF_RM_COND_RN_RD, op_csel },
4006 { 0x7fe00000, 0x6b200000, FMT_SF_RM_OPT_IMM3_RN_RD, op_subs_extreg },
4007 { 0x7fe00000, 0x0b200000, FMT_SF_RM_OPT_IMM3_RN_RD, op_add_extreg },
4008 { 0x7fe00000, 0x2b200000, FMT_SF_RM_OP_IMM3_RN_RD, op_adds_extreg },
4009 { 0x7fe00000, 0x4b200000, FMT_SF_RM_OPT_IMM3_RN_RD, op_sub_extreg },
4010 { 0x7fc00000, 0x28400000, FMT_SF_IMM7_RT2_RN_RT, op_ldnp },
4011 { 0x7fc00000, 0x28c00000, FMT_SF_IMM7_RT2_RN_RT, op_ldp_postidx },
4012 { 0x7fc00000, 0x29c00000, FMT_SF_IMM7_RT2_RN_RT, op_ldp_preidx },
4013 { 0x7fc00000, 0x29400000, FMT_SF_IMM7_RT2_RN_RT, op_ldp_signed },
4014 { 0x7fc00000, 0x28000000, FMT_SF_IMM7_RT2_RN_RT, op_stnp },
4015 { 0x7fc00000, 0x28800000, FMT_SF_IMM7_RT2_RN_RT, op_stp_postidx },
4016 { 0x7fc00000, 0x29800000, FMT_SF_IMM7_RT2_RN_RT, op_stp_preidx },
4017 { 0x7fc00000, 0x29000000, FMT_SF_IMM7_RT2_RN_RT, op_stp_signed },
4018 { 0x7fa00000, 0x13800000, FMT_SF_N_RM_IMM6_RN_RD, op_ror_imm },
4019 { 0x7f800000, 0x12800000, FMT_SF_HW_IMM16_RD, op_movn },
4020 { 0x7f800000, 0x52800000, FMT_SF_HW_IMM16_RD, op_movz },
4021 { 0x7f800000, 0x32000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_orr_imm },
4022 { 0x7f800000, 0x13000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_sbfm },
4023 { 0x7f800000, 0x53000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_ubfm },
4024 { 0x7f800000, 0x12000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_and_imm },
4025 { 0x7f800000, 0x72000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_ands_imm },
4026 { 0x7f800000, 0x33000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_bfi },
4027 { 0x7f800000, 0x52000000, FMT_SF_N_IMMR_IMMS_RN_RD, op_eor_imm },
4028 { 0x7f800000, 0x72800000, FMT_SF_HW_IMM16_RD, op_movk },
4029 { 0x7f200000, 0x2a200000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_orn },
4030 { 0x7f200000, 0x2a000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_orr_reg },
4031 { 0x7f200000, 0x4b000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_sub_shiftreg },
4032 { 0x7f200000, 0x6b000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_subs_shiftreg },
4033 { 0x7f200000, 0x0b000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_add_shiftreg },
4034 { 0x7f200000, 0x2b000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_adds_shiftreg },
4035 { 0x7f200000, 0x0a000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_and_shiftreg },
4036 { 0x7f200000, 0x6a000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_ands_shiftreg },
4037 { 0x7f200000, 0x0a200000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_bic_shiftreg },
4038 { 0x7f200000, 0x6a200000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_bics_shiftreg },
4039 { 0x7f200000, 0x4a200000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_eon_shiftreg },
4040 { 0x7f200000, 0x4a000000, FMT_SF_SHIFT_RM_IMM6_RN_RD, op_eor_shiftreg },
4041 { 0x7f000000, 0x71000000, FMT_SF_SHIFT_IMM12_RN_RD, op_subs_imm },
4042 { 0x7f000000, 0x11000000, FMT_SF_SHIFT_IMM12_RN_RD, op_add_imm },
4043 { 0x7f000000, 0x31000000, FMT_SF_SHIFT_IMM12_RN_RD, op_adds_imm },
4044 { 0x7f000000, 0x35000000, FMT_SF_IMM19_RT, op_cbnz },
4045 { 0x7f000000, 0x34000000, FMT_SF_IMM19_RT, op_cbz },
4046 { 0x7f000000, 0x51000000, FMT_SF_SHIFT_IMM12_RN_RD, op_sub_imm },
4047 { 0x7f000000, 0x37000000, FMT_B5_B40_IMM14_RT, op_tbnz },
4048 { 0x7f000000, 0x36000000, FMT_B5_B40_IMM14_RT, op_tbz },
4049 { 0x3f800000, 0x2c000000, FMT_OPC_L_IMM7_RT2_RN_RT, op_simd_ldstnp },
4050 { 0x3f800000, 0x2c800000, FMT_OPC_L_IMM7_RT2_RN_RT, op_simd_ldstp_postidx },
4051 { 0x3f800000, 0x2d800000, FMT_OPC_L_IMM7_RT2_RN_RT, op_simd_ldstp_preidx },
4052 { 0x3f800000, 0x2d000000, FMT_OPC_L_IMM7_RT2_RN_RT, op_simd_ldstp_signed },
4053 { 0x3f200c00, 0x3c000400, FMT_SIZE_OPC_IMM9_RN_RT, op_simd_ldstr_immpostidx },
4054 { 0x3f200c00, 0x3c000c00, FMT_SIZE_OPC_IMM9_RN_RT, op_simd_ldstr_immpreidx },
4055 { 0x3f200c00, 0x3c200800, FMT_SIZE_OPC_RM_OPT_S_RN_RT, op_simd_ldstr_reg },
4056 { 0x3f000000, 0x3d000000, FMT_SIZE_OPC_IMM12_RN_RT, op_simd_ldstr_immunsign },
4057 { 0x00000000, 0x00000000, FMT_NOARG, op_undefined }
4058 };
4059
4060 #define WIDTHMASK(w) (0xffffffff >> (32 - (w)))
4061
4062 void
4063 disasm_insn(const disasm_interface_t *di, uintptr_t loc, uint32_t insn)
4064 {
4065 uint64_t args[INSN_MAXARG];
4066 unsigned int i, j;
4067
4068 for (i = 0; i < __arraycount(insn_tables); i++) {
4069 if ((insn & insn_tables[i].mask) != insn_tables[i].pattern)
4070 continue;
4071
4072 /* extract operands */
4073 for (j = 0; j < INSN_MAXARG; j++) {
4074 if (insn_tables[i].bitinfo[j].width == 0)
4075 break;
4076 args[j] = (insn >> insn_tables[i].bitinfo[j].pos) &
4077 WIDTHMASK(insn_tables[i].bitinfo[j].width);
4078 }
4079 insn_tables[i].opfunc(di, loc, insn,
4080 args[0], args[1], args[2], args[3],
4081 args[4], args[5], args[6], args[7]);
4082 break;
4083 }
4084 }
4085
4086 uintptr_t
4087 disasm(const disasm_interface_t *di, uintptr_t loc)
4088 {
4089 uint32_t insn;
4090
4091 insn = le32toh(di->di_readword(loc));
4092 disasm_insn(di, loc, insn);
4093
4094 /* return next address */
4095 return loc + sizeof(insn);
4096 }
4097