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