1 /*
   2  * Common Development and Distribution License ("CDDL"), version 1.0.
   3  * You may only use this file in accordance with the terms of version
   4  * 1.0 of the CDDL.
   5  *
   6  * A full copy of the text of the CDDL should have accompanied this
   7  * source.  A copy of the CDDL is also available via the Internet at
   8  * http://www.illumos.org/license/CDDL.
   9  */
  10 /*
  11  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  12  * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  13  */
  14 
  15 /*
  16  * This provides basic support for disassembling arm instructions. This is
  17  * derived from the arm reference manual (generic), chapter A3 (ARM DDI 0100l).
  18  * All instructions come in as uint32_t's.
  19  */
  20 
  21 #include <libdisasm.h>
  22 #include <stdint.h>
  23 #include <stdio.h>
  24 #include <sys/byteorder.h>
  25 
  26 #include "libdisasm_impl.h"
  27 
  28 extern size_t strlen(const char *);
  29 extern size_t strlcat(char *, const char *, size_t);
  30 
  31 /*
  32  * Condition code mask and shift, aka bits 28-31.
  33  */
  34 #define ARM_CC_MASK     0xf0000000
  35 #define ARM_CC_SHIFT    28
  36 
  37 /*
  38  * First level of decoding, aka bits 25-27.
  39  */
  40 #define ARM_L1_DEC_MASK 0x0e000000
  41 #define ARM_L1_DEC_SHIFT        25
  42 
  43 /*
  44  * Masks and values for the 0b000 l1 group
  45  */
  46 #define ARM_L1_0_B4_MASK        0x00000010
  47 #define ARM_L1_0_B7_MASK        0x00000080
  48 #define ARM_L1_0_OPMASK 0x01800000
  49 #define ARM_L1_0_SPECOP 0x01000000
  50 #define ARM_L1_0_SMASK  0x00100000
  51 #define ARM_L1_0_ELS_MASK       0x00000060
  52 
  53 /*
  54  * Masks and values for the 0b001 l1 group.
  55  */
  56 #define ARM_L1_1_OPMASK 0x01800000
  57 #define ARM_L1_1_SPECOP 0x01000000
  58 #define ARM_L1_1_SMASK  0x00100000
  59 #define ARM_L1_1_UNDEF_MASK     0x00200000
  60 
  61 /*
  62  * Masks and values for the 0b011 l1 group
  63  */
  64 #define ARM_L1_3_B4_MASK        0x00000010
  65 #define ARM_L1_3_ARCHUN_MASK    0x01f000f0
  66 
  67 /*
  68  * Masks for the 0b111 l1 group
  69  */
  70 #define ARM_L1_7_COPROCMASK     0x00000010
  71 #define ARM_L1_7_SWINTMASK      0x01000000
  72 
  73 /*
  74  * Masks for the data processing instructions (dpi)
  75  */
  76 #define ARM_DPI_OPCODE_MASK     0x01e00000
  77 #define ARM_DPI_OPCODE_SHIFT    21
  78 #define ARM_DPI_IBIT_MASK       0x02000000
  79 #define ARM_DPI_SBIT_MASK       0x00100000
  80 #define ARM_DPI_RN_MASK         0x000f0000
  81 #define ARM_DPI_RN_SHIFT        16
  82 #define ARM_DPI_RD_MASK         0x0000f000
  83 #define ARM_DPI_RD_SHIFT        12
  84 #define ARM_DPI_BIT4_MASK       0x00000010
  85 
  86 #define ARM_DPI_IMM_ROT_MASK    0x00000f00
  87 #define ARM_DPI_IMM_ROT_SHIFT   8
  88 #define ARM_DPI_IMM_VAL_MASK    0x000000ff
  89 
  90 #define ARM_DPI_IMS_SHIMM_MASK  0x00000f80
  91 #define ARM_DPI_IMS_SHIMM_SHIFT 7
  92 #define ARM_DPI_IMS_SHIFT_MASK  0x00000060
  93 #define ARM_DPI_IMS_SHIFT_SHIFT 5
  94 #define ARM_DPI_IMS_RM_MASK     0x0000000f
  95 
  96 #define ARM_DPI_REGS_RS_MASK    0x00000f00
  97 #define ARM_DPI_REGS_RS_SHIFT   8
  98 #define ARM_DPI_REGS_SHIFT_MASK 0x00000060
  99 #define ARM_DPI_REGS_SHIFT_SHIFT        5
 100 #define ARM_DPI_REGS_RM_MASK    0x0000000f
 101 
 102 /*
 103  * Definitions for the word and byte LDR and STR instructions
 104  */
 105 #define ARM_LS_IBIT_MASK        0x02000000
 106 #define ARM_LS_PBIT_MASK        0x01000000
 107 #define ARM_LS_UBIT_MASK        0x00800000
 108 #define ARM_LS_BBIT_MASK        0x00400000
 109 #define ARM_LS_WBIT_MASK        0x00200000
 110 #define ARM_LS_LBIT_MASK        0x00100000
 111 #define ARM_LS_RN_MASK          0x000f0000
 112 #define ARM_LS_RN_SHIFT         16
 113 #define ARM_LS_RD_MASK          0x0000f000
 114 #define ARM_LS_RD_SHIFT         12
 115 
 116 #define ARM_LS_IMM_MASK         0x00000fff
 117 
 118 #define ARM_LS_REG_RM_MASK      0x0000000f
 119 #define ARM_LS_REG_NRM_MASK     0x00000ff0
 120 
 121 #define ARM_LS_SCR_SIMM_MASK    0x00000f80
 122 #define ARM_LS_SCR_SIMM_SHIFT   7
 123 #define ARM_LS_SCR_SCODE_MASK   0x00000060
 124 #define ARM_LS_SCR_SCODE_SHIFT  5
 125 #define ARM_LS_SCR_RM_MASK      0x0000000f
 126 
 127 /*
 128  * Masks for the Load and Store multiple instructions.
 129  */
 130 #define ARM_LSM_PBIT_MASK       0x01000000
 131 #define ARM_LSM_UBIT_MASK       0x00800000
 132 #define ARM_LSM_SBIT_MASK       0x00400000
 133 #define ARM_LSM_WBIT_MASK       0x00200000
 134 #define ARM_LSM_LBIT_MASK       0x00100000
 135 #define ARM_LSM_RN_MASK         0x000f0000
 136 #define ARM_LSM_RN_SHIFT        16
 137 #define ARM_LSM_RLIST_MASK      0x0000ffff
 138 #define ARM_LSM_ADDR_MASK       0x01800000
 139 #define ARM_LSM_ADDR_SHIFT      23
 140 
 141 /*
 142  * Masks for the Extended and Misc. Loads and stores. This is the extension
 143  * space from figure A3-5. Most of them are handled by arm_dis_els() with the
 144  * exception or swap / swap byte and load/store register exclusive which due to
 145  * its nature is handled elsewhere.
 146  */
 147 #define ARM_ELS_SWAP_MASK       0x01b00000
 148 #define ARM_ELS_SWAP_BYTE_MASK  0x00400000
 149 #define ARM_ELS_IS_SWAP         0x01000000
 150 #define ARM_ELS_EXCL_MASK       0x01800000
 151 #define ARM_ELS_PBIT_MASK       0x01000000
 152 #define ARM_ELS_UBIT_MASK       0x00800000
 153 #define ARM_ELS_IBIT_MASK       0x00400000
 154 #define ARM_ELS_WBIT_MASK       0x00200000
 155 #define ARM_ELS_LBIT_MASK       0x00100000
 156 #define ARM_ELS_SBIT_MASK       0x00000040
 157 #define ARM_ELS_HBIT_MASK       0x00000020
 158 #define ARM_ELS_RN_MASK         0x000f0000
 159 #define ARM_ELS_RN_SHIFT        16
 160 #define ARM_ELS_RD_MASK         0x0000f000
 161 #define ARM_ELS_RD_SHIFT        12
 162 #define ARM_ELS_UP_AM_MASK      0x00000f00
 163 #define ARM_ELS_UP_AM_SHIFT     8
 164 #define ARM_ELS_LOW_AM_MASK     0x0000000f
 165 
 166 /*
 167  * Multiply instruction extensino space masks and values
 168  */
 169 #define ARM_EMULT_UNBIT_MASK    0x00400000
 170 #define ARM_EMULT_ABIT_MASK     0x00200000
 171 #define ARM_EMULT_SBIT_MASK     0x00100000
 172 #define ARM_EMULT_RD_MASK       0x000f0000
 173 #define ARM_EMULT_RD_SHIFT      16
 174 #define ARM_EMULT_RN_MASK       0x0000f000
 175 #define ARM_EMULT_RN_SHIFT      12
 176 #define ARM_EMULT_RS_MASK       0x00000f00
 177 #define ARM_EMULT_RS_SHIFT      8
 178 #define ARM_EMULT_RM_MASK       0x0000000f
 179 #define ARM_EMULT_MA_MASK       0x0fc00000
 180 #define ARM_EMULT_UMA_MASK      0x0ff00000
 181 #define ARM_EMULT_UMA_TARG      0x00400000
 182 #define ARM_EMULT_MAL_MASK      0x0f800000
 183 #define ARM_EMULT_MAL_TARG      0x00800000
 184 
 185 /*
 186  * Here we have the masks and target values to indicate instructions from the
 187  * Control and DSP extension space. There are a bunch of not quite related
 188  * instructions, but that's okay. That's how this thing always rolls.
 189  *
 190  * The ARM_CDSP_STATUS_MASK and TARG do not catch the move immediate to status
 191  * register. That's okay because they get handled and separated out in arm_dis.
 192  */
 193 #define ARM_CDSP_STATUS_MASK    0x0f9000f0
 194 #define ARM_CDSP_STATUS_TARG    0x01000000
 195 #define ARM_CDSP_BEX_UP_MASK    0x0ff00000      /* Branch/exchg/link instrs */
 196 #define ARM_CDSP_BEX_UP_TARG    0x01200000
 197 #define ARM_CDSP_BEX_LOW_MASK   0x000000f0
 198 #define ARM_CDSP_BEX_NLOW_TARG  0x00000000      /* Here the target is inverse */
 199 #define ARM_CDSP_CLZ_MASK       0x0ff000f0      /* Count leading zeros */
 200 #define ARM_CDSP_CLZ_TARG       0x01200030
 201 #define ARM_CDSP_SAT_MASK       0x0f9000f0      /* Saturating add/subtract */
 202 #define ARM_CDSP_SAT_TARG       0x01000050
 203 #define ARM_CDSP_BKPT_MASK      0x0ff000f0      /* Software breakpoint */
 204 #define ARM_CDSP_BKPT_TARG      0x01200070
 205 #define ARM_CDSP_SMUL_MASK      0x0f900090      /* Signed multiplies (type 2) */
 206 #define ARM_CDSP_SMUL_TARG      0x01000080
 207 
 208 #define ARM_CDSP_RN_MASK        0x000f0000
 209 #define ARM_CDSP_RN_SHIFT       16
 210 #define ARM_CDSP_RD_MASK        0x0000f000
 211 #define ARM_CDSP_RD_SHIFT       12
 212 #define ARM_CDSP_RS_MASK        0x00000f00
 213 #define ARM_CDSP_RS_SHIFT       8
 214 #define ARM_CDSP_RM_MASK        0x0000000f
 215 
 216 #define ARM_CDSP_STATUS_RBIT    0x00400000
 217 #define ARM_CDSP_MRS_MASK       0x00300000      /* Ditinguish MRS and MSR */
 218 #define ARM_CDSP_MRS_TARG       0x00000000
 219 #define ARM_CDSP_MSR_F_MASK     0x000f0000
 220 #define ARM_CDSP_MSR_F_SHIFT    16
 221 #define ARM_CDSP_MSR_RI_MASK    0x00000f00
 222 #define ARM_CDSP_MSR_RI_SHIFT   8
 223 #define ARM_CDSP_MSR_IMM_MASK   0x000000ff
 224 #define ARM_CDSP_MSR_ISIMM_MASK 0x02000000
 225 
 226 #define ARM_CDSP_BEX_TYPE_MASK  0x000000f0
 227 #define ARM_CDSP_BEX_TYPE_SHIFT 4
 228 #define ARM_CDSP_BEX_TYPE_X     1
 229 #define ARM_CDSP_BEX_TYPE_J     2
 230 #define ARM_CDSP_BEX_TYPE_L     3
 231 
 232 #define ARM_CDSP_SAT_OP_MASK    0x00600000
 233 #define ARM_CDSP_SAT_OP_SHIFT   21
 234 
 235 #define ARM_CDSP_BKPT_UIMM_MASK 0x000fff00
 236 #define ARM_CDSP_BKPT_UIMM_SHIFT        8
 237 #define ARM_CDSP_BKPT_LIMM_MASK 0x0000000f
 238 
 239 #define ARM_CDSP_SMUL_OP_MASK   0x00600000
 240 #define ARM_CDSP_SMUL_OP_SHIFT  21
 241 #define ARM_CDSP_SMUL_X_MASK    0x00000020
 242 #define ARM_CDSP_SMUL_Y_MASK    0x00000040
 243 
 244 /*
 245  * Interrupt
 246  */
 247 #define ARM_SWI_IMM_MASK        0x00ffffff
 248 
 249 /*
 250  * Branch and Link pieces.
 251  */
 252 #define ARM_BRANCH_LBIT_MASK    0x01000000
 253 #define ARM_BRANCH_IMM_MASK     0x00ffffff
 254 #define ARM_BRANCH_SIGN_MASK    0x00800000
 255 #define ARM_BRANCH_POS_SIGN     0x00ffffff
 256 #define ARM_BRANCH_NEG_SIGN     0xff000000
 257 #define ARM_BRANCH_SHIFT        2
 258 
 259 /*
 260  * Unconditional instructions
 261  */
 262 #define ARM_UNI_CPS_MASK        0x0ff10010      /* Change processor state */
 263 #define ARM_UNI_CPS_TARG        0x01000000
 264 #define ARM_UNI_SE_MASK         0x0fff0078      /* Set endianess */
 265 #define ARM_UNI_SE_TARG         0x01010000
 266 #define ARM_UNI_PLD_MASK        0x0d70f000      /* Cach preload */
 267 #define ARM_UNI_PLD_TARG        0x0550f000
 268 #define ARM_UNI_SRS_MASK        0x0e5f0f00      /* Save return state */
 269 #define ARM_UNI_SRS_TARG        0x084d0500
 270 #define ARM_UNI_RFE_MASK        0x0e500f00      /* Return from exception */
 271 #define ARM_UNI_RFE_TARG        0x08100a00
 272 #define ARM_UNI_BLX_MASK        0x0e000000      /* Branch with Link / Thumb */
 273 #define ARM_UNI_BLX_TARG        0x0a000000
 274 #define ARM_UNI_CODRT_MASK      0x0fe00000      /* double reg to coproc */
 275 #define ARM_UNI_CODRT_TARG      0x0c400000
 276 #define ARM_UNI_CORT_MASK       0x0f000010      /* single reg to coproc */
 277 #define ARM_UNI_CORT_TARG       0x0e000010
 278 #define ARM_UNI_CODP_MASK       0x0f000010      /* coproc data processing */
 279 #define ARM_UNI_CODP_TARG       0x0e000000
 280 
 281 #define ARM_UNI_CPS_IMOD_MASK   0x000c0000
 282 #define ARM_UNI_CPS_IMOD_SHIFT  18
 283 #define ARM_UNI_CPS_MMOD_MASK   0x00020000
 284 #define ARM_UNI_CPS_A_MASK      0x00000100
 285 #define ARM_UNI_CPS_I_MASK      0x00000080
 286 #define ARM_UNI_CPS_F_MASK      0x00000040
 287 #define ARM_UNI_CPS_MODE_MASK   0x0000001f
 288 
 289 #define ARM_UNI_SE_BE_MASK      0x00000200
 290 
 291 #define ARM_UNI_SRS_WBIT_MASK   0x00200000
 292 #define ARM_UNI_SRS_MODE_MASK   0x0000000f
 293 
 294 #define ARM_UNI_RFE_WBIT_MASK   0x00200000
 295 
 296 #define ARM_UNI_BLX_IMM_MASK    0x00ffffff
 297 
 298 /*
 299  * Definitions of the ARM Media instruction extension space.
 300  */
 301 #define ARM_MEDIA_L1_MASK       0x01800000      /* First level breakdown */
 302 #define ARM_MEDIA_L1_SHIFT      23
 303 
 304 #define ARM_MEDIA_OP1_MASK      0x00700000
 305 #define ARM_MEDIA_OP1_SHIFT     20
 306 #define ARM_MEDIA_OP2_MASK      0x000000e0
 307 #define ARM_MEDIA_OP2_SHIFT     5
 308 
 309 #define ARM_MEDIA_RN_MASK       0x000f0000
 310 #define ARM_MEDIA_RN_SHIFT      16
 311 #define ARM_MEDIA_RD_MASK       0x0000f000
 312 #define ARM_MEDIA_RD_SHIFT      12
 313 #define ARM_MEDIA_RS_MASK       0x00000f00
 314 #define ARM_MEDIA_RS_SHIFT      8
 315 #define ARM_MEDIA_RM_MASK       0x0000000f
 316 
 317 #define ARM_MEDIA_MULT_X_MASK   0x00000020
 318 
 319 #define ARM_MEDIA_HPACK_MASK    0x00700020      /* Halfword pack */
 320 #define ARM_MEDIA_HPACK_TARG    0x00000000
 321 #define ARM_MEDIA_WSAT_MASK     0x00200020      /* Word saturate */
 322 #define ARM_MEDIA_WSAT_TARG     0x00200000
 323 #define ARM_MEDIA_PHSAT_MASK    0x003000e0      /* Parallel halfword saturate */
 324 #define ARM_MEDIA_PHSAT_TARG    0x00200020
 325 #define ARM_MEDIA_REV_MASK      0x007000e0      /* Byte rev. word */
 326 #define ARM_MEDIA_REV_TARG      0x00300020
 327 #define ARM_MEDIA_BRPH_MASK     0x007000e0      /* Byte rev. packed halfword */
 328 #define ARM_MEDIA_BRPH_TARG     0x003000a0
 329 #define ARM_MEDIA_BRSH_MASK     0x007000e0      /* Byte rev. signed halfword */
 330 #define ARM_MEDIA_BRSH_TARG     0x007000a0
 331 #define ARM_MEDIA_SEL_MASK      0x008000e0      /* Select bytes */
 332 #define ARM_MEDIA_SEL_TARG      0x000000a0
 333 #define ARM_MEDIA_SZE_MASK      0x000000e0      /* Sign/zero extend */
 334 #define ARM_MEDIA_SZE_TARG      0x00000030
 335 
 336 #define ARM_MEDIA_HPACK_OP_MASK 0x00000040
 337 #define ARM_MEDIA_HPACK_SHIFT_MASK      0x00000f80
 338 #define ARM_MEDIA_HPACK_SHIFT_IMM       7
 339 
 340 #define ARM_MEDIA_SAT_U_MASK    0x00400000
 341 #define ARM_MEDIA_SAT_IMM_MASK  0x001f0000
 342 #define ARM_MEDIA_SAT_IMM_SHIFT 16
 343 #define ARM_MEDIA_SAT_SHI_MASK  0x00000f80
 344 #define ARM_MEDIA_SAT_SHI_SHIFT 7
 345 #define ARM_MEDIA_SAT_STYPE_MASK        0x00000040
 346 
 347 #define ARM_MEDIA_SZE_S_MASK    0x00400000
 348 #define ARM_MEDIA_SZE_OP_MASK   0x00300000
 349 #define ARM_MEDIA_SZE_OP_SHIFT  20
 350 #define ARM_MEDIA_SZE_ROT_MASK  0x00000c00
 351 #define ARM_MEDIA_SZE_ROT_SHIFT 10
 352 
 353 /*
 354  * Definitions for coprocessor instructions
 355  */
 356 #define ARM_COPROC_RN_MASK      0x000f0000
 357 #define ARM_COPROC_RN_SHIFT     16
 358 #define ARM_COPROC_RD_MASK      0x0000f000
 359 #define ARM_COPROC_RD_SHIFT     12
 360 #define ARM_COPROC_RM_MASK      0x0000000f
 361 #define ARM_COPROC_NUM_MASK     0x00000f00
 362 #define ARM_COPROC_NUM_SHIFT    8
 363 
 364 #define ARM_COPROC_CDP_OP1_MASK 0x00f00000
 365 #define ARM_COPROC_CDP_OP1_SHIFT        20
 366 #define ARM_COPROC_CDP_OP2_MASK 0x000000e0
 367 #define ARM_COPROC_CDP_OP2_SHIFT        5
 368 
 369 #define ARM_COPROC_CRT_OP1_MASK 0x00e00000
 370 #define ARM_COPROC_CRT_OP1_SHIFT        21
 371 #define ARM_COPROC_CRT_OP2_MASK 0x000000e0
 372 #define ARM_COPROC_CRT_OP2_SHIFT        5
 373 #define ARM_COPROC_CRT_DIR_MASK 0x00100000      /* MCR or MRC */
 374 
 375 #define ARM_COPROC_DRT_MASK     0x01e00000
 376 #define ARM_COPROC_DRT_TARG     0x00400000
 377 #define ARM_COPROC_DRT_OP_MASK  0x000000f0
 378 #define ARM_COPROC_DRT_OP_SHIFT 4
 379 #define ARM_COPROC_DRT_DIR_MASK 0x00100000      /* MCRR or MRRC */
 380 
 381 #define ARM_COPROC_LS_P_MASK    0x01000000
 382 #define ARM_COPROC_LS_U_MASK    0x00800000
 383 #define ARM_COPROC_LS_N_MASK    0x00400000
 384 #define ARM_COPROC_LS_W_MASK    0x00200000
 385 #define ARM_COPROC_LS_L_MASK    0x00100000
 386 #define ARM_COPROC_LS_IMM_MASK  0x000000ff
 387 
 388 /*
 389  * This is the table of condition codes that instructions might have. Every
 390  * instruction starts with a four bit code. The last two codes are special.
 391  * 0b1110 is the always condition. Therefore we leave off its mneomic extension
 392  * and treat it as the empty string. The condition code 0b1111 takes us to a
 393  * separate series of encoded instructions and therefore we go elsewhere with
 394  * them.
 395  */
 396 static const char *arm_cond_names[] = {
 397         "eq",           /* Equal */
 398         "ne",           /* Not Equal */
 399         "cs/hs",        /* Carry set/unsigned higher or same */
 400         "cc/lo",        /* Carry clear/unsigned lower */
 401         "mi",           /* Minus/negative */
 402         "pl",           /* Plus/positive or zero */
 403         "vs",           /* Overflow */
 404         "vc",           /* No overflow */
 405         "hi",           /* Unsigned higher */
 406         "ls",           /* Unsigned lower or same */
 407         "ge",           /* Signed greater than or equal */
 408         "lt",           /* Signed less than */
 409         "gt",           /* Signed greater than */
 410         "le",           /* Signed less than or equal */
 411         "",             /* AL - Always (unconditional) */
 412         NULL            /* Not a condition code */
 413 };
 414 
 415 typedef enum arm_cond_code {
 416         ARM_COND_EQ,    /* Equal */
 417         ARM_COND_NE,    /* Not Equal */
 418         ARM_COND_CSHS,  /* Carry set/unsigned higher or same */
 419         ARM_COND_CCLO,  /* Carry clear/unsigned lower */
 420         ARM_COND_MI,    /* Minus/negative */
 421         ARM_COND_PL,    /* Plus/positive or zero */
 422         ARM_COND_VS,    /* Overflow */
 423         ARM_COND_VC,    /* No overflow */
 424         ARM_COND_HI,    /* Unsigned higher */
 425         ARM_COND_LS,    /* Unsigned lower or same */
 426         ARM_COND_GE,    /* Signed greater than or equal */
 427         ARM_COND_LT,    /* Signed less than */
 428         ARM_COND_GT,    /* Signed greater than */
 429         ARM_COND_LE,    /* Signed less than or equal */
 430         ARM_COND_AL,    /* AL - Always (unconditional) */
 431         ARM_COND_NACC   /* Not a condition code */
 432 } arm_cond_code_t;
 433 
 434 /*
 435  * Registers are encoded surprisingly sanely. It's a 4-bit value that indicates
 436  * which register in question we're working with.
 437  */
 438 static const char *arm_reg_names[] = {
 439         "r0",
 440         "r1",
 441         "r2",
 442         "r3",
 443         "r4",
 444         "r5",
 445         "r6",
 446         "r7",
 447         "r8",
 448         "fp",   /* Alt for r9 */
 449         "r10",
 450         "r11",
 451         "ip",   /* Alt for r12 */
 452         "sp",   /* Alt for r13 */
 453         "lr",   /* Alt for r14 */
 454         "pc"    /* Alt for r15 */
 455 };
 456 
 457 typedef enum arm_reg {
 458         ARM_REG_R0,
 459         ARM_REG_R1,
 460         ARM_REG_R2,
 461         ARM_REG_R3,
 462         ARM_REG_R4,
 463         ARM_REG_R5,
 464         ARM_REG_R6,
 465         ARM_REG_R7,
 466         ARM_REG_R8,
 467         ARM_REG_R9,
 468         ARM_REG_R10,
 469         ARM_REG_R11,
 470         ARM_REG_R12,
 471         ARM_REG_R13,
 472         ARM_REG_R14,
 473         ARM_REG_R15
 474 } arm_reg_t;
 475 
 476 /*
 477  * Default coprocessor names
 478  */
 479 static const char *arm_coproc_names[] = {
 480         "p0",
 481         "p1",
 482         "p2",
 483         "p3",
 484         "p4",
 485         "p5",
 486         "p6",
 487         "p7",
 488         "p8",
 489         "p9",
 490         "p10",
 491         "p11",
 492         "p12",
 493         "p13",
 494         "p14",
 495         "p15"
 496 };
 497 
 498 /*
 499  * These are the opcodes for the instructions which are considered data
 500  * processing instructions.
 501  */
 502 static const char *arm_dpi_opnames[] = {
 503         "and",  /* Logical AND */
 504         "eor",  /* Logical Exclusive OR */
 505         "sub",  /* Subtract */
 506         "rsb",  /* Reverse Subtract */
 507         "add",  /* Add */
 508         "adc",  /* Add with Carry */
 509         "sbc",  /* Subtract with Carry */
 510         "rsc",  /* Reverse Subtract with Carry */
 511         "tst",  /* Test */
 512         "teq",  /* Test Equivalence */
 513         "cmp",  /* Compare */
 514         "cmn",  /* Compare negated */
 515         "orr",  /* Logical (inclusive) OR */
 516         "mov",  /* Move */
 517         "bic",  /* Bit clear */
 518         "mvn"   /* Move not */
 519 };
 520 
 521 typedef enum arm_dpi_opcode {
 522         DPI_OP_AND,     /* Logical AND */
 523         DPI_OP_EOR,     /* Logical Exclusive OR */
 524         DPI_OP_SUB,     /* Subtract */
 525         DPI_OP_RSB,     /* Reverse Subtract */
 526         DPI_OP_ADD,     /* Add */
 527         DPI_OP_ADC,     /* Add with Carry */
 528         DPI_OP_SBC,     /* Subtract with Carry */
 529         DPI_OP_RSC,     /* Reverse Subtract with Carry */
 530         DPI_OP_TST,     /* Test */
 531         DPI_OP_TEQ,     /* Test Equivalence */
 532         DPI_OP_CMP,     /* Compare */
 533         DPI_OP_CMN,     /* Compare negated */
 534         DPI_OP_ORR,     /* Logical (inclusive) OR */
 535         DPI_OP_MOV,     /* Move */
 536         DPI_OP_BIC,     /* Bit clear */
 537         DPI_OP_MVN      /* Move not */
 538 } arm_dpi_opcode_t;
 539 
 540 const char *arm_dpi_shifts[] = {
 541         "lsl",  /* Logical shift left */
 542         "lsr",  /* Logical shift right */
 543         "asr",  /* Arithmetic shift right */
 544         "ror",  /* Rotate right */
 545         "rrx"   /* Rotate right with extend. This is a special case of ror */
 546 };
 547 
 548 typedef enum arm_dpi_shift_code {
 549         DPI_S_LSL,      /* Logical shift left */
 550         DPI_S_LSR,      /* Logical shift right */
 551         DPI_S_ASR,      /* Arithmetic shift right */
 552         DPI_S_ROR,      /* Rotate right */
 553         DPI_S_RRX,      /* Rotate right with extend. Special case of ror */
 554         DPI_S_NONE      /* No shift code */
 555 } arm_dpi_shift_code_t;
 556 
 557 #define ARM_DPI_SHIFTER_IMM32   0x00
 558 #define ARM_DPI_SHIFTER_SIMM    0x01
 559 #define ARM_DPI_SHIFTER_SREG    0x02
 560 
 561 typedef struct arm_dpi_shifter_imm {
 562         uint8_t dpisi_rot;                      /* Rotation amount */
 563         uint8_t dpisi_imm;                      /* Immediate value */
 564 } arm_dpi_shifter_imm_t;
 565 
 566 typedef struct arm_dpi_shifter_simm {
 567         uint8_t dpiss_imm;                      /* Shift value */
 568         arm_dpi_shift_code_t dpiss_code;        /* Shift type */
 569         arm_reg_t dpiss_targ;                   /* Target register */
 570 } arm_dpi_shifter_simm_t;
 571 
 572 typedef struct arm_dpi_shifter_sreg {
 573         arm_reg_t dpisr_val;                    /* reg with shift value */
 574         arm_dpi_shift_code_t dpisr_code;        /* Shift type */
 575         arm_reg_t dpisr_targ;                   /* Target register */
 576 } arm_dpi_shifter_sreg_t;
 577 
 578 typedef struct arm_dpi_inst {
 579         arm_dpi_opcode_t dpii_op;               /* dpi opcode */
 580         arm_cond_code_t dpii_cond;              /* condition code */
 581         int dpii_sbit;                          /* value of S bit */
 582         arm_reg_t dpii_rn;                      /* first operand */
 583         arm_reg_t dpii_rd;                      /* destination operand */
 584         int dpii_stype;                         /* type of shifter */
 585         union {                                 /* shifter values */
 586                 arm_dpi_shifter_imm_t dpii_im;
 587                 arm_dpi_shifter_simm_t dpii_si;
 588                 arm_dpi_shifter_sreg_t dpii_ri;
 589         } dpii_un;
 590 } arm_dpi_inst_t;
 591 
 592 /*
 593  * This table contains the names of the load store multiple addressing modes.
 594  * The P and U bits are supposed to be combined to index into this. You should
 595  * do this by doing P << 1 | U.
 596  */
 597 static const char *arm_lsm_mode_names[] = {
 598         "da",
 599         "ia",
 600         "db",
 601         "ib"
 602 };
 603 
 604 /*
 605  * The MSR field has a four bit field mask. Each bit correspons to a letter.
 606  * From high to low, f, s, x, c. At least one must be specified, hence 0 is
 607  * NULL. The preferred manual ordering of these is csxf.
 608  */
 609 static const char *arm_cdsp_msr_field_names[] = {
 610         NULL,
 611         "c",    /* 0001 */
 612         "x",    /* 0010 */
 613         "cx",   /* 0011 */
 614         "s",    /* 0100 */
 615         "cs",   /* 0101 */
 616         "sx",   /* 0110 */
 617         "csx",  /* 0111 */
 618         "f",    /* 1000 */
 619         "cf",   /* 1001 */
 620         "xf",   /* 1010 */
 621         "cxf",  /* 1011 */
 622         "sf",   /* 1100 */
 623         "csf",  /* 1101 */
 624         "sxf",  /* 1110 */
 625         "csxf"  /* 1111 */
 626 };
 627 
 628 /*
 629  * Names for specific saturating add and subtraction instructions from the
 630  * extended control and dsp instructino section.
 631  */
 632 static const char *arm_cdsp_sat_opnames[] = {
 633         "add",
 634         "sub",
 635         "dadd",
 636         "dsub"
 637 };
 638 
 639 static const char *arm_padd_p_names[] = {
 640         NULL,   /* 000 */
 641         "s",    /* 001 */
 642         "q",    /* 010 */
 643         "sh",   /* 011 */
 644         NULL,   /* 100 */
 645         "u",    /* 101 */
 646         "uq",   /* 110 */
 647         "uh",   /* 111 */
 648 };
 649 
 650 static const char *arm_padd_i_names[] = {
 651         "add16",        /* 000 */
 652         "addsubx",      /* 001 */
 653         "subaddx",      /* 010 */
 654         "sub16",        /* 011 */
 655         "add8",         /* 100 */
 656         NULL,           /* 101 */
 657         NULL,           /* 110 */
 658         "sub8",         /* 111 */
 659 };
 660 
 661 static const char *arm_extend_rot_names[] = {
 662         "",             /* 0b00, ROR #0 */
 663         ", ror #8",     /* 0b01 */
 664         ", ror #16",    /* 0b10 */
 665         ", ror #24"     /* 0b11 */
 666 };
 667 
 668 /*
 669  * There are sixteen data processing instructions (dpi). They come in a few
 670  * different forms which are based on whether immediate values are used and
 671  * whether or not some special purpose shifting is done. We use this one entry
 672  * point to cover all the different types.
 673  *
 674  * From the ARM arch manual:
 675  *
 676  * <opcode1>{<cond>}{S} <Rd>,<shifter>
 677  * <opcode1> := MOV | MVN
 678  * <opcode2>{<cond>} <Rn>,<shifter>
 679  * <opcode2> := CMP, CMN, TST, TEQ
 680  * <opcode3>{<cond>{S} <Rd>,<Rn>, <shifter>
 681  * <opcode3> := ADD | SUB | RSB | ADC | SBC | RSC | AND | BIC | EOR | ORR
 682  *
 683  * 31 - 28|27 26 |25 | 24-21  |20 | 19-16 | 15-12 | 11 - 0
 684  * [ cond | 0  0 | I | opcode | S | Rn    | Rd    | shifter ]
 685  *
 686  * I bit: Determines whether shifter_operand is immediate or register based
 687  * S bit: Determines whether or not the insn updates condition codes
 688  * Rn:    First source operand register
 689  * Rd:    Destination register
 690  * shifter: Specifies the second operand
 691  *
 692  * There are three primary encodings:
 693  *
 694  * 32-bit immediate
 695  * 31 - 28|27 26|25 |24-21 |20|19-16| 15-12|11 - 8    |7 - 0
 696  * [ cond | 0  0| 1 |opcode| S|Rn   | Rd   |rotate_imm|immed_8 ]
 697  *
 698  * Immediate shifts
 699  * 31 - 28|27 26|25 |24-21 |20|19-16|15-12|11 - 7   |6 5  |4|3-0
 700  * [ cond | 0  0| 0 |opcode| S|Rn   |Rd   |shift_imm|shift|0|Rm ]
 701  *
 702  * Register shifts
 703  * 31 - 28|27 26|25 |24-21 |20|19-16|15-12|11 - 8|7|6 5  |4|3-0
 704  * [ cond | 0  0| 0 |opcode| S|Rn   |Rd   |Rs    |0|shift|1|Rm ]
 705  *
 706  * There are four different kinds of shifts that work with both immediate and
 707  * register shifts:
 708  *   o Logical shift left  0b00 (LSL)
 709  *   o Logical shift right 0b01 (LSR)
 710  *   o Arithmetic shift right 0b10 (ASR)
 711  *   o Rotate right 0b11 (ROR)
 712  * There is one special shift which only works with immediate shift format:
 713  *   o If shift_imm = 0 and shift = 0b11, then it is a rotate right with extend
 714  *   (RRX)
 715  *
 716  * Finally there is one special indication for no shift. An immediate shift
 717  * whose shift_imm = shift = 0. This is a shortcut to a direct value from the
 718  * register.
 719  *
 720  * While processing this, we first build up all the information into the
 721  * arm_dpi_inst_t and then from there we go and print out the format based on
 722  * the opcode and shifter. As per the rough grammar above we have to print
 723  * different sets of instructions in different ways.
 724  */
 725 static int
 726 arm_dis_dpi(uint32_t in, arm_cond_code_t cond, char *buf, size_t buflen)
 727 {
 728         arm_dpi_inst_t dpi_inst;
 729         int ibit, bit4;
 730         size_t len;
 731 
 732         dpi_inst.dpii_op = (in & ARM_DPI_OPCODE_MASK) >> ARM_DPI_OPCODE_SHIFT;
 733         dpi_inst.dpii_cond = cond;
 734         dpi_inst.dpii_rn = (in & ARM_DPI_RN_MASK) >> ARM_DPI_RN_SHIFT;
 735         dpi_inst.dpii_rd = (in & ARM_DPI_RD_MASK) >> ARM_DPI_RD_SHIFT;
 736         dpi_inst.dpii_sbit = in & ARM_DPI_SBIT_MASK;
 737 
 738         ibit = in & ARM_DPI_IBIT_MASK;
 739         bit4 = in & ARM_DPI_BIT4_MASK;
 740 
 741         if (ibit) {
 742                 /* 32-bit immediate */
 743                 dpi_inst.dpii_stype = ARM_DPI_SHIFTER_IMM32;
 744                 dpi_inst.dpii_un.dpii_im.dpisi_rot = (in &
 745                     ARM_DPI_IMM_ROT_MASK) >> ARM_DPI_IMM_ROT_SHIFT;
 746                 dpi_inst.dpii_un.dpii_im.dpisi_imm = in & ARM_DPI_IMM_VAL_MASK;
 747         } else if (bit4) {
 748                 /* Register shift */
 749                 dpi_inst.dpii_stype = ARM_DPI_SHIFTER_SREG;
 750                 dpi_inst.dpii_un.dpii_ri.dpisr_val = (in &
 751                     ARM_DPI_REGS_RS_MASK) >> ARM_DPI_REGS_RS_SHIFT;
 752                 dpi_inst.dpii_un.dpii_ri.dpisr_targ = in &
 753                     ARM_DPI_REGS_RM_MASK;
 754                 dpi_inst.dpii_un.dpii_ri.dpisr_code = in &
 755                     ARM_DPI_REGS_SHIFT_MASK >> ARM_DPI_REGS_SHIFT_SHIFT;
 756         } else {
 757                 /* Immediate shift */
 758                 dpi_inst.dpii_stype = ARM_DPI_SHIFTER_SIMM;
 759                 dpi_inst.dpii_un.dpii_si.dpiss_imm = (in &
 760                     ARM_DPI_IMS_SHIMM_MASK) >> ARM_DPI_IMS_SHIMM_SHIFT;
 761                 dpi_inst.dpii_un.dpii_si.dpiss_code = (in &
 762                     ARM_DPI_IMS_SHIFT_MASK) >> ARM_DPI_IMS_SHIFT_SHIFT;
 763                 dpi_inst.dpii_un.dpii_si.dpiss_targ = in & ARM_DPI_IMS_RM_MASK;
 764                 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_ROR &&
 765                     dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
 766                         dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_RRX;
 767 
 768                 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_LSL &&
 769                     dpi_inst.dpii_un.dpii_si.dpiss_imm == 0)
 770                         dpi_inst.dpii_un.dpii_si.dpiss_code = DPI_S_NONE;
 771         }
 772 
 773         /*
 774          * Print everything before the shifter based on the instruction
 775          */
 776         switch (dpi_inst.dpii_op) {
 777         case DPI_OP_MOV:
 778         case DPI_OP_MVN:
 779                 len = snprintf(buf, buflen, "%s%s%s %s",
 780                     arm_dpi_opnames[dpi_inst.dpii_op],
 781                     arm_cond_names[dpi_inst.dpii_cond],
 782                     dpi_inst.dpii_sbit != 0 ? "s" : "",
 783                     arm_reg_names[dpi_inst.dpii_rd]);
 784                 break;
 785         case DPI_OP_CMP:
 786         case DPI_OP_CMN:
 787         case DPI_OP_TST:
 788         case DPI_OP_TEQ:
 789                 len = snprintf(buf, buflen, "%s%s %s",
 790                     arm_dpi_opnames[dpi_inst.dpii_op],
 791                     arm_cond_names[dpi_inst.dpii_cond],
 792                     arm_reg_names[dpi_inst.dpii_rn]);
 793                 break;
 794         default:
 795                 len = snprintf(buf, buflen,
 796                     "%s%s%s %s, %s", arm_dpi_opnames[dpi_inst.dpii_op],
 797                     arm_cond_names[dpi_inst.dpii_cond],
 798                     dpi_inst.dpii_sbit != 0 ? "s" : "",
 799                     arm_reg_names[dpi_inst.dpii_rd],
 800                     arm_reg_names[dpi_inst.dpii_rn]);
 801                 break;
 802         }
 803 
 804         if (len >= buflen)
 805                 return (-1);
 806         buflen -= len;
 807         buf += len;
 808 
 809         /*
 810          * Print the shifter as appropriate
 811          */
 812         switch (dpi_inst.dpii_stype) {
 813         case ARM_DPI_SHIFTER_IMM32: {
 814                 uint32_t rawimm, imm;
 815                 int rawrot, rot;
 816 
 817                 rawimm = dpi_inst.dpii_un.dpii_im.dpisi_imm;
 818                 rawrot = dpi_inst.dpii_un.dpii_im.dpisi_rot;
 819 
 820                 rot = rawrot * 2;
 821                 imm = (rawimm << (32 - rot)) | (rawimm >> rot);
 822 
 823                 len = snprintf(buf, buflen, ", #%u, %d ; 0x%08x", rawimm,
 824                     rawrot, imm);
 825                 break;
 826         }
 827         case ARM_DPI_SHIFTER_SIMM:
 828                 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_NONE) {
 829                         len = snprintf(buf, buflen, ", %s",
 830                             arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
 831                         break;
 832                 }
 833                 if (dpi_inst.dpii_un.dpii_si.dpiss_code == DPI_S_RRX) {
 834                         len = snprintf(buf, buflen, ", %s rrx",
 835                             arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ]);
 836                         break;
 837                 }
 838                 len = snprintf(buf, buflen, ", %s, %s #%d",
 839                     arm_reg_names[dpi_inst.dpii_un.dpii_si.dpiss_targ],
 840                     arm_dpi_shifts[dpi_inst.dpii_un.dpii_si.dpiss_code],
 841                     dpi_inst.dpii_un.dpii_si.dpiss_imm);
 842                 break;
 843         case ARM_DPI_SHIFTER_SREG:
 844                 len = snprintf(buf, buflen, ", %s, %s %s",
 845                     arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_targ],
 846                     arm_dpi_shifts[dpi_inst.dpii_un.dpii_ri.dpisr_code],
 847                     arm_reg_names[dpi_inst.dpii_un.dpii_ri.dpisr_val]);
 848                 break;
 849         }
 850 
 851         return (len < buflen ? 0 : -1);
 852 }
 853 
 854 /*
 855  * This handles the byte and word size loads and stores. It does not handle the
 856  * multi-register loads or the 'extra' ones. The instruction has the generic
 857  * form off:
 858  *
 859  * 31 - 28|27 26 |25|24|23|22|21|20|19-16|15-12|11 - 0
 860  * [ cond | 0  0 |I |P |U |B |W |L | Rn | Rd   |mode_specific]
 861  *
 862  * Here the bits mean the following:
 863  *
 864  * Rn: The base register used by the addressing mode
 865  * Rd: The register to load to or store from
 866  * L bit: If L==1 then a load, else store
 867  * B bit: If B==1 then work on a byte, else a 32-bit word
 868  *
 869  * The remaining pieces determine the mode we are operating in:
 870  * I bit: If 0 use immediate offsets, otherwise if 1 used register based offsets
 871  * P bit: If 0 use post-indexed addressing. If 1, indexing mode is either offset
 872  *        addessing or pre-indexed addressing based on the W bit.
 873  * U bit: If 1, offset is added to base, if 0 offset is subtracted from base
 874  * W bit: This bits interpretation varies based on the P bit. If P is zero then
 875  *        W indicates whether a normal memory access is performed or if a read
 876  *        from user memory is performed (W = 1).
 877  *        If P is 1 then then when W = 0 the base register is not updated and
 878  *        when W = 1 the calculated address is written back to the base
 879  *        register.
 880  *
 881  * Based on these combinations there are a total of nine different operating
 882  * modes, though not every LDR and STR variant can reach them all.
 883  */
 884 static int
 885 arm_dis_ldstr(uint32_t in, char *buf, size_t buflen)
 886 {
 887         arm_cond_code_t cc;
 888         arm_reg_t rd, rn, rm;
 889         int ibit, pbit, ubit, bbit, wbit, lbit;
 890         arm_dpi_shift_code_t sc;
 891         uint8_t simm;
 892         size_t len;
 893 
 894         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
 895         ibit = in & ARM_LS_IBIT_MASK;
 896         pbit = in & ARM_LS_PBIT_MASK;
 897         ubit = in & ARM_LS_UBIT_MASK;
 898         bbit = in & ARM_LS_BBIT_MASK;
 899         wbit = in & ARM_LS_WBIT_MASK;
 900         lbit = in & ARM_LS_LBIT_MASK;
 901         rd = (in & ARM_LS_RD_MASK) >> ARM_LS_RD_SHIFT;
 902         rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
 903 
 904         len = snprintf(buf, buflen, "%s%s%s%s %s, ", lbit != 0 ? "ldr" : "str",
 905             arm_cond_names[cc], bbit != 0 ? "b" : "",
 906             (pbit == 0 && wbit != 0) ? "t" : "",
 907             arm_reg_names[rd]);
 908         if (len >= buflen)
 909                 return (-1);
 910 
 911         /* Figure out the specifics of the encoding for the rest */
 912         if (ibit == 0 && pbit != 0) {
 913                 /*
 914                  * This is the immediate offset mode (A5.2.2). That means that
 915                  * we have something of the form [ <Rn>, #+/-<offset_12> ]. All
 916                  * of the mode specific bits contribute to offset_12. We also
 917                  * handle the pre-indexed version (A5.2.5) which depends on the
 918                  * wbit being set.
 919                  */
 920                 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
 921                     arm_reg_names[rn], ubit != 0 ? "" : "-",
 922                     in & ARM_LS_IMM_MASK, wbit != 0 ? "!" : "");
 923         } else if (ibit != 0 && pbit != 0) {
 924                 /*
 925                  * This handles A5.2.2, A5.2.3, A5.2.6, and A5.2.7. We can have
 926                  * one of two options. If the non-rm bits (11-4) are all zeros
 927                  * then we have a special case of a register offset is just
 928                  * being added. Otherwise we have a scaled register offset where
 929                  * the shift code matters.
 930                  */
 931                 rm = in & ARM_LS_REG_RM_MASK;
 932                 len += snprintf(buf + len, buflen - len, "[%s, %s%s",
 933                     arm_reg_names[rn], ubit != 0 ? "" : "-",
 934                     arm_reg_names[rm]);
 935                 if (len >= buflen)
 936                         return (-1);
 937                 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
 938                         simm = (in & ARM_LS_SCR_SIMM_MASK) >>
 939                             ARM_LS_SCR_SIMM_SHIFT;
 940                         sc = (in & ARM_LS_SCR_SCODE_MASK) >>
 941                             ARM_LS_SCR_SCODE_SHIFT;
 942 
 943                         if (simm == 0 && sc == DPI_S_ROR)
 944                                 sc = DPI_S_RRX;
 945 
 946                         len += snprintf(buf + len, buflen - len, "%s",
 947                             arm_dpi_shifts[sc]);
 948                         if (len >= buflen)
 949                                 return (-1);
 950                         if (sc != DPI_S_RRX) {
 951                                 len += snprintf(buf + len, buflen - len, " #%d",
 952                                     simm);
 953                                 if (len >= buflen)
 954                                         return (-1);
 955                         }
 956                 }
 957                 len += snprintf(buf + len, buflen - len, "]%s",
 958                     wbit != 0 ? "!" : "");
 959         } else if (ibit == 0 && pbit == 0 && wbit == 0) {
 960                 /* A5.2.8 immediate post-indexed */
 961                 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
 962                     arm_reg_names[rn], ubit != 0 ? "" : "-",
 963                     in & ARM_LS_IMM_MASK);
 964         } else if (ibit != 0 && pbit == 0 && wbit == 0) {
 965                 /* A5.2.9 and A5.2.10 */
 966                 rm = in & ARM_LS_REG_RM_MASK;
 967                 len += snprintf(buf + len, buflen - len, "[%s], %s%s",
 968                     arm_reg_names[rn], ubit != 0 ? "" : "-",
 969                     arm_reg_names[rm]);
 970                 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
 971                         simm = (in & ARM_LS_SCR_SIMM_MASK) >>
 972                             ARM_LS_SCR_SIMM_SHIFT;
 973                         sc = (in & ARM_LS_SCR_SCODE_MASK) >>
 974                             ARM_LS_SCR_SCODE_SHIFT;
 975 
 976                         if (simm == 0 && sc == DPI_S_ROR)
 977                                 sc = DPI_S_RRX;
 978 
 979                         len += snprintf(buf + len, buflen - len, "%s",
 980                             arm_dpi_shifts[sc]);
 981                         if (len >= buflen)
 982                                 return (-1);
 983                         if (sc != DPI_S_RRX)
 984                                 len += snprintf(buf + len, buflen - len,
 985                                     " #%d", simm);
 986                 }
 987         }
 988 
 989         return (len < buflen ? 0 : -1);
 990 }
 991 
 992 static void
 993 print_range(char **bufp, size_t *buflenp, uint16_t regs, uint16_t precede)
 994 {
 995         char *buf = *bufp;
 996         size_t buflen = *buflenp;
 997         boolean_t cont = B_FALSE;
 998         int minreg = -1;
 999         int i;
1000 
1001         *buf = '\0';
1002 
1003         if (precede && regs)
1004                 strlcat(buf, ", ", buflen);
1005 
1006         for (i = 0; i < 16; i++) {
1007                 boolean_t present = (regs & (1 << i)) != 0;
1008                 boolean_t lastreg = (regs & (2 << i)) == 0;
1009 
1010                 if (!present)
1011                         continue;
1012 
1013                 if (minreg == -1) {
1014                         if (cont)
1015                                 strlcat(buf, ", ", buflen);
1016 
1017                         strlcat(buf, arm_reg_names[i], buflen);
1018 
1019                         if (!lastreg)
1020                                 minreg = i;
1021                 } else {
1022                         if (lastreg) {
1023                                 strlcat(buf, "-", buflen);
1024                                 strlcat(buf, arm_reg_names[i], buflen);
1025                                 minreg = -1;
1026                         }
1027                 }
1028 
1029                 cont = B_TRUE;
1030         }
1031 
1032         *bufp += strlen(buf);
1033         *buflenp -= strlen(buf);
1034 }
1035 
1036 static size_t
1037 print_reg_list(char *buf, size_t buflen, uint16_t regs)
1038 {
1039         char *save = buf;
1040 
1041         print_range(&buf, &buflen, regs & 0x01ff, 0);
1042         print_range(&buf, &buflen, regs & 0x0200, regs & 0x01ff); /* fp */
1043         print_range(&buf, &buflen, regs & 0x0c00, regs & 0x03ff);
1044         print_range(&buf, &buflen, regs & 0x1000, regs & 0x0fff); /* ip */
1045         print_range(&buf, &buflen, regs & 0x2000, regs & 0x1fff); /* sp */
1046         print_range(&buf, &buflen, regs & 0x4000, regs & 0x3fff); /* lr */
1047         print_range(&buf, &buflen, regs & 0x8000, regs & 0x7fff); /* pc */
1048 
1049         return (strlen(save));
1050 }
1051 
1052 /*
1053  * This handles load and store multiple instructions. The general format is as
1054  * follows:
1055  *
1056  * 31 - 28|27 26 25|24|23|22|21|20|19-16|15-0
1057  * [ cond | 1  0 0 |P |U |S |W |L | Rn | register set
1058  *
1059  * The register set has one bit per register. If a bit is set it indicates that
1060  * register and if it is not set then it indicates that the register is not
1061  * included in this.
1062  *
1063  * S bit: If the instruction is a LDM and we load the PC, the S == 1 tells us to
1064  * load the CPSR from SPSR after the other regs are loaded. If the instruction
1065  * is a STM or LDM without touching the PC it indicates that if we are
1066  * privileged we should send the banked registers.
1067  *
1068  * L bit: Where this is a load or store. Load is active high.
1069  *
1070  * P bit: If P == 0 then Rn is included in the memory region transfers and its
1071  * location is dependent on the U bit. It is at the top (U == 0) or bottom (U ==
1072  * 1). If P == 1 then it is excluded and lies one word beyond the top (U == 0)
1073  * or bottom based on the U bit.
1074  *
1075  * U bit: If U == 1 then the transfer is made upwards and if U == 0 then the
1076  * transfer is made downwards.
1077  *
1078  * W bit: If set then we incremet the base register after the transfer. It is
1079  * modified by 4 times the number of registers in the list. If the U bit is
1080  * positive then that value is added to Rn otherwise it is subtracted.
1081  *
1082  * The overal layout for this is
1083  * (LDM|STM){<cond>}<addressing mode> Rn{!}, <registers>{^}. Here the ! is based
1084  * on having the W bit set. The ^ bit depends on whether S is set or not.
1085  *
1086  * There are four normal addressing modes: IA, IB, DA, DB. There are also
1087  * corresponding stack addressing modes that exist. However we have no way of
1088  * knowing which are the ones being used, therefore we are going to default to
1089  * the non-stack versions which are listed as the primary.
1090  *
1091  * Finally the last useful bit is how the registers list is specified. It is a
1092  * comma separated list inside of { }. However, a user may separate a contiguous
1093  * range by the use of a -, eg. R0 - R4. However, it is impossible for us to map
1094  * back directly to what the user did. So for now, we punt on second down and
1095  * instead just list each indidvidual register rather than attempt a joining
1096  * routine.
1097  */
1098 static int
1099 arm_dis_ldstr_multi(uint32_t in, char *buf, size_t buflen)
1100 {
1101         int sbit, wbit, lbit;
1102         uint16_t regs, addr_mode;
1103         arm_reg_t rn;
1104         arm_cond_code_t cc;
1105         size_t len;
1106 
1107         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1108         sbit = in & ARM_LSM_SBIT_MASK;
1109         wbit = in & ARM_LSM_WBIT_MASK;
1110         lbit = in & ARM_LSM_LBIT_MASK;
1111         rn = (in & ARM_LSM_RN_MASK) >> ARM_LSM_RN_SHIFT;
1112         regs = in & ARM_LSM_RLIST_MASK;
1113         addr_mode = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1114 
1115         if ((lbit == 0 && addr_mode == 2 && rn == ARM_REG_R13 && wbit != 0) ||
1116             (lbit != 0 && addr_mode == 1 && rn == ARM_REG_R13 && wbit != 0))
1117                 len = snprintf(buf, buflen, "%s%s { ",
1118                     lbit != 0 ? "pop" : "push",
1119                     arm_cond_names[cc]);
1120         else
1121                 len = snprintf(buf, buflen, "%s%s%s %s%s, { ",
1122                     lbit != 0 ? "ldm" : "stm",
1123                     arm_cond_names[cc],
1124                     arm_lsm_mode_names[addr_mode],
1125                     arm_reg_names[rn],
1126                     wbit != 0 ? "!" : "");
1127 
1128         len += print_reg_list(buf + len, buflen - len, regs);
1129 
1130         len += snprintf(buf + len, buflen - len, " }%s", sbit != 0 ? "^" : "");
1131         return (len >= buflen ? -1 : 0);
1132 }
1133 
1134 /*
1135  * Here we need to handle miscellaneous loads and stores. This is used to load
1136  * and store signed and unsigned half words. To load a signed byte. And to load
1137  * and store double words. There is no specific store routines for signed bytes
1138  * and halfwords as they are supposed to use the SRB and STRH. There are two
1139  * primary encodings this time. The general case looks like:
1140  *
1141  * 31 - 28|27 - 25|24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1142  * [ cond |   0   |P |U |I |W |L | Rn | Rd   |amode|1|S|H|1|amode ]
1143  *
1144  * The I, P, U, and W bits specify the addressing mode.
1145  * The L, S, and H bits describe the type and size.
1146  * Rn: The base register used by the addressing mode
1147  * Rd: The register to load to or store from
1148  *
1149  * The other bits specifically mean:
1150  * I bit: If set to one the address specific pieces are immediate. Otherwise
1151  * they aren't.
1152  * P bit: If P is 0 used post-indexed addressing. If P is 1 its behavior is
1153  * based on the value of W.
1154  * U bit: If U is one the offset is added to the base otherwise subtracted
1155  * W bit: When P is one a value of W == 1 says that the resulting memory address
1156  * should be written back to the base register. The base register isn't touched
1157  * when W is zero.
1158  *
1159  * The L, S, and H bits combine in the following table:
1160  *
1161  *  L | S | H | Meaning
1162  *  -------------------
1163  *  0 | 0 | 1 | store halfword
1164  *  0 | 1 | 0 | load doubleword
1165  *  0 | 1 | 1 | store doubleword
1166  *  1 | 0 | 1 | load unsigned half word
1167  *  1 | 1 | 0 | load signed byte
1168  *  1 | 1 | 1 | load signed halfword
1169  *
1170  * The final format of this is:
1171  * LDR|STR{<cond>}H|SH|SB|D <rd>, address_mode
1172  */
1173 static int
1174 arm_dis_els(uint32_t in, char *buf, size_t buflen)
1175 {
1176         arm_cond_code_t cc;
1177         arm_reg_t rn, rd;
1178         const char *iname, *suffix;
1179         int lbit, sbit, hbit, pbit, ubit, ibit, wbit;
1180         uint8_t imm;
1181         size_t len;
1182 
1183         lbit = in & ARM_ELS_LBIT_MASK;
1184         sbit = in & ARM_ELS_SBIT_MASK;
1185         hbit = in & ARM_ELS_SBIT_MASK;
1186 
1187         if (lbit || (sbit && hbit == 0))
1188                 iname = "ldr";
1189         else
1190                 iname = "str";
1191 
1192         if (sbit == 0 && hbit)
1193                 suffix = "h";
1194         else if (lbit == 0)
1195                 suffix = "d";
1196         else if (sbit && hbit == 0)
1197                 suffix = "sb";
1198         else if (sbit && hbit)
1199                 suffix = "sh";
1200 
1201         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1202         rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1203         rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1204 
1205         len = snprintf(buf, buflen, "%s%s%s %s, ", iname, arm_cond_names[cc],
1206             suffix, arm_reg_names[rd]);
1207         if (len >= buflen)
1208                 return (-1);
1209 
1210         pbit = in & ARM_ELS_PBIT_MASK;
1211         ubit = in & ARM_ELS_UBIT_MASK;
1212         ibit = in & ARM_ELS_IBIT_MASK;
1213         wbit = in & ARM_ELS_WBIT_MASK;
1214 
1215         if (pbit && ibit) {
1216                 /* Handle A5.3.2 and A5.3.4 immediate offset and pre-indexed */
1217                 /* Bits 11-8 form the upper 4 bits of imm */
1218                 imm = (in & ARM_ELS_UP_AM_MASK) >> (ARM_ELS_UP_AM_SHIFT - 4);
1219                 imm |= in & ARM_ELS_LOW_AM_MASK;
1220                 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
1221                     arm_reg_names[rn],
1222                     ubit != 0 ? "" : "-", imm,
1223                     wbit != 0 ? "!" : "");
1224         } else if (pbit && ibit == 0) {
1225                 /* Handle A5.3.3 and A5.3.5 register offset and pre-indexed */
1226                 len += snprintf(buf + len, buflen - len, "[%s %s%s]%s",
1227                     arm_reg_names[rn],
1228                     ubit != 0 ? "" : "-",
1229                     arm_reg_names[in & ARM_ELS_LOW_AM_MASK],
1230                     wbit != 0 ? "!" : "");
1231         } else if (pbit == 0 && ibit) {
1232                 /* A5.3.6 Immediate post-indexed */
1233                 /* Bits 11-8 form the upper 4 bits of imm */
1234                 imm = (in & ARM_ELS_UP_AM_MASK) >> (ARM_ELS_UP_AM_SHIFT - 4);
1235                 imm |= in & ARM_ELS_LOW_AM_MASK;
1236                 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
1237                     arm_reg_names[rn], ubit != 0 ? "" : "-", imm);
1238         } else if (pbit == 0 && ibit == 0) {
1239                 /* Handle A 5.3.7 Register post-indexed */
1240                 len += snprintf(buf + len, buflen - len, "[%s], %s%s",
1241                     arm_reg_names[rn], ubit != 0 ? "" : "-",
1242                     arm_reg_names[in & ARM_ELS_LOW_AM_MASK]);
1243         }
1244 
1245         return (len >= buflen ? -1 : 0);
1246 }
1247 
1248 /*
1249  * Handle SWP and SWPB out of the extra loads/stores extensions.
1250  */
1251 static int
1252 arm_dis_swap(uint32_t in, char *buf, size_t buflen)
1253 {
1254         arm_cond_code_t cc;
1255         arm_reg_t rn, rd, rm;
1256 
1257         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1258         rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1259         rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1260         rm = in & ARM_ELS_RN_MASK;
1261 
1262         if (snprintf(buf, buflen, "swp%s%s %s, %s, [%s]",
1263             arm_cond_names[cc],
1264             (in & ARM_ELS_SWAP_BYTE_MASK) ? "b" : "",
1265             arm_reg_names[rd], arm_reg_names[rm], arm_reg_names[rn]) >=
1266             buflen)
1267                 return (-1);
1268 
1269         return (0);
1270 }
1271 
1272 /*
1273  * Handle LDREX and STREX out of the extra loads/stores extensions.
1274  */
1275 static int
1276 arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1277 {
1278         arm_cond_code_t cc;
1279         arm_reg_t rn, rd, rm;
1280         int lbit;
1281         size_t len;
1282 
1283         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1284         rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1285         rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1286         rm = in & ARM_ELS_RN_MASK;
1287         lbit = in & ARM_ELS_LBIT_MASK;
1288 
1289         len = snprintf(buf, buflen, "%s%sex %s, ",
1290             lbit != 0 ? "ldr" : "str",
1291             arm_cond_names[cc], arm_reg_names[rd]);
1292         if (len >= buflen)
1293                 return (-1);
1294 
1295         if (lbit)
1296                 len += snprintf(buf + len, buflen - len, "[%s]",
1297                     arm_reg_names[rn]);
1298         else
1299                 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1300                     arm_reg_names[rm], arm_reg_names[rn]);
1301         return (len >= buflen ? -1 : 0);
1302 }
1303 
1304 /*
1305  * This is designed to handle the multiplication instruction extension space.
1306  * Note that this doesn't actually cover all of the multiplication instructions
1307  * available in ARM, but all of the ones that are in this space. This includes
1308  * the following instructions:
1309  *
1310  *
1311  * There are three basic encoding formats:
1312  *
1313  * Multipy (acc):
1314  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1315  * [ cond |   0   |0 |0 | A |S |Rn  | Rd   |Rs   |1|0|0|1|Rm ]
1316  *
1317  * Unsigned multipy acc acc long
1318  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1319  * [ cond |   0   |0 |1 |0 |0 |RdHi |RdLo  |Rs   |1|0|0|1|Rm ]
1320  *
1321  * Multiply (acc) long:
1322  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1323  * [ cond |   0   |1 |Un|A |S |RdHi| RdLo |Rs   |1|0|0|1|Rm ]
1324  *
1325  * A bit: Accumulate
1326  * Un bit: Unsigned is active low, signed is active high
1327  * S bit: Indicates whethere the status register should be updated.
1328  *
1329  * MLA(S) and MUL(S) make up the first type of instructions.
1330  * UMAAL makes up the second group.
1331  * (U|S)MULL(S), (U|S)MLAL(S), Make up the third.
1332  */
1333 static int
1334 arm_dis_extmul(uint32_t in, char *buf, size_t buflen)
1335 {
1336         arm_cond_code_t cc;
1337         arm_reg_t rd, rn, rs, rm;
1338         size_t len;
1339 
1340         /*
1341          * RdHi is equal to rd here. RdLo is equal to Rn here.
1342          */
1343         rd = (in & ARM_EMULT_RD_MASK) >> ARM_EMULT_RD_SHIFT;
1344         rn = (in & ARM_EMULT_RN_MASK) >> ARM_EMULT_RN_SHIFT;
1345         rs = (in & ARM_EMULT_RS_MASK) >> ARM_EMULT_RS_SHIFT;
1346         rm = in & ARM_EMULT_RM_MASK;
1347 
1348         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1349 
1350         if ((in & ARM_EMULT_MA_MASK) == 0) {
1351                 if (in & ARM_EMULT_ABIT_MASK) {
1352                         len = snprintf(buf, buflen, "mla%s%s %s, %s, %s, %s",
1353                             arm_cond_names[cc],
1354                             (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1355                             arm_reg_names[rd], arm_reg_names[rm],
1356                             arm_reg_names[rs], arm_reg_names[rs]);
1357                 } else {
1358                         len = snprintf(buf, buflen, "mul%s%s %s, %s, %s",
1359                             arm_cond_names[cc],
1360                             (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1361                             arm_reg_names[rd], arm_reg_names[rm],
1362                             arm_reg_names[rs]);
1363 
1364                 }
1365         } else if ((in & ARM_EMULT_UMA_MASK) == ARM_EMULT_UMA_TARG) {
1366                 len = snprintf(buf, buflen, "umaal%s %s, %s, %s, %s",
1367                     arm_cond_names[cc], arm_reg_names[rn], arm_reg_names[rd],
1368                     arm_reg_names[rm], arm_reg_names[rs]);
1369         } else if ((in & ARM_EMULT_MAL_MASK) == ARM_EMULT_MAL_TARG) {
1370                 len = snprintf(buf, buflen, "%s%s%s%s %s, %s, %s, %s",
1371                     (in & ARM_EMULT_UNBIT_MASK) ? "s" : "u",
1372                     (in & ARM_EMULT_ABIT_MASK) ? "mlal" : "mull",
1373                     arm_cond_names[cc],
1374                     (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1375                     arm_reg_names[rn], arm_reg_names[rd], arm_reg_names[rm],
1376                     arm_reg_names[rs]);
1377         } else {
1378                 /* Not a supported instruction in this space */
1379                 return (-1);
1380         }
1381         return (len >= buflen ? -1 : 0);
1382 }
1383 
1384 /*
1385  * Here we handle the three different cases of moving to and from the various
1386  * status registers in both register mode and in immediate mode.
1387  */
1388 static int
1389 arm_dis_status_regs(uint32_t in, char *buf, size_t buflen)
1390 {
1391         arm_cond_code_t cc;
1392         arm_reg_t rd, rm;
1393         uint8_t field;
1394         int imm;
1395         size_t len;
1396 
1397         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1398 
1399         if ((in & ARM_CDSP_MRS_MASK) == ARM_CDSP_MRS_TARG) {
1400                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1401                 if (snprintf(buf, buflen, "mrs%s %s, %s", arm_cond_names[cc],
1402                     arm_reg_names[rd],
1403                     (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr") >=
1404                     buflen)
1405                         return (-1);
1406                 return (0);
1407         }
1408 
1409         field = (in & ARM_CDSP_MSR_F_MASK) >> ARM_CDSP_MSR_F_SHIFT;
1410         len = snprintf(buf, buflen, "msr%s %s_%s, ", arm_cond_names[cc],
1411             (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr",
1412             arm_cdsp_msr_field_names[field]);
1413         if (len >= buflen)
1414                 return (-1);
1415 
1416         if (in & ARM_CDSP_MSR_ISIMM_MASK) {
1417                 imm = in & ARM_CDSP_MSR_IMM_MASK;
1418                 imm <<= (in & ARM_CDSP_MSR_RI_MASK) >> ARM_CDSP_MSR_RI_SHIFT;
1419                 len += snprintf(buf + len, buflen - len, "#%d", imm);
1420         } else {
1421                 rm = in & ARM_CDSP_RM_MASK;
1422                 len += snprintf(buf + len, buflen - len, "%s",
1423                     arm_reg_names[rm]);
1424         }
1425 
1426         return (len >= buflen ? -1 : 0);
1427 }
1428 
1429 /*
1430  * Here we need to handle the Control And DSP instruction extension space. This
1431  * consists of several different instructions. Unlike other extension spaces
1432  * there isn't as much tha tis similar here as there is stuff that is different.
1433  * Oh well, that's a part of life. Instead we do a little bit of additional
1434  * parsing here.
1435  *
1436  * The first group that we separate out are the instructions that interact with
1437  * the status registers. Those are handled in their own function.
1438  */
1439 static int
1440 arm_dis_cdsp_ext(uint32_t in, char *buf, size_t buflen)
1441 {
1442         uint16_t imm, op;
1443         arm_cond_code_t cc;
1444         arm_reg_t rd, rm, rn, rs;
1445         size_t len;
1446 
1447         if ((in & ARM_CDSP_STATUS_MASK) == ARM_CDSP_STATUS_TARG)
1448                 return (arm_dis_status_regs(in, buf, buflen));
1449 
1450         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1451 
1452         /*
1453          * This gets the Branch/exchange as well as the Branch and link/exchange
1454          * pieces. These generally also transform the instruction set into
1455          * something we can't actually disassemble. Here the lower mask and
1456          * target is the opposite. eg. the target bits are not what we want.
1457          */
1458         if ((in & ARM_CDSP_BEX_UP_MASK) == ARM_CDSP_BEX_UP_TARG &&
1459             (in & ARM_CDSP_BEX_LOW_MASK) != ARM_CDSP_BEX_NLOW_TARG) {
1460                 rm = in & ARM_CDSP_RM_MASK;
1461                 imm = (in & ARM_CDSP_BEX_TYPE_MASK) >> ARM_CDSP_BEX_TYPE_SHIFT;
1462                 if (snprintf(buf, buflen, "b%s%s %s",
1463                     imm == ARM_CDSP_BEX_TYPE_X ? "x" :
1464                     imm == ARM_CDSP_BEX_TYPE_J ? "xj" : "lx",
1465                     arm_cond_names[cc], arm_reg_names[rm]) >= buflen)
1466                         return (-1);
1467                 return (0);
1468         }
1469 
1470         /* Count leading zeros */
1471         if ((in & ARM_CDSP_CLZ_MASK) == ARM_CDSP_CLZ_TARG) {
1472                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1473                 rm = in & ARM_CDSP_RM_MASK;
1474                 if (snprintf(buf, buflen, "clz%s %s, %s", arm_cond_names[cc],
1475                     arm_reg_names[rd], arm_reg_names[rm]) >= buflen)
1476                         return (-1);
1477                 return (0);
1478         }
1479 
1480         if ((in & ARM_CDSP_SAT_MASK) == ARM_CDSP_SAT_TARG) {
1481                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1482                 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1483                 rm = in & ARM_CDSP_RM_MASK;
1484                 imm = (in & ARM_CDSP_SAT_OP_MASK) >> ARM_CDSP_SAT_OP_SHIFT;
1485                 if (snprintf(buf, buflen, "q%s%s %s, %s, %s",
1486                     arm_cdsp_sat_opnames[imm], arm_cond_names[cc],
1487                     arm_reg_names[rd], arm_reg_names[rm],
1488                     arm_reg_names[rn]) >= buflen)
1489                         return (-1);
1490                 return (0);
1491         }
1492 
1493         /*
1494          * Breakpoint instructions are a bit different. While they are in the
1495          * conditional instruction namespace, they actually aren't defined to
1496          * take a condition. That's just how it rolls. The breakpoint is a
1497          * 16-bit value. The upper 12 bits are stored together and the lower
1498          * four together.
1499          */
1500         if ((in & ARM_CDSP_BKPT_MASK) == ARM_CDSP_BKPT_TARG) {
1501                 if (cc != ARM_COND_NACC)
1502                         return (-1);
1503                 imm = (in & ARM_CDSP_BKPT_UIMM_MASK) >>
1504                     ARM_CDSP_BKPT_UIMM_SHIFT;
1505                 imm <<= 4;
1506                 imm |= (in & ARM_CDSP_BKPT_LIMM_MASK);
1507                 if (snprintf(buf, buflen, "bkpt %d", imm) >= buflen)
1508                         return (1);
1509                 return (0);
1510         }
1511 
1512         /*
1513          * Here we need to handle another set of multiplies. Specifically the
1514          * Signed multiplies. This is SMLA<x><y>, SMLAW<y>, SMULW<y>,
1515          * SMLAL<x><y>, SMUL<x><y>. These instructions all follow the form:
1516          *
1517          * 31 - 28|27-25|24|23|22-21|20|19-16|15-12|11 - 8|7|6|5|4|3-0
1518          * [ cond |  0  | 1| 0| op. | 0|Rn   |Rd   |Rs    |1|y|x|0|Rm ]
1519          *
1520          * If x is one a T is used for that part of the name. Otherwise a B is.
1521          * The same holds true for y.
1522          *
1523          * These instructions map to the following opcodes:
1524          * SMLA<x><y>: 00,
1525          * SMLAW<y>: 01 and x is zero,
1526          * SMULW<y>: 01 and x is one ,
1527          * SMLAL<x><y>: 10,
1528          * SMUL<xy><y>: 11
1529          */
1530         if ((in & ARM_CDSP_SMUL_MASK) == ARM_CDSP_SMUL_TARG) {
1531                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1532                 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1533                 rs = (in & ARM_CDSP_RS_MASK) >> ARM_CDSP_RS_SHIFT;
1534                 rm = in & ARM_CDSP_RM_MASK;
1535                 op = (in & ARM_CDSP_SMUL_OP_MASK) >> ARM_CDSP_SMUL_OP_SHIFT;
1536 
1537                 switch (op) {
1538                 case 0:
1539                         len = snprintf(buf, buflen, "smla%s%s%s %s, %s, %s, %s",
1540                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1541                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1542                             arm_cond_names[cc], arm_reg_names[rd],
1543                             arm_reg_names[rm], arm_reg_names[rs],
1544                             arm_reg_names[rn]);
1545                         break;
1546                 case 1:
1547                         if (in & ARM_CDSP_SMUL_X_MASK) {
1548                                 len = snprintf(buf, buflen,
1549                                     "smulw%s%s %s, %s, %s",
1550                                     (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1551                                     "b", arm_cond_names[cc], arm_reg_names[rd],
1552                                     arm_reg_names[rm], arm_reg_names[rs]);
1553                         } else {
1554                                 len = snprintf(buf, buflen,
1555                                     "smlaw%s%s %s, %s, %s %s",
1556                                     (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1557                                     "b", arm_cond_names[cc], arm_reg_names[rd],
1558                                     arm_reg_names[rm], arm_reg_names[rs],
1559                                     arm_reg_names[rn]);
1560                         }
1561                         break;
1562                 case 2:
1563                         len = snprintf(buf, buflen,
1564                             "smlal%s%s%s %s, %s, %s, %s",
1565                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1566                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1567                             arm_cond_names[cc], arm_reg_names[rd],
1568                             arm_reg_names[rn], arm_reg_names[rm],
1569                             arm_reg_names[rs]);
1570                         break;
1571                 case 3:
1572                         len = snprintf(buf, buflen, "smul%s%s%s %s, %s, %s",
1573                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1574                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1575                             arm_cond_names[cc], arm_reg_names[rd],
1576                             arm_reg_names[rm], arm_reg_names[rs]);
1577                         break;
1578                 default:
1579                         return (-1);
1580                 }
1581                 return (len >= buflen ? -1 : 0);
1582         }
1583 
1584         /*
1585          * If we got here then this is some other instructin we don't know
1586          * about in the instruction extensino space.
1587          */
1588         return (-1);
1589 }
1590 
1591 /*
1592  * Coprocessor double register transfers
1593  *
1594  * MCRR:
1595  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11-8|7-4|3-0
1596  * [ cond |1 1 0| 0| 0| 1| 0| 0| Rn  |  Rd |cp #|op |CRm
1597  *
1598  * MRRC:
1599  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11-8|7-4|3-0
1600  * [ cond |1 1 0| 0| 0| 1| 0| 1| Rn  |  Rd |cp #|op |CRm
1601  *
1602  */
1603 static int
1604 arm_dis_coproc_drt(uint32_t in, char *buf, size_t buflen)
1605 {
1606         arm_cond_code_t cc;
1607         arm_reg_t rd, rn, rm;
1608         uint8_t coproc, op;
1609         const char *ccn;
1610         size_t len;
1611 
1612         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1613         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1614         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1615         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1616         rm = in & ARM_COPROC_RM_MASK;
1617         op = (in & ARM_COPROC_DRT_OP_MASK) >> ARM_COPROC_DRT_OP_SHIFT;
1618 
1619         if (cc == ARM_COND_NACC)
1620                 ccn = "2";
1621         else
1622                 ccn = arm_cond_names[cc];
1623 
1624         len = snprintf(buf, buflen, "%s%s %s, #%d, %s, %s, c%s",
1625             (in & ARM_COPROC_DRT_DIR_MASK) != 0 ? "mrrc" : "mcrr",
1626             ccn, arm_coproc_names[coproc], op, arm_reg_names[rd],
1627             arm_reg_names[rn], arm_reg_names[rm]);
1628         return (len >= buflen ? -1 : 0);
1629 }
1630 
1631 /*
1632  * This serves as both the entry point for the normal load and stores as well as
1633  * the double register transfers (MCRR and MRCC). If it is a register transfer
1634  * then we quickly send it off.
1635  * LDC:
1636  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1637  * [ cond |1 1 0| P| U| N| W| L| Rn  | CRd | cp # | off ]
1638  *
1639  * STC:
1640  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1641  * [ cond |1 1 0| P| U| N| W| L| Rn  | CRd | cp # | off ]
1642  *
1643  * Here the bits mean:
1644  *
1645  * P bit: If P is zero, it is post-indexed or unindexed based on W. If P is 1
1646  * then it is offset-addressing or pre-indexed based on W again.
1647  *
1648  * U bit: If U is positive then the offset if added, subtracted otherwise.. Note
1649  * that if P is zero and W is zero, U must be one.
1650  *
1651  * N bit: If set that means that we have a Long size, this bit is set by the L
1652  * suffix, not to be confused with the L bit.
1653  *
1654  * W bit: If W is one then the memory address is written back to the base
1655  * register. Further W = 0 and P = 0 is unindexed addressing. W = 1, P = 0 is
1656  * post-indexed. W = 0, P = 1 is offset addressing and W = 1, P = 1 is
1657  * pre-indexed.
1658  */
1659 static int
1660 arm_dis_coproc_lsdrt(uint32_t in, char *buf, size_t buflen)
1661 {
1662         arm_cond_code_t cc;
1663         arm_reg_t rn, rd;
1664         uint8_t coproc;
1665         uint32_t imm;
1666         int pbit, ubit, nbit, wbit, lbit;
1667         const char *ccn;
1668         size_t len;
1669 
1670         if ((in & ARM_COPROC_DRT_MASK) == ARM_COPROC_DRT_TARG)
1671                 return (arm_dis_coproc_drt(in, buf, buflen));
1672 
1673         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1674         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1675         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1676         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1677         imm = in & ARM_COPROC_LS_IMM_MASK;
1678 
1679         pbit = in & ARM_COPROC_LS_P_MASK;
1680         ubit = in & ARM_COPROC_LS_U_MASK;
1681         nbit = in & ARM_COPROC_LS_N_MASK;
1682         wbit = in & ARM_COPROC_LS_W_MASK;
1683         lbit = in & ARM_COPROC_LS_L_MASK;
1684 
1685         if (cc == ARM_COND_NACC)
1686                 ccn = "2";
1687         else
1688                 ccn = arm_cond_names[cc];
1689 
1690         len = snprintf(buf, buflen, "%s%s%s %s, c%s, ",
1691             lbit != 0 ? "ldc" : "stc", ccn, nbit != 0 ? "l" : "",
1692             arm_coproc_names[coproc], arm_reg_names[rd]);
1693         if (len >= buflen)
1694                 return (-1);
1695 
1696         if (pbit != 0) {
1697                 imm *= 4;
1698                 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
1699                     arm_reg_names[rn],
1700                     ubit != 0 ? "" : "-", imm,
1701                     wbit != 0 ? "!" : "");
1702         } else if (wbit != 0) {
1703                 imm *= 4;
1704                 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
1705                     arm_reg_names[rn], ubit != 0 ? "" : "-", imm);
1706         } else {
1707                 len += snprintf(buf + len, buflen - len, "[%s], { %d }",
1708                     arm_reg_names[rn], imm);
1709         }
1710         return (len >= buflen ? -1 : 0);
1711 }
1712 
1713 /*
1714  * Here we tell a coprocessor to do data processing
1715  *
1716  * CDP:
1717  * 31 - 28|27 - 24|23-20|19-16|15-12|11 - 8|7 - 5|4|3-0
1718  * [ cond |1 1 1 0| op_1| CRn | CRd | cp # | op_2|0|CRm ]
1719  */
1720 static int
1721 arm_dis_coproc_dp(uint32_t in, char *buf, size_t buflen)
1722 {
1723         arm_cond_code_t cc;
1724         arm_reg_t rn, rd, rm;
1725         uint8_t op1, op2, coproc;
1726         const char *ccn;
1727 
1728         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1729         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1730         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1731         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1732         rm = in & ARM_COPROC_RM_MASK;
1733         op1 = (in & ARM_COPROC_CDP_OP1_MASK) >> ARM_COPROC_CDP_OP1_SHIFT;
1734         op2 = (in & ARM_COPROC_CDP_OP2_MASK) >> ARM_COPROC_CDP_OP2_SHIFT;
1735 
1736         /*
1737          * This instruction is valid with the undefined condition code. When it
1738          * does that, the instruction is intead CDP2 as opposed to CDP.
1739          */
1740         if (cc == ARM_COND_NACC)
1741                 ccn = "2";
1742         else
1743                 ccn = arm_cond_names[cc];
1744 
1745         if (snprintf(buf, buflen, "cdp%s %s, #%d, c%s, c%s, c%s, #%d", ccn,
1746             arm_coproc_names[coproc], op1, arm_reg_names[rd],
1747             arm_reg_names[rn], arm_reg_names[rm], op2) >= buflen)
1748                 return (-1);
1749 
1750         return (0);
1751 }
1752 
1753 /*
1754  * Here we handle coprocesser single register transfers.
1755  *
1756  * MCR:
1757  * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1758  * [ cond |1 1 1 0| op_1| 0| CRn |  Rd | cp # | op_2|1|CRm ]
1759  *
1760  * MRC:
1761  * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1762  * [ cond |1 1 1 0| op_1| 1| CRn |  Rd | cp # | op_2|1|CRm ]
1763  */
1764 static int
1765 arm_dis_coproc_rt(uint32_t in, char *buf, size_t buflen)
1766 {
1767         arm_cond_code_t cc;
1768         arm_reg_t rn, rd, rm;
1769         uint8_t op1, op2, coproc;
1770         const char *ccn;
1771         size_t len;
1772 
1773         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1774         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1775         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1776         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1777         rm = in & ARM_COPROC_RM_MASK;
1778         op1 = (in & ARM_COPROC_CRT_OP1_MASK) >> ARM_COPROC_CRT_OP1_SHIFT;
1779         op2 = (in & ARM_COPROC_CRT_OP2_MASK) >> ARM_COPROC_CRT_OP2_SHIFT;
1780 
1781         if (cc == ARM_COND_NACC)
1782                 ccn = "2";
1783         else
1784                 ccn = arm_cond_names[cc];
1785 
1786         len = snprintf(buf, buflen, "%s%s %s, #%d, %s, c%s, c%s",
1787             (in & ARM_COPROC_CRT_DIR_MASK) != 0 ? "mrc" : "mcr", ccn,
1788             arm_coproc_names[coproc], op1, arm_reg_names[rd],
1789             arm_reg_names[rn], arm_reg_names[rm]);
1790         if (len >= buflen)
1791                 return (-1);
1792 
1793         if (op2 != 0)
1794                 if (snprintf(buf + len, buflen - len, ", #%d", op2) >=
1795                     buflen - len)
1796                         return (-1);
1797         return (0);
1798 }
1799 
1800 /*
1801  * Here we handle the set of unconditional instructions.
1802  */
1803 static int
1804 arm_dis_uncond_insn(uint32_t in, char *buf, size_t buflen)
1805 {
1806         int imm, sc;
1807         arm_reg_t rn, rm;
1808         size_t len;
1809 
1810         /*
1811          * The CPS instruction is a bit complicated. It has the following big
1812          * pattern which maps to a few different ways to use it:
1813          *
1814          *
1815          * 31-28|27-25|24|23-20|19-18|17 |16|15-9|8|7|6|5|4-0
1816          *    1 |  0  | 1| 0   |imod|mmod| 0|SBZ |A|I|F|0|mode
1817          *
1818          * CPS<effect> <iflags> {, #<mode> }
1819          * CPS #<mode>
1820          *
1821          * effect: determines what to do with the A, I, F interrupt bits in the
1822          * CPSR. effect is encoded in the imod field. It is either enable
1823          * interrupts 0b10 or disable interrupts 0b11. Recall that interrupts
1824          * are active low in the CPSR. If effect is not specified then this is
1825          * strictly a mode change which is required.
1826          *
1827          * A, I, F: If effect is specified then the bits which are high are
1828          * modified by the instruction.
1829          *
1830          * mode: Specifies a mode to change to. mmod will be 1 if mode is set.
1831          *
1832          */
1833         if ((in & ARM_UNI_CPS_MASK) == ARM_UNI_CPS_TARG) {
1834                 imm = (in & ARM_UNI_CPS_IMOD_MASK) > ARM_UNI_CPS_IMOD_SHIFT;
1835 
1836                 /* Ob01 is not a valid value for the imod */
1837                 if (imm == 1)
1838                         return (-1);
1839 
1840                 if (imm != 0)
1841                         len = snprintf(buf, buflen, "cps%s %s%s%s%s",
1842                             imm == 2 ? "ie" : "id",
1843                             (in & ARM_UNI_CPS_A_MASK) ? "a" : "",
1844                             (in & ARM_UNI_CPS_I_MASK) ? "i" : "",
1845                             (in & ARM_UNI_CPS_F_MASK) ? "f" : "",
1846                             (in & ARM_UNI_CPS_MMOD_MASK) ? " ," : "");
1847                 else
1848                         len = snprintf(buf, buflen, "cps ");
1849                 if (len >= buflen)
1850                         return (-1);
1851 
1852                 if (in & ARM_UNI_CPS_MMOD_MASK)
1853                         if (snprintf(buf + len, buflen - len, "#%d",
1854                             in & ARM_UNI_CPS_MODE_MASK) >= buflen - len)
1855                                 return (-1);
1856                 return (0);
1857         }
1858 
1859         if ((in & ARM_UNI_SE_MASK) == ARM_UNI_SE_TARG) {
1860                 if (snprintf(buf, buflen, "SETEND %s",
1861                     (in & ARM_UNI_SE_BE_MASK) ? "be" : "le") >= buflen)
1862                         return (-1);
1863                 return (0);
1864         }
1865 
1866         /*
1867          * The cache preload is like a load, but it has a much simpler set of
1868          * constraints. The only valid bits that you can transform are the I and
1869          * the U bits. We have to use pre-indexed addressing. This means that we
1870          * only have the U bit and the I bit. See arm_dis_ldstr for a full
1871          * explanation of what's happening here.
1872          */
1873         if ((in & ARM_UNI_PLD_MASK) == ARM_UNI_PLD_TARG) {
1874                 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1875                 if ((in & ARM_LS_IBIT_MASK) == 0) {
1876                         if (snprintf(buf, buflen, "pld [%s, #%s%d",
1877                             arm_reg_names[rn],
1878                             (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1879                             in & ARM_LS_IMM_MASK) >= buflen)
1880                                 return (-1);
1881                         return (0);
1882                 }
1883 
1884                 rm = in & ARM_LS_REG_RM_MASK;
1885                 len = snprintf(buf, buflen, "pld [%s, %s%s", arm_reg_names[rn],
1886                     (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1887                     arm_reg_names[rm]);
1888                 if (len >= buflen)
1889                         return (-1);
1890 
1891                 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
1892                         imm = (in & ARM_LS_SCR_SIMM_MASK) >>
1893                             ARM_LS_SCR_SIMM_SHIFT;
1894                         sc = (in & ARM_LS_SCR_SCODE_MASK) >>
1895                             ARM_LS_SCR_SCODE_SHIFT;
1896 
1897                         if (imm == 0 && sc == DPI_S_ROR)
1898                                 sc = DPI_S_RRX;
1899 
1900                         len += snprintf(buf + len, buflen - len, "%s",
1901                             arm_dpi_shifts[sc]);
1902                         if (len >= buflen)
1903                                 return (-1);
1904                         if (sc != DPI_S_RRX) {
1905                                 len += snprintf(buf + len, buflen - len,
1906                                     " #%d", imm);
1907                                 if (len >= buflen)
1908                                         return (-1);
1909                         }
1910                 }
1911                 if (snprintf(buf + len, buflen - len, "]") >= buflen - len)
1912                         return (-1);
1913                 return (0);
1914         }
1915 
1916         /*
1917          * This is a special case of STM, but it works across chip modes.
1918          */
1919         if ((in & ARM_UNI_SRS_MASK) == ARM_UNI_SRS_TARG) {
1920                 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1921                 if (snprintf(buf, buflen, "srs%s #%d%s",
1922                     arm_lsm_mode_names[imm],
1923                     in & ARM_UNI_SRS_MODE_MASK,
1924                     (in & ARM_UNI_SRS_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1925                         return (-1);
1926                 return (0);
1927         }
1928 
1929         /*
1930          * RFE is a return from exception instruction that is similar to the LDM
1931          * and STM, but a bit different.
1932          */
1933         if ((in & ARM_UNI_RFE_MASK) == ARM_UNI_RFE_TARG) {
1934                 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1935                 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1936                 if (snprintf(buf, buflen, "rfe%s %s%s", arm_lsm_mode_names[imm],
1937                     arm_reg_names[rn],
1938                     (in & ARM_UNI_RFE_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1939                         return (-1);
1940                 return (0);
1941         }
1942 
1943         if ((in & ARM_UNI_BLX_MASK) == ARM_UNI_BLX_TARG) {
1944                 if (snprintf(buf, buflen, "blx %d",
1945                     in & ARM_UNI_BLX_IMM_MASK) >= buflen)
1946                         return (-1);
1947                 return (0);
1948         }
1949 
1950         if ((in & ARM_UNI_CODRT_MASK) == ARM_UNI_CODRT_TARG) {
1951                 return (arm_dis_coproc_lsdrt(in, buf, buflen));
1952         }
1953 
1954         if ((in & ARM_UNI_CORT_MASK) == ARM_UNI_CORT_TARG) {
1955                 return (arm_dis_coproc_rt(in, buf, buflen));
1956         }
1957 
1958         if ((in & ARM_UNI_CODP_MASK) == ARM_UNI_CORT_TARG) {
1959                 return (arm_dis_coproc_dp(in, buf, buflen));
1960         }
1961 
1962         /*
1963          * An undefined or illegal instruction
1964          */
1965         return (-1);
1966 }
1967 
1968 /*
1969  * Disassemble B and BL instructions. The instruction is given a 24-bit two's
1970  * complement value as an offset address. This value gets sign extended to 30
1971  * bits and then shifted over two bits. This is then added to the PC + 8. So,
1972  * instead of dispalying an absolute address, we're going to display the delta
1973  * that the instruction has instead.
1974  */
1975 static int
1976 arm_dis_branch(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
1977 {
1978         uint32_t addr;
1979         arm_cond_code_t cc;
1980         size_t len;
1981 
1982         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1983         addr = in & ARM_BRANCH_IMM_MASK;
1984         if (in & ARM_BRANCH_SIGN_MASK)
1985                 addr |= ARM_BRANCH_NEG_SIGN;
1986         else
1987                 addr &= ARM_BRANCH_POS_SIGN;
1988         addr <<= 2;
1989         if ((len = snprintf(buf, buflen, "b%s%s %d",
1990             (in & ARM_BRANCH_LBIT_MASK) != 0 ? "l" : "",
1991             arm_cond_names[cc], (int)addr)) >= buflen)
1992                 return (-1);
1993 
1994         /* Per the ARM manuals, we have to account for the extra 8 bytes here */
1995         if (dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8, NULL, 0,
1996             NULL, NULL) == 0) {
1997                 len += snprintf(buf + len, buflen - len, "\t<");
1998                 if (len >= buflen)
1999                         return (-1);
2000                 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8,
2001                     buf + len, buflen - len, NULL, NULL);
2002                 strlcat(buf, ">", buflen);
2003         }
2004 
2005         return (0);
2006 }
2007 
2008 /*
2009  * There are six instructions that are covered here: ADD16, ADDSUBX, SUBADDX,
2010  * SUB16, ADD8, and SUB8. They can hae the following variations: S, Q, SH, U,
2011  * UQ, and UH. It has two differnt sets of bits to determine the opcode: 22-20
2012  * and then 7-5.
2013  *
2014  * These instructions have the general form of:
2015  *
2016  * 31 - 28|27-25|24|23|22-20|19-16|15-12|11 - 8|7-5|4|3-0
2017  * [ cond |0 1 1| 0| 0| opP |Rn   |Rd   |SBO   |opI|1|Rm ]
2018  *
2019  * Here we use opP to refer to the prefix of the instruction, eg. S, Q, etc.
2020  * Where as opI refers to which instruction it is, eg. ADD16, ADD8, etc. We use
2021  * string tables for both of these in arm_padd_p_names and arm_padd_i_names. If
2022  * there is an empty entry that means that the instruction in question doesn't
2023  * exist.
2024  */
2025 static int
2026 arm_dis_padd(uint32_t in, char *buf, size_t buflen)
2027 {
2028         arm_reg_t rn, rd, rm;
2029         arm_cond_code_t cc;
2030         uint8_t opp, opi;
2031         const char *pstr, *istr;
2032 
2033         opp = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2034         opi = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2035 
2036         pstr = arm_padd_p_names[opp];
2037         istr = arm_padd_i_names[opi];
2038 
2039         if (pstr == NULL || istr == NULL)
2040                 return (-1);
2041 
2042         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2043         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2044         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2045         rm = in & ARM_MEDIA_RM_MASK;
2046 
2047         if (snprintf(buf, buflen, "%s%%s %s, %s, %s", pstr, istr,
2048             arm_cond_names[cc], arm_reg_names[rd], arm_reg_names[rn],
2049             arm_reg_names[rm]) >= buflen)
2050                 return (-1);
2051         return (0);
2052 }
2053 
2054 /*
2055  * Disassemble the extend instructions from ARMv6. There are six instructions:
2056  *
2057  * XTAB16, XTAB, XTAH, XTB16, XTB, XTFH. These can exist with one of the
2058  * following prefixes: S, U. The opcode exists in bits 22-20. We have the
2059  * following rules from there:
2060  *
2061  * If bit 22 is one then we are using the U prefix, otherwise the S prefix. Then
2062  * we have the following opcode maps in the lower two bits:
2063  * XTAB16       00 iff Rn != 0xf
2064  * XTAB         10 iff Rn != 0xf
2065  * XTAH         11 iff Rn != 0xf
2066  * XTB16        00 iff Rn = 0xf
2067  * XTB          10 iff Rn = 0xf
2068  * XTH          11 iff Rn = 0xf
2069  */
2070 static int
2071 arm_dis_extend(uint32_t in, char *buf, size_t buflen)
2072 {
2073         uint8_t op, rot;
2074         int sbit;
2075         arm_cond_code_t cc;
2076         arm_reg_t rn, rm, rd;
2077         const char *opn;
2078         size_t len;
2079 
2080 
2081         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2082         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2083         rm = in & ARM_MEDIA_RM_MASK;
2084         op = (in & ARM_MEDIA_SZE_OP_MASK) >> ARM_MEDIA_SZE_OP_SHIFT;
2085         rot = (in & ARM_MEDIA_SZE_ROT_MASK) >> ARM_MEDIA_SZE_ROT_SHIFT;
2086         sbit = in & ARM_MEDIA_SZE_S_MASK;
2087         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2088 
2089         switch (op) {
2090         case 0x0:
2091                 opn = rn == ARM_REG_R15 ? "xtab16" : "xtb16";
2092                 break;
2093         case 0x2:
2094                 opn = rn == ARM_REG_R15 ? "xtab" : "xtb";
2095                 break;
2096         case 0x3:
2097                 opn = rn == ARM_REG_R15 ? "xtah" : "xth";
2098                 break;
2099         default:
2100                 return (-1);
2101                 break;
2102         }
2103 
2104         if (rn == ARM_REG_R15) {
2105                 len = snprintf(buf, buflen, "%s%s%s %s, %s",
2106                     sbit != 0 ? "u" : "s",
2107                     opn, arm_cond_names[cc], arm_reg_names[rd],
2108                     arm_reg_names[rn]);
2109         } else {
2110                 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2111                     sbit != 0 ? "u" : "s",
2112                     opn, arm_cond_names[cc], arm_reg_names[rd],
2113                     arm_reg_names[rn], arm_reg_names[rm]);
2114         }
2115 
2116         if (len >= buflen)
2117                 return (-1);
2118 
2119         if (snprintf(buf + len, buflen - len, "%s",
2120             arm_extend_rot_names[rot]) >= buflen - len)
2121                 return (-1);
2122         return (0);
2123 }
2124 
2125 /*
2126  * The media instructions and extensions can be divided into different groups of
2127  * instructions. We first use bits 23 and 24 to figure out where to send it. We
2128  * call this group of bits the l1 mask.
2129  */
2130 static int
2131 arm_dis_media(uint32_t in, char *buf, size_t buflen)
2132 {
2133         uint8_t l1, op1, op2;
2134         arm_cond_code_t cc;
2135         arm_reg_t rd, rn, rs, rm;
2136         int xbit;
2137         size_t len;
2138 
2139         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2140         l1 = (in & ARM_MEDIA_L1_MASK) >> ARM_MEDIA_L1_SHIFT;
2141         switch (l1) {
2142         case 0x0:
2143                 return (arm_dis_padd(in, buf, buflen));
2144                 break;
2145         case 0x1:
2146                 if ((in & ARM_MEDIA_HPACK_MASK) == ARM_MEDIA_HPACK_TARG) {
2147                         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2148                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2149                         rm = in & ARM_MEDIA_RM_MASK;
2150                         op1 = (in & ARM_MEDIA_HPACK_SHIFT_MASK) >>
2151                             ARM_MEDIA_HPACK_SHIFT_IMM;
2152                         len = snprintf(buf, buflen, "%s%s %s, %s, %s",
2153                             (in & ARM_MEDIA_HPACK_OP_MASK) != 0 ?
2154                             "pkhtb" : "pkhbt", arm_cond_names[cc],
2155                             arm_reg_names[rd], arm_reg_names[rn],
2156                             arm_reg_names[rd]);
2157                         if (len >= buflen)
2158                                 return (-1);
2159 
2160                         if (op1 != 0) {
2161                                 if (in & ARM_MEDIA_HPACK_OP_MASK)
2162                                         len += snprintf(buf + len, buflen - len,
2163                                             ", asr %d", op1);
2164                                 else
2165                                         len += snprintf(buf + len, buflen - len,
2166                                             ", lsl %d", op1);
2167                         }
2168                         return (len >= buflen ? -1 : 0);
2169                 }
2170 
2171                 if ((in & ARM_MEDIA_WSAT_MASK) == ARM_MEDIA_WSAT_TARG) {
2172                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2173                         rm = in & ARM_MEDIA_RM_MASK;
2174                         op1 = (in & ARM_MEDIA_SAT_IMM_MASK) >>
2175                             ARM_MEDIA_SAT_IMM_SHIFT;
2176                         op2 = (in & ARM_MEDIA_SAT_SHI_MASK) >>
2177                             ARM_MEDIA_SAT_SHI_SHIFT;
2178                         len = snprintf(buf, buflen, "%s%s %s, #%d, %s",
2179                             (in & ARM_MEDIA_SAT_U_MASK) != 0 ? "usat" : "ssat",
2180                             arm_cond_names[cc], arm_reg_names[rd], op1,
2181                             arm_reg_names[rm]);
2182 
2183                         if (len >= buflen)
2184                                 return (-1);
2185 
2186                         /*
2187                          * The shift is optional in the assembler and encoded as
2188                          * LSL 0. However if we get ASR 0, that means ASR #32.
2189                          * An ARM_MEDIA_SAT_STYPE_MASK of 0 is LSL, 1 is ASR.
2190                          */
2191                         if (op2 != 0 || (in & ARM_MEDIA_SAT_STYPE_MASK) == 1) {
2192                                 if (op2 == 0)
2193                                         op2 = 32;
2194                                 if (snprintf(buf + len, buflen - len,
2195                                     ", %s #%d",
2196                                     (in & ARM_MEDIA_SAT_STYPE_MASK) != 0 ?
2197                                     "asr" : "lsl", op2) >= buflen - len)
2198                                         return (-1);
2199                         }
2200                         return (0);
2201                 }
2202 
2203                 if ((in & ARM_MEDIA_PHSAT_MASK) == ARM_MEDIA_PHSAT_TARG) {
2204                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2205                         rm = in & ARM_MEDIA_RM_MASK;
2206                         op1 = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2207                         if (snprintf(buf, buflen, "%s%s %s, #%d, %s",
2208                             (in & ARM_MEDIA_SAT_U_MASK) != 0 ?
2209                             "usat16" : "ssat16",
2210                             arm_cond_names[cc], arm_reg_names[rd], op1,
2211                             arm_reg_names[rm]) >= buflen)
2212                                 return (-1);
2213                         return (0);
2214                 }
2215 
2216                 if ((in & ARM_MEDIA_REV_MASK) == ARM_MEDIA_REV_TARG) {
2217                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2218                         rm = in & ARM_MEDIA_RM_MASK;
2219                         if (snprintf(buf, buflen, "rev%s %s, %s",
2220                             arm_cond_names[cc], arm_reg_names[rd],
2221                             arm_reg_names[rd]) >= buflen)
2222                                 return (-1);
2223                         return (0);
2224                 }
2225 
2226                 if ((in & ARM_MEDIA_BRPH_MASK) == ARM_MEDIA_BRPH_TARG) {
2227                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2228                         rm = in & ARM_MEDIA_RM_MASK;
2229                         if (snprintf(buf, buflen, "rev16%s %s, %s",
2230                             arm_cond_names[cc], arm_reg_names[rd],
2231                             arm_reg_names[rd]) >= buflen)
2232                                 return (-1);
2233                         return (0);
2234                 }
2235 
2236                 if ((in & ARM_MEDIA_BRSH_MASK) == ARM_MEDIA_BRSH_TARG) {
2237                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2238                         rm = in & ARM_MEDIA_RM_MASK;
2239                         if (snprintf(buf, buflen, "revsh%s %s, %s",
2240                             arm_cond_names[cc], arm_reg_names[rd],
2241                             arm_reg_names[rd]) >= buflen)
2242                                 return (-1);
2243                         return (0);
2244                 }
2245 
2246                 if ((in & ARM_MEDIA_SEL_MASK) == ARM_MEDIA_SEL_TARG) {
2247                         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2248                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2249                         rm = in & ARM_MEDIA_RM_MASK;
2250                         if (snprintf(buf, buflen, "sel%s %s, %s, %s",
2251                             arm_cond_names[cc], arm_reg_names[rd],
2252                             arm_reg_names[rn], arm_reg_names[rm]) >= buflen)
2253                                 return (-1);
2254                         return (0);
2255                 }
2256 
2257                 if ((in & ARM_MEDIA_SZE_MASK) == ARM_MEDIA_SZE_TARG)
2258                         return (arm_dis_extend(in, buf, buflen));
2259                 /* Unknown instruction */
2260                 return (-1);
2261                 break;
2262         case 0x2:
2263                 /*
2264                  * This consists of the following multiply instructions:
2265                  * SMLAD, SMLSD, SMLALD, SMUAD, and SMUSD.
2266                  *
2267                  * SMLAD and SMUAD encoding are the same, switch on Rn == R15
2268                  * 22-20 are 000 7-6 are 00
2269                  * SMLSD and SMUSD encoding are the same, switch on Rn == R15
2270                  * 22-20 are 000 7-6 are 01
2271                  * SMLALD: 22-20 are 100 7-6 are 00
2272                  */
2273                 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2274                 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2275                 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2276                 rm = in & ARM_MEDIA_RM_MASK;
2277                 op1 = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2278                 op2 = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2279                 xbit = in & ARM_MEDIA_MULT_X_MASK;
2280 
2281                 if (op1 == 0x0) {
2282                         if (op2 != 0x0 && op2 != 0x1)
2283                                 return (-1);
2284                         if (rn == ARM_REG_R15) {
2285                                 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2286                                     op2 != 0 ? "smusd" : "smuad",
2287                                     xbit != 0 ? "x" : "x",
2288                                     arm_cond_names[cc], arm_reg_names[rd],
2289                                     arm_reg_names[rm], arm_reg_names[rs]);
2290                         } else {
2291                                 len = snprintf(buf, buflen,
2292                                     "%s%s%s %s, %s, %s, %s",
2293                                     op2 != 0 ? "smlsd" : "smlad",
2294                                     xbit != 0 ? "x" : "",
2295                                     arm_cond_names[cc], arm_reg_names[rd],
2296                                     arm_reg_names[rm], arm_reg_names[rs],
2297                                     arm_reg_names[rn]);
2298 
2299                         }
2300                 } else if (op1 == 0x8) {
2301                         if (op2 != 0x0)
2302                                 return (-1);
2303                         len = snprintf(buf, buflen, "smlald%s%s %s, %s, %s, %s",
2304                             xbit != 0 ? "x" : "",
2305                             arm_cond_names[cc], arm_reg_names[rn],
2306                             arm_reg_names[rd], arm_reg_names[rm],
2307                             arm_reg_names[rs]);
2308                 } else
2309                         return (-1);
2310 
2311                 return (len >= buflen ? -1 : 0);
2312                 break;
2313         case 0x3:
2314                 /*
2315                  * Here we handle USAD8 and USADA8. The main difference is the
2316                  * presence of RN. USAD8 is defined as having a value of rn that
2317                  * is not r15. If it is r15, then instead it is USADA8.
2318                  */
2319                 if ((in & ARM_MEDIA_OP1_MASK) != 0)
2320                         return (-1);
2321                 if ((in & ARM_MEDIA_OP2_MASK) != 0)
2322                         return (-1);
2323 
2324                 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2325                 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2326                 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2327                 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2328                 rm = in & ARM_MEDIA_RM_MASK;
2329 
2330                 if (rn != ARM_REG_R15)
2331                         len = snprintf(buf, buflen, "usada8%s %s, %s, %s, %s",
2332                             arm_cond_names[cc], arm_reg_names[rd],
2333                             arm_reg_names[rm], arm_reg_names[rs],
2334                             arm_reg_names[rn]);
2335                 else
2336                         len = snprintf(buf, buflen, "usad8%s %s, %s, %s",
2337                             arm_cond_names[cc], arm_reg_names[rd],
2338                             arm_reg_names[rm], arm_reg_names[rs]);
2339                 return (len >= buflen ? -1 : 0);
2340                 break;
2341         default:
2342                 return (-1);
2343         }
2344 }
2345 
2346 /*
2347  * Each instruction in the ARM instruction set is a uint32_t and in our case is
2348  * LE. The upper four bits determine the condition code. If the conditoin code
2349  * is undefined then we know to immediately jump there. Otherwise we go use the
2350  * next three bits to determine where we should go next and how to further
2351  * process the instruction in question. The ARM instruction manual doesn't
2352  * define this field so we're going to call it the L1_DEC or level 1 decoding
2353  * from which it will have to be further subdivided into the specific
2354  * instruction groupings that we care about.
2355  */
2356 static int
2357 arm_dis(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
2358 {
2359         uint8_t l1;
2360         arm_cond_code_t cc;
2361 
2362         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2363 
2364         if (cc == ARM_COND_NACC)
2365                 return (arm_dis_uncond_insn(in, buf, buflen));
2366 
2367         l1 = (in & ARM_L1_DEC_MASK) >> ARM_L1_DEC_SHIFT;
2368 
2369         switch (l1) {
2370         case 0x0:
2371                 /*
2372                  * The l0 group is a bit complicated. We have several different
2373                  * groups of instructions to consider. The first question is
2374                  * whether bit 4 is zero or not. If it is, then we have a data
2375                  * processing immediate shift unless the opcode and + S bits
2376                  * (24-20) is of the form 0b10xx0.
2377                  *
2378                  * When bit 4 is 1, we have to then also look at bit 7. If bit
2379                  * 7 is one then we know that this is the class of multiplies /
2380                  * extra load/stores. If bit 7 is zero then we have the same
2381                  * opcode games as we did above.
2382                  */
2383                 if (in & ARM_L1_0_B4_MASK) {
2384                         if (in & ARM_L1_0_B7_MASK) {
2385                                 /*
2386                                  * Both the multiplication extensions and the
2387                                  * load and store extensions live in this
2388                                  * region. The load and store extensions can be
2389                                  * identified by having at least one of bits 5
2390                                  * and 6 set. The exceptions to this are the
2391                                  * SWP and SWPB instructions and the exclusive
2392                                  * load and store instructions which, unlike the
2393                                  * multiplication instructions. These have
2394                                  * specific values for the bits in the range of
2395                                  * 20-24.
2396                                  */
2397                                 if ((in & ARM_L1_0_ELS_MASK) != 0)
2398                                         /* Extra loads/stores */
2399                                         return (arm_dis_els(in, buf, buflen));
2400                                 if ((in & ARM_ELS_SWAP_MASK) == ARM_ELS_IS_SWAP)
2401                                         return (arm_dis_swap(in, buf, buflen));
2402                                 if ((in & ARM_ELS_EXCL_MASK) ==
2403                                     ARM_ELS_EXCL_MASK)
2404                                         return (arm_dis_lsexcl(in, buf,
2405                                             buflen));
2406                                 /* Multiplication instruction extension A3-3. */
2407                                 return (arm_dis_extmul(in, buf, buflen));
2408                         }
2409                         if ((in & ARM_L1_0_OPMASK) == ARM_L1_0_SPECOP &&
2410                             !(in & ARM_L1_0_SMASK)) {
2411                                 /* Misc. Instructions A3-4 */
2412                                 return (arm_dis_cdsp_ext(in, buf, buflen));
2413                         } else {
2414                                 /* data processing register shift */
2415                                 return (arm_dis_dpi(in, cc, buf, buflen));
2416                         }
2417                 } else {
2418                         if ((in & ARM_L1_0_OPMASK) == ARM_L1_0_SPECOP &&
2419                             !(in & ARM_L1_0_SMASK))
2420                                 /* Misc. Instructions A3-4 */
2421                                 return (arm_dis_cdsp_ext(in, buf, buflen));
2422                         else {
2423                                 /* Data processing immediate shift */
2424                                 return (arm_dis_dpi(in, cc, buf, buflen));
2425                         }
2426                 }
2427                 break;
2428         case 0x1:
2429                 /*
2430                  * In l1 group 0b001 there are a few ways to tell things apart.
2431                  * We are directed to first look at bits 20-24. Data processing
2432                  * immediate has a 4 bit opcode 24-21 followed by an S bit. We
2433                  * know it is not a data processing immediate if we have
2434                  * something of the form 0b10xx0.
2435                  */
2436                 if ((in & ARM_L1_1_OPMASK) == ARM_L1_1_SPECOP &&
2437                     !(in & ARM_L1_1_SMASK)) {
2438                         if (in & ARM_L1_1_UNDEF_MASK) {
2439                                 /* Undefined instructions */
2440                                 return (-1);
2441                         } else {
2442                                 /* Move immediate to status register */
2443                                 return (arm_dis_status_regs(in, buf, buflen));
2444                         }
2445                 } else {
2446                         /* Data processing immedaite */
2447                         return (arm_dis_dpi(in, cc, buf, buflen));
2448                 }
2449                 break;
2450         case 0x2:
2451                 /* Load/store Immediate offset */
2452                 return (arm_dis_ldstr(in, buf, buflen));
2453                 break;
2454         case 0x3:
2455                 /*
2456                  * Like other sets we use the 4th bit to make an intial
2457                  * determination. If it is zero then this is a load/store
2458                  * register offset class instruction. Following that we have a
2459                  * specical mask of 0x01f000f0 to determine whether this is an
2460                  * architecturally undefined instruction type or not.
2461                  *
2462                  * The architecturally undefined are parts of the current name
2463                  * space that just aren't used, but could be used at some point
2464                  * in the future. For now though, it's an invalid op code.
2465                  */
2466                 if (in & ARM_L1_3_B4_MASK) {
2467                         if ((in & ARM_L1_3_ARCHUN_MASK) ==
2468                             ARM_L1_3_ARCHUN_MASK) {
2469                                 /* Architecturally undefined */
2470                                 return (-1);
2471                         } else {
2472                                 /* Media instructions */
2473                                 return (arm_dis_media(in, buf, buflen));
2474                         }
2475                 } else {
2476                         /* Load/store register offset */
2477                         return (arm_dis_ldstr(in, buf, buflen));
2478                 }
2479                 break;
2480         case 0x4:
2481                 /* Load/store multiple */
2482                 return (arm_dis_ldstr_multi(in, buf, buflen));
2483                 break;
2484         case 0x5:
2485                 /* Branch and Branch with link */
2486                 return (arm_dis_branch(dhp, in, buf, buflen));
2487                 break;
2488         case 0x6:
2489                 /* coprocessor load/store && double register transfers */
2490                 return (arm_dis_coproc_lsdrt(in, buf, buflen));
2491                 break;
2492         case 0x7:
2493                 /*
2494                  * In l1 group 0b111 you can determine the three groups using
2495                  * the following logic. If the next bit after the l1 group (bit
2496                  * 24) is one than you know that it is a software interrupt.
2497                  * Otherwise it is one of the coprocessor instructions.
2498                  * Furthermore you can tell apart the data processing from the
2499                  * register transfers based on bit 4. If it is zero then it is
2500                  * a data processing instruction, otherwise it is a register
2501                  * transfer.
2502                  */
2503                 if (in & ARM_L1_7_SWINTMASK) {
2504                         /*
2505                          * The software interrupt is pretty straightforward. The
2506                          * lower 24 bits are the interrupt number. It's also
2507                          * valid for it to run with a condition code.
2508                          */
2509                         if (snprintf(buf, buflen, "swi%s %d",
2510                             arm_cond_names[cc],
2511                             in & ARM_SWI_IMM_MASK) >= buflen)
2512                                 return (-1);
2513                         return (0);
2514                 } else if (in & ARM_L1_7_COPROCMASK) {
2515                         /* coprocessor register transfers */
2516                         return (arm_dis_coproc_rt(in, buf, buflen));
2517                 } else {
2518                         /* coprocessor data processing */
2519                         return (arm_dis_coproc_dp(in, buf, buflen));
2520                 }
2521                 break;
2522         }
2523 
2524         return (-1);
2525 }
2526 
2527 static int
2528 dis_arm_supports_flags(int flags)
2529 {
2530         int archflags = flags & DIS_ARCH_MASK;
2531 
2532         return (archflags == DIS_ARM);
2533 }
2534 
2535 /*ARGSUSED*/
2536 static int
2537 dis_arm_handle_attach(dis_handle_t *dhp)
2538 {
2539         return (0);
2540 }
2541 
2542 /*ARGSUSED*/
2543 static void
2544 dis_arm_handle_detach(dis_handle_t *dhp)
2545 {
2546 }
2547 
2548 static int
2549 dis_arm_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
2550 {
2551         uint32_t in;
2552 
2553         buf[0] = '\0';
2554         dhp->dh_addr = addr;
2555         if (dhp->dh_read(dhp->dh_data, addr, &in, sizeof (in)) !=
2556             sizeof (in))
2557                 return (-1);
2558 
2559         /* Translate in case we're on sparc? */
2560         in = LE_32(in);
2561 
2562         return (arm_dis(dhp, in, buf, buflen));
2563 }
2564 
2565 /*
2566  * This is simple in a non Thumb world. If and when we do enter a world where we
2567  * support thumb instructions, then this becomes far less than simple.
2568  */
2569 /*ARGSUSED*/
2570 static uint64_t
2571 dis_arm_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
2572 {
2573         if (n <= 0)
2574                 return (pc);
2575 
2576         return (pc - n*4);
2577 }
2578 
2579 /*
2580  * If and when we support thumb, then this value should probably become two.
2581  * However, it varies based on whether or not a given instruction is in thumb
2582  * mode.
2583  */
2584 /*ARGSUSED*/
2585 static int
2586 dis_arm_min_instrlen(dis_handle_t *dhp)
2587 {
2588         return (4);
2589 }
2590 
2591 /*
2592  * Regardless of thumb, this value does not change.
2593  */
2594 /*ARGSUSED*/
2595 static int
2596 dis_arm_max_instrlen(dis_handle_t *dhp)
2597 {
2598         return (4);
2599 }
2600 
2601 /* ARGSUSED */
2602 static int
2603 dis_arm_instrlen(dis_handle_t *dhp, uint64_t pc)
2604 {
2605         return (4);
2606 }
2607 
2608 dis_arch_t dis_arch_arm = {
2609         dis_arm_supports_flags,
2610         dis_arm_handle_attach,
2611         dis_arm_handle_detach,
2612         dis_arm_disassemble,
2613         dis_arm_previnstr,
2614         dis_arm_min_instrlen,
2615         dis_arm_max_instrlen,
2616         dis_arm_instrlen
2617 };