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