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