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