xref: /openbsd-src/sys/arch/arm64/arm64/disasm.c (revision 206a9ca3e029a5f72680e37d893a2b6ef825b8d8)
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