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 rx, ry, rz;
1280         int lbit;
1281         size_t len;
1282 
1283         /*
1284          * To make things confusing enough, the names of bitfields between
1285          * ldrex and strex are not totally consistent.  Specifically,
1286          *    STREX rd, rt, [rn]
1287          *       rn = 19:16
1288          *       rd = 15:12
1289          *       rt = 3:0
1290          *
1291          *    LDREX rt, [rn]
1292          *       rn = 19:16
1293          *       rt = 15:12
1294          *
1295          * To avoid having to do too many mental gymnastics, let's just
1296          * think of the bitfields as:
1297          *
1298          *       rx = 19:16
1299          *       ry = 15:12
1300          *       rz = 3:0
1301          *
1302          * And so we print the instructions as:
1303          *    STREX ry, rz, [rx]
1304          *    LDREX ry, [rx]
1305          */
1306 
1307         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1308         rx = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1309         ry = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1310         rz = (in & ARM_ELS_LOW_AM_MASK);
1311         lbit = in & ARM_ELS_LBIT_MASK;
1312 
1313         len = snprintf(buf, buflen, "%s%sex %s, ",
1314             lbit != 0 ? "ldr" : "str",
1315             arm_cond_names[cc], arm_reg_names[ry]);
1316         if (len >= buflen)
1317                 return (-1);
1318 
1319         if (lbit)
1320                 len += snprintf(buf + len, buflen - len, "[%s]",
1321                     arm_reg_names[rx]);
1322         else
1323                 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1324                     arm_reg_names[rz], arm_reg_names[rx]);
1325         return (len >= buflen ? -1 : 0);
1326 }
1327 
1328 /*
1329  * This is designed to handle the multiplication instruction extension space.
1330  * Note that this doesn't actually cover all of the multiplication instructions
1331  * available in ARM, but all of the ones that are in this space. This includes
1332  * the following instructions:
1333  *
1334  *
1335  * There are three basic encoding formats:
1336  *
1337  * Multipy (acc):
1338  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1339  * [ cond |   0   |0 |0 | A |S |Rn  | Rd   |Rs   |1|0|0|1|Rm ]
1340  *
1341  * Unsigned multipy acc acc long
1342  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1343  * [ cond |   0   |0 |1 |0 |0 |RdHi |RdLo  |Rs   |1|0|0|1|Rm ]
1344  *
1345  * Multiply (acc) long:
1346  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1347  * [ cond |   0   |1 |Un|A |S |RdHi| RdLo |Rs   |1|0|0|1|Rm ]
1348  *
1349  * A bit: Accumulate
1350  * Un bit: Unsigned is active low, signed is active high
1351  * S bit: Indicates whethere the status register should be updated.
1352  *
1353  * MLA(S) and MUL(S) make up the first type of instructions.
1354  * UMAAL makes up the second group.
1355  * (U|S)MULL(S), (U|S)MLAL(S), Make up the third.
1356  */
1357 static int
1358 arm_dis_extmul(uint32_t in, char *buf, size_t buflen)
1359 {
1360         arm_cond_code_t cc;
1361         arm_reg_t rd, rn, rs, rm;
1362         size_t len;
1363 
1364         /*
1365          * RdHi is equal to rd here. RdLo is equal to Rn here.
1366          */
1367         rd = (in & ARM_EMULT_RD_MASK) >> ARM_EMULT_RD_SHIFT;
1368         rn = (in & ARM_EMULT_RN_MASK) >> ARM_EMULT_RN_SHIFT;
1369         rs = (in & ARM_EMULT_RS_MASK) >> ARM_EMULT_RS_SHIFT;
1370         rm = in & ARM_EMULT_RM_MASK;
1371 
1372         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1373 
1374         if ((in & ARM_EMULT_MA_MASK) == 0) {
1375                 if (in & ARM_EMULT_ABIT_MASK) {
1376                         len = snprintf(buf, buflen, "mla%s%s %s, %s, %s, %s",
1377                             arm_cond_names[cc],
1378                             (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1379                             arm_reg_names[rd], arm_reg_names[rm],
1380                             arm_reg_names[rs], arm_reg_names[rs]);
1381                 } else {
1382                         len = snprintf(buf, buflen, "mul%s%s %s, %s, %s",
1383                             arm_cond_names[cc],
1384                             (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1385                             arm_reg_names[rd], arm_reg_names[rm],
1386                             arm_reg_names[rs]);
1387 
1388                 }
1389         } else if ((in & ARM_EMULT_UMA_MASK) == ARM_EMULT_UMA_TARG) {
1390                 len = snprintf(buf, buflen, "umaal%s %s, %s, %s, %s",
1391                     arm_cond_names[cc], arm_reg_names[rn], arm_reg_names[rd],
1392                     arm_reg_names[rm], arm_reg_names[rs]);
1393         } else if ((in & ARM_EMULT_MAL_MASK) == ARM_EMULT_MAL_TARG) {
1394                 len = snprintf(buf, buflen, "%s%s%s%s %s, %s, %s, %s",
1395                     (in & ARM_EMULT_UNBIT_MASK) ? "s" : "u",
1396                     (in & ARM_EMULT_ABIT_MASK) ? "mlal" : "mull",
1397                     arm_cond_names[cc],
1398                     (in & ARM_EMULT_SBIT_MASK) ? "s" : "",
1399                     arm_reg_names[rn], arm_reg_names[rd], arm_reg_names[rm],
1400                     arm_reg_names[rs]);
1401         } else {
1402                 /* Not a supported instruction in this space */
1403                 return (-1);
1404         }
1405         return (len >= buflen ? -1 : 0);
1406 }
1407 
1408 /*
1409  * Here we handle the three different cases of moving to and from the various
1410  * status registers in both register mode and in immediate mode.
1411  */
1412 static int
1413 arm_dis_status_regs(uint32_t in, char *buf, size_t buflen)
1414 {
1415         arm_cond_code_t cc;
1416         arm_reg_t rd, rm;
1417         uint8_t field;
1418         int imm;
1419         size_t len;
1420 
1421         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1422 
1423         if ((in & ARM_CDSP_MRS_MASK) == ARM_CDSP_MRS_TARG) {
1424                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1425                 if (snprintf(buf, buflen, "mrs%s %s, %s", arm_cond_names[cc],
1426                     arm_reg_names[rd],
1427                     (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr") >=
1428                     buflen)
1429                         return (-1);
1430                 return (0);
1431         }
1432 
1433         field = (in & ARM_CDSP_MSR_F_MASK) >> ARM_CDSP_MSR_F_SHIFT;
1434         len = snprintf(buf, buflen, "msr%s %s_%s, ", arm_cond_names[cc],
1435             (in & ARM_CDSP_STATUS_RBIT) != 0 ? "spsr" : "cpsr",
1436             arm_cdsp_msr_field_names[field]);
1437         if (len >= buflen)
1438                 return (-1);
1439 
1440         if (in & ARM_CDSP_MSR_ISIMM_MASK) {
1441                 imm = in & ARM_CDSP_MSR_IMM_MASK;
1442                 imm <<= (in & ARM_CDSP_MSR_RI_MASK) >> ARM_CDSP_MSR_RI_SHIFT;
1443                 len += snprintf(buf + len, buflen - len, "#%d", imm);
1444         } else {
1445                 rm = in & ARM_CDSP_RM_MASK;
1446                 len += snprintf(buf + len, buflen - len, "%s",
1447                     arm_reg_names[rm]);
1448         }
1449 
1450         return (len >= buflen ? -1 : 0);
1451 }
1452 
1453 /*
1454  * Here we need to handle the Control And DSP instruction extension space. This
1455  * consists of several different instructions. Unlike other extension spaces
1456  * there isn't as much tha tis similar here as there is stuff that is different.
1457  * Oh well, that's a part of life. Instead we do a little bit of additional
1458  * parsing here.
1459  *
1460  * The first group that we separate out are the instructions that interact with
1461  * the status registers. Those are handled in their own function.
1462  */
1463 static int
1464 arm_dis_cdsp_ext(uint32_t in, char *buf, size_t buflen)
1465 {
1466         uint16_t imm, op;
1467         arm_cond_code_t cc;
1468         arm_reg_t rd, rm, rn, rs;
1469         size_t len;
1470 
1471         if ((in & ARM_CDSP_STATUS_MASK) == ARM_CDSP_STATUS_TARG)
1472                 return (arm_dis_status_regs(in, buf, buflen));
1473 
1474         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1475 
1476         /*
1477          * This gets the Branch/exchange as well as the Branch and link/exchange
1478          * pieces. These generally also transform the instruction set into
1479          * something we can't actually disassemble. Here the lower mask and
1480          * target is the opposite. eg. the target bits are not what we want.
1481          */
1482         if ((in & ARM_CDSP_BEX_UP_MASK) == ARM_CDSP_BEX_UP_TARG &&
1483             (in & ARM_CDSP_BEX_LOW_MASK) != ARM_CDSP_BEX_NLOW_TARG) {
1484                 rm = in & ARM_CDSP_RM_MASK;
1485                 imm = (in & ARM_CDSP_BEX_TYPE_MASK) >> ARM_CDSP_BEX_TYPE_SHIFT;
1486                 if (snprintf(buf, buflen, "b%s%s %s",
1487                     imm == ARM_CDSP_BEX_TYPE_X ? "x" :
1488                     imm == ARM_CDSP_BEX_TYPE_J ? "xj" : "lx",
1489                     arm_cond_names[cc], arm_reg_names[rm]) >= buflen)
1490                         return (-1);
1491                 return (0);
1492         }
1493 
1494         /* Count leading zeros */
1495         if ((in & ARM_CDSP_CLZ_MASK) == ARM_CDSP_CLZ_TARG) {
1496                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1497                 rm = in & ARM_CDSP_RM_MASK;
1498                 if (snprintf(buf, buflen, "clz%s %s, %s", arm_cond_names[cc],
1499                     arm_reg_names[rd], arm_reg_names[rm]) >= buflen)
1500                         return (-1);
1501                 return (0);
1502         }
1503 
1504         if ((in & ARM_CDSP_SAT_MASK) == ARM_CDSP_SAT_TARG) {
1505                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1506                 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1507                 rm = in & ARM_CDSP_RM_MASK;
1508                 imm = (in & ARM_CDSP_SAT_OP_MASK) >> ARM_CDSP_SAT_OP_SHIFT;
1509                 if (snprintf(buf, buflen, "q%s%s %s, %s, %s",
1510                     arm_cdsp_sat_opnames[imm], arm_cond_names[cc],
1511                     arm_reg_names[rd], arm_reg_names[rm],
1512                     arm_reg_names[rn]) >= buflen)
1513                         return (-1);
1514                 return (0);
1515         }
1516 
1517         /*
1518          * Breakpoint instructions are a bit different. While they are in the
1519          * conditional instruction namespace, they actually aren't defined to
1520          * take a condition. That's just how it rolls. The breakpoint is a
1521          * 16-bit value. The upper 12 bits are stored together and the lower
1522          * four together.
1523          */
1524         if ((in & ARM_CDSP_BKPT_MASK) == ARM_CDSP_BKPT_TARG) {
1525                 if (cc != ARM_COND_NACC)
1526                         return (-1);
1527                 imm = (in & ARM_CDSP_BKPT_UIMM_MASK) >>
1528                     ARM_CDSP_BKPT_UIMM_SHIFT;
1529                 imm <<= 4;
1530                 imm |= (in & ARM_CDSP_BKPT_LIMM_MASK);
1531                 if (snprintf(buf, buflen, "bkpt %d", imm) >= buflen)
1532                         return (1);
1533                 return (0);
1534         }
1535 
1536         /*
1537          * Here we need to handle another set of multiplies. Specifically the
1538          * Signed multiplies. This is SMLA<x><y>, SMLAW<y>, SMULW<y>,
1539          * SMLAL<x><y>, SMUL<x><y>. These instructions all follow the form:
1540          *
1541          * 31 - 28|27-25|24|23|22-21|20|19-16|15-12|11 - 8|7|6|5|4|3-0
1542          * [ cond |  0  | 1| 0| op. | 0|Rn   |Rd   |Rs    |1|y|x|0|Rm ]
1543          *
1544          * If x is one a T is used for that part of the name. Otherwise a B is.
1545          * The same holds true for y.
1546          *
1547          * These instructions map to the following opcodes:
1548          * SMLA<x><y>: 00,
1549          * SMLAW<y>: 01 and x is zero,
1550          * SMULW<y>: 01 and x is one ,
1551          * SMLAL<x><y>: 10,
1552          * SMUL<xy><y>: 11
1553          */
1554         if ((in & ARM_CDSP_SMUL_MASK) == ARM_CDSP_SMUL_TARG) {
1555                 rd = (in & ARM_CDSP_RD_MASK) >> ARM_CDSP_RD_SHIFT;
1556                 rn = (in & ARM_CDSP_RN_MASK) >> ARM_CDSP_RN_SHIFT;
1557                 rs = (in & ARM_CDSP_RS_MASK) >> ARM_CDSP_RS_SHIFT;
1558                 rm = in & ARM_CDSP_RM_MASK;
1559                 op = (in & ARM_CDSP_SMUL_OP_MASK) >> ARM_CDSP_SMUL_OP_SHIFT;
1560 
1561                 switch (op) {
1562                 case 0:
1563                         len = snprintf(buf, buflen, "smla%s%s%s %s, %s, %s, %s",
1564                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1565                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1566                             arm_cond_names[cc], arm_reg_names[rd],
1567                             arm_reg_names[rm], arm_reg_names[rs],
1568                             arm_reg_names[rn]);
1569                         break;
1570                 case 1:
1571                         if (in & ARM_CDSP_SMUL_X_MASK) {
1572                                 len = snprintf(buf, buflen,
1573                                     "smulw%s%s %s, %s, %s",
1574                                     (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1575                                     "b", arm_cond_names[cc], arm_reg_names[rd],
1576                                     arm_reg_names[rm], arm_reg_names[rs]);
1577                         } else {
1578                                 len = snprintf(buf, buflen,
1579                                     "smlaw%s%s %s, %s, %s %s",
1580                                     (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" :
1581                                     "b", arm_cond_names[cc], arm_reg_names[rd],
1582                                     arm_reg_names[rm], arm_reg_names[rs],
1583                                     arm_reg_names[rn]);
1584                         }
1585                         break;
1586                 case 2:
1587                         len = snprintf(buf, buflen,
1588                             "smlal%s%s%s %s, %s, %s, %s",
1589                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1590                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1591                             arm_cond_names[cc], arm_reg_names[rd],
1592                             arm_reg_names[rn], arm_reg_names[rm],
1593                             arm_reg_names[rs]);
1594                         break;
1595                 case 3:
1596                         len = snprintf(buf, buflen, "smul%s%s%s %s, %s, %s",
1597                             (in & ARM_CDSP_SMUL_X_MASK) != 0 ? "t" : "b",
1598                             (in & ARM_CDSP_SMUL_Y_MASK) != 0 ? "t" : "b",
1599                             arm_cond_names[cc], arm_reg_names[rd],
1600                             arm_reg_names[rm], arm_reg_names[rs]);
1601                         break;
1602                 default:
1603                         return (-1);
1604                 }
1605                 return (len >= buflen ? -1 : 0);
1606         }
1607 
1608         /*
1609          * If we got here then this is some other instructin we don't know
1610          * about in the instruction extensino space.
1611          */
1612         return (-1);
1613 }
1614 
1615 /*
1616  * Coprocessor double register transfers
1617  *
1618  * MCRR:
1619  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11-8|7-4|3-0
1620  * [ cond |1 1 0| 0| 0| 1| 0| 0| Rn  |  Rd |cp #|op |CRm
1621  *
1622  * MRRC:
1623  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11-8|7-4|3-0
1624  * [ cond |1 1 0| 0| 0| 1| 0| 1| Rn  |  Rd |cp #|op |CRm
1625  *
1626  */
1627 static int
1628 arm_dis_coproc_drt(uint32_t in, char *buf, size_t buflen)
1629 {
1630         arm_cond_code_t cc;
1631         arm_reg_t rd, rn, rm;
1632         uint8_t coproc, op;
1633         const char *ccn;
1634         size_t len;
1635 
1636         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1637         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1638         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1639         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1640         rm = in & ARM_COPROC_RM_MASK;
1641         op = (in & ARM_COPROC_DRT_OP_MASK) >> ARM_COPROC_DRT_OP_SHIFT;
1642 
1643         if (cc == ARM_COND_NACC)
1644                 ccn = "2";
1645         else
1646                 ccn = arm_cond_names[cc];
1647 
1648         len = snprintf(buf, buflen, "%s%s %s, #%d, %s, %s, c%s",
1649             (in & ARM_COPROC_DRT_DIR_MASK) != 0 ? "mrrc" : "mcrr",
1650             ccn, arm_coproc_names[coproc], op, arm_reg_names[rd],
1651             arm_reg_names[rn], arm_reg_names[rm]);
1652         return (len >= buflen ? -1 : 0);
1653 }
1654 
1655 /*
1656  * This serves as both the entry point for the normal load and stores as well as
1657  * the double register transfers (MCRR and MRCC). If it is a register transfer
1658  * then we quickly send it off.
1659  * LDC:
1660  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1661  * [ cond |1 1 0| P| U| N| W| L| Rn  | CRd | cp # | off ]
1662  *
1663  * STC:
1664  * 31 - 28|27-25|24|23|22|21|20|19-16|15-12|11 - 8|7 - 0
1665  * [ cond |1 1 0| P| U| N| W| L| Rn  | CRd | cp # | off ]
1666  *
1667  * Here the bits mean:
1668  *
1669  * P bit: If P is zero, it is post-indexed or unindexed based on W. If P is 1
1670  * then it is offset-addressing or pre-indexed based on W again.
1671  *
1672  * U bit: If U is positive then the offset if added, subtracted otherwise.. Note
1673  * that if P is zero and W is zero, U must be one.
1674  *
1675  * N bit: If set that means that we have a Long size, this bit is set by the L
1676  * suffix, not to be confused with the L bit.
1677  *
1678  * W bit: If W is one then the memory address is written back to the base
1679  * register. Further W = 0 and P = 0 is unindexed addressing. W = 1, P = 0 is
1680  * post-indexed. W = 0, P = 1 is offset addressing and W = 1, P = 1 is
1681  * pre-indexed.
1682  */
1683 static int
1684 arm_dis_coproc_lsdrt(uint32_t in, char *buf, size_t buflen)
1685 {
1686         arm_cond_code_t cc;
1687         arm_reg_t rn, rd;
1688         uint8_t coproc;
1689         uint32_t imm;
1690         int pbit, ubit, nbit, wbit, lbit;
1691         const char *ccn;
1692         size_t len;
1693 
1694         if ((in & ARM_COPROC_DRT_MASK) == ARM_COPROC_DRT_TARG)
1695                 return (arm_dis_coproc_drt(in, buf, buflen));
1696 
1697         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1698         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1699         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1700         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1701         imm = in & ARM_COPROC_LS_IMM_MASK;
1702 
1703         pbit = in & ARM_COPROC_LS_P_MASK;
1704         ubit = in & ARM_COPROC_LS_U_MASK;
1705         nbit = in & ARM_COPROC_LS_N_MASK;
1706         wbit = in & ARM_COPROC_LS_W_MASK;
1707         lbit = in & ARM_COPROC_LS_L_MASK;
1708 
1709         if (cc == ARM_COND_NACC)
1710                 ccn = "2";
1711         else
1712                 ccn = arm_cond_names[cc];
1713 
1714         len = snprintf(buf, buflen, "%s%s%s %s, c%s, ",
1715             lbit != 0 ? "ldc" : "stc", ccn, nbit != 0 ? "l" : "",
1716             arm_coproc_names[coproc], arm_reg_names[rd]);
1717         if (len >= buflen)
1718                 return (-1);
1719 
1720         if (pbit != 0) {
1721                 imm *= 4;
1722                 len += snprintf(buf + len, buflen - len, "[%s, #%s%d]%s",
1723                     arm_reg_names[rn],
1724                     ubit != 0 ? "" : "-", imm,
1725                     wbit != 0 ? "!" : "");
1726         } else if (wbit != 0) {
1727                 imm *= 4;
1728                 len += snprintf(buf + len, buflen - len, "[%s], #%s%d",
1729                     arm_reg_names[rn], ubit != 0 ? "" : "-", imm);
1730         } else {
1731                 len += snprintf(buf + len, buflen - len, "[%s], { %d }",
1732                     arm_reg_names[rn], imm);
1733         }
1734         return (len >= buflen ? -1 : 0);
1735 }
1736 
1737 /*
1738  * Here we tell a coprocessor to do data processing
1739  *
1740  * CDP:
1741  * 31 - 28|27 - 24|23-20|19-16|15-12|11 - 8|7 - 5|4|3-0
1742  * [ cond |1 1 1 0| op_1| CRn | CRd | cp # | op_2|0|CRm ]
1743  */
1744 static int
1745 arm_dis_coproc_dp(uint32_t in, char *buf, size_t buflen)
1746 {
1747         arm_cond_code_t cc;
1748         arm_reg_t rn, rd, rm;
1749         uint8_t op1, op2, coproc;
1750         const char *ccn;
1751 
1752         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1753         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1754         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1755         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1756         rm = in & ARM_COPROC_RM_MASK;
1757         op1 = (in & ARM_COPROC_CDP_OP1_MASK) >> ARM_COPROC_CDP_OP1_SHIFT;
1758         op2 = (in & ARM_COPROC_CDP_OP2_MASK) >> ARM_COPROC_CDP_OP2_SHIFT;
1759 
1760         /*
1761          * This instruction is valid with the undefined condition code. When it
1762          * does that, the instruction is intead CDP2 as opposed to CDP.
1763          */
1764         if (cc == ARM_COND_NACC)
1765                 ccn = "2";
1766         else
1767                 ccn = arm_cond_names[cc];
1768 
1769         if (snprintf(buf, buflen, "cdp%s %s, #%d, c%s, c%s, c%s, #%d", ccn,
1770             arm_coproc_names[coproc], op1, arm_reg_names[rd],
1771             arm_reg_names[rn], arm_reg_names[rm], op2) >= buflen)
1772                 return (-1);
1773 
1774         return (0);
1775 }
1776 
1777 /*
1778  * Here we handle coprocesser single register transfers.
1779  *
1780  * MCR:
1781  * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1782  * [ cond |1 1 1 0| op_1| 0| CRn |  Rd | cp # | op_2|1|CRm ]
1783  *
1784  * MRC:
1785  * 31 - 28|27 - 24|23-21|20|19-16|15-12|11 - 8|7 - 5|4|3-0
1786  * [ cond |1 1 1 0| op_1| 1| CRn |  Rd | cp # | op_2|1|CRm ]
1787  */
1788 static int
1789 arm_dis_coproc_rt(uint32_t in, char *buf, size_t buflen)
1790 {
1791         arm_cond_code_t cc;
1792         arm_reg_t rn, rd, rm;
1793         uint8_t op1, op2, coproc;
1794         const char *ccn;
1795         size_t len;
1796 
1797         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1798         coproc = (in & ARM_COPROC_NUM_MASK) >> ARM_COPROC_NUM_SHIFT;
1799         rn = (in & ARM_COPROC_RN_MASK) >> ARM_COPROC_RN_SHIFT;
1800         rd = (in & ARM_COPROC_RD_MASK) >> ARM_COPROC_RD_SHIFT;
1801         rm = in & ARM_COPROC_RM_MASK;
1802         op1 = (in & ARM_COPROC_CRT_OP1_MASK) >> ARM_COPROC_CRT_OP1_SHIFT;
1803         op2 = (in & ARM_COPROC_CRT_OP2_MASK) >> ARM_COPROC_CRT_OP2_SHIFT;
1804 
1805         if (cc == ARM_COND_NACC)
1806                 ccn = "2";
1807         else
1808                 ccn = arm_cond_names[cc];
1809 
1810         len = snprintf(buf, buflen, "%s%s %s, #%d, %s, c%s, c%s",
1811             (in & ARM_COPROC_CRT_DIR_MASK) != 0 ? "mrc" : "mcr", ccn,
1812             arm_coproc_names[coproc], op1, arm_reg_names[rd],
1813             arm_reg_names[rn], arm_reg_names[rm]);
1814         if (len >= buflen)
1815                 return (-1);
1816 
1817         if (op2 != 0)
1818                 if (snprintf(buf + len, buflen - len, ", #%d", op2) >=
1819                     buflen - len)
1820                         return (-1);
1821         return (0);
1822 }
1823 
1824 /*
1825  * Here we handle the set of unconditional instructions.
1826  */
1827 static int
1828 arm_dis_uncond_insn(uint32_t in, char *buf, size_t buflen)
1829 {
1830         int imm, sc;
1831         arm_reg_t rn, rm;
1832         size_t len;
1833 
1834         /*
1835          * The CPS instruction is a bit complicated. It has the following big
1836          * pattern which maps to a few different ways to use it:
1837          *
1838          *
1839          * 31-28|27-25|24|23-20|19-18|17 |16|15-9|8|7|6|5|4-0
1840          *    1 |  0  | 1| 0   |imod|mmod| 0|SBZ |A|I|F|0|mode
1841          *
1842          * CPS<effect> <iflags> {, #<mode> }
1843          * CPS #<mode>
1844          *
1845          * effect: determines what to do with the A, I, F interrupt bits in the
1846          * CPSR. effect is encoded in the imod field. It is either enable
1847          * interrupts 0b10 or disable interrupts 0b11. Recall that interrupts
1848          * are active low in the CPSR. If effect is not specified then this is
1849          * strictly a mode change which is required.
1850          *
1851          * A, I, F: If effect is specified then the bits which are high are
1852          * modified by the instruction.
1853          *
1854          * mode: Specifies a mode to change to. mmod will be 1 if mode is set.
1855          *
1856          */
1857         if ((in & ARM_UNI_CPS_MASK) == ARM_UNI_CPS_TARG) {
1858                 imm = (in & ARM_UNI_CPS_IMOD_MASK) > ARM_UNI_CPS_IMOD_SHIFT;
1859 
1860                 /* Ob01 is not a valid value for the imod */
1861                 if (imm == 1)
1862                         return (-1);
1863 
1864                 if (imm != 0)
1865                         len = snprintf(buf, buflen, "cps%s %s%s%s%s",
1866                             imm == 2 ? "ie" : "id",
1867                             (in & ARM_UNI_CPS_A_MASK) ? "a" : "",
1868                             (in & ARM_UNI_CPS_I_MASK) ? "i" : "",
1869                             (in & ARM_UNI_CPS_F_MASK) ? "f" : "",
1870                             (in & ARM_UNI_CPS_MMOD_MASK) ? " ," : "");
1871                 else
1872                         len = snprintf(buf, buflen, "cps ");
1873                 if (len >= buflen)
1874                         return (-1);
1875 
1876                 if (in & ARM_UNI_CPS_MMOD_MASK)
1877                         if (snprintf(buf + len, buflen - len, "#%d",
1878                             in & ARM_UNI_CPS_MODE_MASK) >= buflen - len)
1879                                 return (-1);
1880                 return (0);
1881         }
1882 
1883         if ((in & ARM_UNI_SE_MASK) == ARM_UNI_SE_TARG) {
1884                 if (snprintf(buf, buflen, "SETEND %s",
1885                     (in & ARM_UNI_SE_BE_MASK) ? "be" : "le") >= buflen)
1886                         return (-1);
1887                 return (0);
1888         }
1889 
1890         /*
1891          * The cache preload is like a load, but it has a much simpler set of
1892          * constraints. The only valid bits that you can transform are the I and
1893          * the U bits. We have to use pre-indexed addressing. This means that we
1894          * only have the U bit and the I bit. See arm_dis_ldstr for a full
1895          * explanation of what's happening here.
1896          */
1897         if ((in & ARM_UNI_PLD_MASK) == ARM_UNI_PLD_TARG) {
1898                 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1899                 if ((in & ARM_LS_IBIT_MASK) == 0) {
1900                         if (snprintf(buf, buflen, "pld [%s, #%s%d",
1901                             arm_reg_names[rn],
1902                             (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1903                             in & ARM_LS_IMM_MASK) >= buflen)
1904                                 return (-1);
1905                         return (0);
1906                 }
1907 
1908                 rm = in & ARM_LS_REG_RM_MASK;
1909                 len = snprintf(buf, buflen, "pld [%s, %s%s", arm_reg_names[rn],
1910                     (in & ARM_LS_UBIT_MASK) != 0 ? "" : "-",
1911                     arm_reg_names[rm]);
1912                 if (len >= buflen)
1913                         return (-1);
1914 
1915                 if ((in & ARM_LS_REG_NRM_MASK) != 0) {
1916                         imm = (in & ARM_LS_SCR_SIMM_MASK) >>
1917                             ARM_LS_SCR_SIMM_SHIFT;
1918                         sc = (in & ARM_LS_SCR_SCODE_MASK) >>
1919                             ARM_LS_SCR_SCODE_SHIFT;
1920 
1921                         if (imm == 0 && sc == DPI_S_ROR)
1922                                 sc = DPI_S_RRX;
1923 
1924                         len += snprintf(buf + len, buflen - len, "%s",
1925                             arm_dpi_shifts[sc]);
1926                         if (len >= buflen)
1927                                 return (-1);
1928                         if (sc != DPI_S_RRX) {
1929                                 len += snprintf(buf + len, buflen - len,
1930                                     " #%d", imm);
1931                                 if (len >= buflen)
1932                                         return (-1);
1933                         }
1934                 }
1935                 if (snprintf(buf + len, buflen - len, "]") >= buflen - len)
1936                         return (-1);
1937                 return (0);
1938         }
1939 
1940         /*
1941          * This is a special case of STM, but it works across chip modes.
1942          */
1943         if ((in & ARM_UNI_SRS_MASK) == ARM_UNI_SRS_TARG) {
1944                 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1945                 if (snprintf(buf, buflen, "srs%s #%d%s",
1946                     arm_lsm_mode_names[imm],
1947                     in & ARM_UNI_SRS_MODE_MASK,
1948                     (in & ARM_UNI_SRS_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1949                         return (-1);
1950                 return (0);
1951         }
1952 
1953         /*
1954          * RFE is a return from exception instruction that is similar to the LDM
1955          * and STM, but a bit different.
1956          */
1957         if ((in & ARM_UNI_RFE_MASK) == ARM_UNI_RFE_TARG) {
1958                 imm = (in & ARM_LSM_ADDR_MASK) >> ARM_LSM_ADDR_SHIFT;
1959                 rn = (in & ARM_LS_RN_MASK) >> ARM_LS_RN_SHIFT;
1960                 if (snprintf(buf, buflen, "rfe%s %s%s", arm_lsm_mode_names[imm],
1961                     arm_reg_names[rn],
1962                     (in & ARM_UNI_RFE_WBIT_MASK) != 0 ? "!" : "") >= buflen)
1963                         return (-1);
1964                 return (0);
1965         }
1966 
1967         if ((in & ARM_UNI_BLX_MASK) == ARM_UNI_BLX_TARG) {
1968                 if (snprintf(buf, buflen, "blx %d",
1969                     in & ARM_UNI_BLX_IMM_MASK) >= buflen)
1970                         return (-1);
1971                 return (0);
1972         }
1973 
1974         if ((in & ARM_UNI_CODRT_MASK) == ARM_UNI_CODRT_TARG) {
1975                 return (arm_dis_coproc_lsdrt(in, buf, buflen));
1976         }
1977 
1978         if ((in & ARM_UNI_CORT_MASK) == ARM_UNI_CORT_TARG) {
1979                 return (arm_dis_coproc_rt(in, buf, buflen));
1980         }
1981 
1982         if ((in & ARM_UNI_CODP_MASK) == ARM_UNI_CORT_TARG) {
1983                 return (arm_dis_coproc_dp(in, buf, buflen));
1984         }
1985 
1986         /*
1987          * An undefined or illegal instruction
1988          */
1989         return (-1);
1990 }
1991 
1992 /*
1993  * Disassemble B and BL instructions. The instruction is given a 24-bit two's
1994  * complement value as an offset address. This value gets sign extended to 30
1995  * bits and then shifted over two bits. This is then added to the PC + 8. So,
1996  * instead of dispalying an absolute address, we're going to display the delta
1997  * that the instruction has instead.
1998  */
1999 static int
2000 arm_dis_branch(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
2001 {
2002         uint32_t addr;
2003         arm_cond_code_t cc;
2004         size_t len;
2005 
2006         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2007         addr = in & ARM_BRANCH_IMM_MASK;
2008         if (in & ARM_BRANCH_SIGN_MASK)
2009                 addr |= ARM_BRANCH_NEG_SIGN;
2010         else
2011                 addr &= ARM_BRANCH_POS_SIGN;
2012         addr <<= 2;
2013         if ((len = snprintf(buf, buflen, "b%s%s %d",
2014             (in & ARM_BRANCH_LBIT_MASK) != 0 ? "l" : "",
2015             arm_cond_names[cc], (int)addr)) >= buflen)
2016                 return (-1);
2017 
2018         /* Per the ARM manuals, we have to account for the extra 8 bytes here */
2019         if (dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8, NULL, 0,
2020             NULL, NULL) == 0) {
2021                 len += snprintf(buf + len, buflen - len, "\t<");
2022                 if (len >= buflen)
2023                         return (-1);
2024                 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int)addr + 8,
2025                     buf + len, buflen - len, NULL, NULL);
2026                 strlcat(buf, ">", buflen);
2027         }
2028 
2029         return (0);
2030 }
2031 
2032 /*
2033  * There are six instructions that are covered here: ADD16, ADDSUBX, SUBADDX,
2034  * SUB16, ADD8, and SUB8. They can hae the following variations: S, Q, SH, U,
2035  * UQ, and UH. It has two differnt sets of bits to determine the opcode: 22-20
2036  * and then 7-5.
2037  *
2038  * These instructions have the general form of:
2039  *
2040  * 31 - 28|27-25|24|23|22-20|19-16|15-12|11 - 8|7-5|4|3-0
2041  * [ cond |0 1 1| 0| 0| opP |Rn   |Rd   |SBO   |opI|1|Rm ]
2042  *
2043  * Here we use opP to refer to the prefix of the instruction, eg. S, Q, etc.
2044  * Where as opI refers to which instruction it is, eg. ADD16, ADD8, etc. We use
2045  * string tables for both of these in arm_padd_p_names and arm_padd_i_names. If
2046  * there is an empty entry that means that the instruction in question doesn't
2047  * exist.
2048  */
2049 static int
2050 arm_dis_padd(uint32_t in, char *buf, size_t buflen)
2051 {
2052         arm_reg_t rn, rd, rm;
2053         arm_cond_code_t cc;
2054         uint8_t opp, opi;
2055         const char *pstr, *istr;
2056 
2057         opp = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2058         opi = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2059 
2060         pstr = arm_padd_p_names[opp];
2061         istr = arm_padd_i_names[opi];
2062 
2063         if (pstr == NULL || istr == NULL)
2064                 return (-1);
2065 
2066         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2067         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2068         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2069         rm = in & ARM_MEDIA_RM_MASK;
2070 
2071         if (snprintf(buf, buflen, "%s%%s %s, %s, %s", pstr, istr,
2072             arm_cond_names[cc], arm_reg_names[rd], arm_reg_names[rn],
2073             arm_reg_names[rm]) >= buflen)
2074                 return (-1);
2075         return (0);
2076 }
2077 
2078 /*
2079  * Disassemble the extend instructions from ARMv6. There are six instructions:
2080  *
2081  * XTAB16, XTAB, XTAH, XTB16, XTB, XTFH. These can exist with one of the
2082  * following prefixes: S, U. The opcode exists in bits 22-20. We have the
2083  * following rules from there:
2084  *
2085  * If bit 22 is one then we are using the U prefix, otherwise the S prefix. Then
2086  * we have the following opcode maps in the lower two bits:
2087  * XTAB16       00 iff Rn != 0xf
2088  * XTAB         10 iff Rn != 0xf
2089  * XTAH         11 iff Rn != 0xf
2090  * XTB16        00 iff Rn = 0xf
2091  * XTB          10 iff Rn = 0xf
2092  * XTH          11 iff Rn = 0xf
2093  */
2094 static int
2095 arm_dis_extend(uint32_t in, char *buf, size_t buflen)
2096 {
2097         uint8_t op, rot;
2098         int sbit;
2099         arm_cond_code_t cc;
2100         arm_reg_t rn, rm, rd;
2101         const char *opn;
2102         size_t len;
2103 
2104 
2105         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2106         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2107         rm = in & ARM_MEDIA_RM_MASK;
2108         op = (in & ARM_MEDIA_SZE_OP_MASK) >> ARM_MEDIA_SZE_OP_SHIFT;
2109         rot = (in & ARM_MEDIA_SZE_ROT_MASK) >> ARM_MEDIA_SZE_ROT_SHIFT;
2110         sbit = in & ARM_MEDIA_SZE_S_MASK;
2111         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2112 
2113         switch (op) {
2114         case 0x0:
2115                 opn = rn == ARM_REG_R15 ? "xtab16" : "xtb16";
2116                 break;
2117         case 0x2:
2118                 opn = rn == ARM_REG_R15 ? "xtab" : "xtb";
2119                 break;
2120         case 0x3:
2121                 opn = rn == ARM_REG_R15 ? "xtah" : "xth";
2122                 break;
2123         default:
2124                 return (-1);
2125                 break;
2126         }
2127 
2128         if (rn == ARM_REG_R15) {
2129                 len = snprintf(buf, buflen, "%s%s%s %s, %s",
2130                     sbit != 0 ? "u" : "s",
2131                     opn, arm_cond_names[cc], arm_reg_names[rd],
2132                     arm_reg_names[rn]);
2133         } else {
2134                 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2135                     sbit != 0 ? "u" : "s",
2136                     opn, arm_cond_names[cc], arm_reg_names[rd],
2137                     arm_reg_names[rn], arm_reg_names[rm]);
2138         }
2139 
2140         if (len >= buflen)
2141                 return (-1);
2142 
2143         if (snprintf(buf + len, buflen - len, "%s",
2144             arm_extend_rot_names[rot]) >= buflen - len)
2145                 return (-1);
2146         return (0);
2147 }
2148 
2149 /*
2150  * The media instructions and extensions can be divided into different groups of
2151  * instructions. We first use bits 23 and 24 to figure out where to send it. We
2152  * call this group of bits the l1 mask.
2153  */
2154 static int
2155 arm_dis_media(uint32_t in, char *buf, size_t buflen)
2156 {
2157         uint8_t l1, op1, op2;
2158         arm_cond_code_t cc;
2159         arm_reg_t rd, rn, rs, rm;
2160         int xbit;
2161         size_t len;
2162 
2163         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2164         l1 = (in & ARM_MEDIA_L1_MASK) >> ARM_MEDIA_L1_SHIFT;
2165         switch (l1) {
2166         case 0x0:
2167                 return (arm_dis_padd(in, buf, buflen));
2168                 break;
2169         case 0x1:
2170                 if ((in & ARM_MEDIA_HPACK_MASK) == ARM_MEDIA_HPACK_TARG) {
2171                         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2172                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2173                         rm = in & ARM_MEDIA_RM_MASK;
2174                         op1 = (in & ARM_MEDIA_HPACK_SHIFT_MASK) >>
2175                             ARM_MEDIA_HPACK_SHIFT_IMM;
2176                         len = snprintf(buf, buflen, "%s%s %s, %s, %s",
2177                             (in & ARM_MEDIA_HPACK_OP_MASK) != 0 ?
2178                             "pkhtb" : "pkhbt", arm_cond_names[cc],
2179                             arm_reg_names[rd], arm_reg_names[rn],
2180                             arm_reg_names[rd]);
2181                         if (len >= buflen)
2182                                 return (-1);
2183 
2184                         if (op1 != 0) {
2185                                 if (in & ARM_MEDIA_HPACK_OP_MASK)
2186                                         len += snprintf(buf + len, buflen - len,
2187                                             ", asr %d", op1);
2188                                 else
2189                                         len += snprintf(buf + len, buflen - len,
2190                                             ", lsl %d", op1);
2191                         }
2192                         return (len >= buflen ? -1 : 0);
2193                 }
2194 
2195                 if ((in & ARM_MEDIA_WSAT_MASK) == ARM_MEDIA_WSAT_TARG) {
2196                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2197                         rm = in & ARM_MEDIA_RM_MASK;
2198                         op1 = (in & ARM_MEDIA_SAT_IMM_MASK) >>
2199                             ARM_MEDIA_SAT_IMM_SHIFT;
2200                         op2 = (in & ARM_MEDIA_SAT_SHI_MASK) >>
2201                             ARM_MEDIA_SAT_SHI_SHIFT;
2202                         len = snprintf(buf, buflen, "%s%s %s, #%d, %s",
2203                             (in & ARM_MEDIA_SAT_U_MASK) != 0 ? "usat" : "ssat",
2204                             arm_cond_names[cc], arm_reg_names[rd], op1,
2205                             arm_reg_names[rm]);
2206 
2207                         if (len >= buflen)
2208                                 return (-1);
2209 
2210                         /*
2211                          * The shift is optional in the assembler and encoded as
2212                          * LSL 0. However if we get ASR 0, that means ASR #32.
2213                          * An ARM_MEDIA_SAT_STYPE_MASK of 0 is LSL, 1 is ASR.
2214                          */
2215                         if (op2 != 0 || (in & ARM_MEDIA_SAT_STYPE_MASK) == 1) {
2216                                 if (op2 == 0)
2217                                         op2 = 32;
2218                                 if (snprintf(buf + len, buflen - len,
2219                                     ", %s #%d",
2220                                     (in & ARM_MEDIA_SAT_STYPE_MASK) != 0 ?
2221                                     "asr" : "lsl", op2) >= buflen - len)
2222                                         return (-1);
2223                         }
2224                         return (0);
2225                 }
2226 
2227                 if ((in & ARM_MEDIA_PHSAT_MASK) == ARM_MEDIA_PHSAT_TARG) {
2228                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2229                         rm = in & ARM_MEDIA_RM_MASK;
2230                         op1 = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2231                         if (snprintf(buf, buflen, "%s%s %s, #%d, %s",
2232                             (in & ARM_MEDIA_SAT_U_MASK) != 0 ?
2233                             "usat16" : "ssat16",
2234                             arm_cond_names[cc], arm_reg_names[rd], op1,
2235                             arm_reg_names[rm]) >= buflen)
2236                                 return (-1);
2237                         return (0);
2238                 }
2239 
2240                 if ((in & ARM_MEDIA_REV_MASK) == ARM_MEDIA_REV_TARG) {
2241                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2242                         rm = in & ARM_MEDIA_RM_MASK;
2243                         if (snprintf(buf, buflen, "rev%s %s, %s",
2244                             arm_cond_names[cc], arm_reg_names[rd],
2245                             arm_reg_names[rd]) >= buflen)
2246                                 return (-1);
2247                         return (0);
2248                 }
2249 
2250                 if ((in & ARM_MEDIA_BRPH_MASK) == ARM_MEDIA_BRPH_TARG) {
2251                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2252                         rm = in & ARM_MEDIA_RM_MASK;
2253                         if (snprintf(buf, buflen, "rev16%s %s, %s",
2254                             arm_cond_names[cc], arm_reg_names[rd],
2255                             arm_reg_names[rd]) >= buflen)
2256                                 return (-1);
2257                         return (0);
2258                 }
2259 
2260                 if ((in & ARM_MEDIA_BRSH_MASK) == ARM_MEDIA_BRSH_TARG) {
2261                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2262                         rm = in & ARM_MEDIA_RM_MASK;
2263                         if (snprintf(buf, buflen, "revsh%s %s, %s",
2264                             arm_cond_names[cc], arm_reg_names[rd],
2265                             arm_reg_names[rd]) >= buflen)
2266                                 return (-1);
2267                         return (0);
2268                 }
2269 
2270                 if ((in & ARM_MEDIA_SEL_MASK) == ARM_MEDIA_SEL_TARG) {
2271                         rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2272                         rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2273                         rm = in & ARM_MEDIA_RM_MASK;
2274                         if (snprintf(buf, buflen, "sel%s %s, %s, %s",
2275                             arm_cond_names[cc], arm_reg_names[rd],
2276                             arm_reg_names[rn], arm_reg_names[rm]) >= buflen)
2277                                 return (-1);
2278                         return (0);
2279                 }
2280 
2281                 if ((in & ARM_MEDIA_SZE_MASK) == ARM_MEDIA_SZE_TARG)
2282                         return (arm_dis_extend(in, buf, buflen));
2283                 /* Unknown instruction */
2284                 return (-1);
2285                 break;
2286         case 0x2:
2287                 /*
2288                  * This consists of the following multiply instructions:
2289                  * SMLAD, SMLSD, SMLALD, SMUAD, and SMUSD.
2290                  *
2291                  * SMLAD and SMUAD encoding are the same, switch on Rn == R15
2292                  * 22-20 are 000 7-6 are 00
2293                  * SMLSD and SMUSD encoding are the same, switch on Rn == R15
2294                  * 22-20 are 000 7-6 are 01
2295                  * SMLALD: 22-20 are 100 7-6 are 00
2296                  */
2297                 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2298                 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2299                 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2300                 rm = in & ARM_MEDIA_RM_MASK;
2301                 op1 = (in & ARM_MEDIA_OP1_MASK) >> ARM_MEDIA_OP1_SHIFT;
2302                 op2 = (in & ARM_MEDIA_OP2_MASK) >> ARM_MEDIA_OP2_SHIFT;
2303                 xbit = in & ARM_MEDIA_MULT_X_MASK;
2304 
2305                 if (op1 == 0x0) {
2306                         if (op2 != 0x0 && op2 != 0x1)
2307                                 return (-1);
2308                         if (rn == ARM_REG_R15) {
2309                                 len = snprintf(buf, buflen, "%s%s%s %s, %s, %s",
2310                                     op2 != 0 ? "smusd" : "smuad",
2311                                     xbit != 0 ? "x" : "x",
2312                                     arm_cond_names[cc], arm_reg_names[rd],
2313                                     arm_reg_names[rm], arm_reg_names[rs]);
2314                         } else {
2315                                 len = snprintf(buf, buflen,
2316                                     "%s%s%s %s, %s, %s, %s",
2317                                     op2 != 0 ? "smlsd" : "smlad",
2318                                     xbit != 0 ? "x" : "",
2319                                     arm_cond_names[cc], arm_reg_names[rd],
2320                                     arm_reg_names[rm], arm_reg_names[rs],
2321                                     arm_reg_names[rn]);
2322 
2323                         }
2324                 } else if (op1 == 0x8) {
2325                         if (op2 != 0x0)
2326                                 return (-1);
2327                         len = snprintf(buf, buflen, "smlald%s%s %s, %s, %s, %s",
2328                             xbit != 0 ? "x" : "",
2329                             arm_cond_names[cc], arm_reg_names[rn],
2330                             arm_reg_names[rd], arm_reg_names[rm],
2331                             arm_reg_names[rs]);
2332                 } else
2333                         return (-1);
2334 
2335                 return (len >= buflen ? -1 : 0);
2336                 break;
2337         case 0x3:
2338                 /*
2339                  * Here we handle USAD8 and USADA8. The main difference is the
2340                  * presence of RN. USAD8 is defined as having a value of rn that
2341                  * is not r15. If it is r15, then instead it is USADA8.
2342                  */
2343                 if ((in & ARM_MEDIA_OP1_MASK) != 0)
2344                         return (-1);
2345                 if ((in & ARM_MEDIA_OP2_MASK) != 0)
2346                         return (-1);
2347 
2348                 cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2349                 rn = (in & ARM_MEDIA_RN_MASK) >> ARM_MEDIA_RN_SHIFT;
2350                 rd = (in & ARM_MEDIA_RD_MASK) >> ARM_MEDIA_RD_SHIFT;
2351                 rs = (in & ARM_MEDIA_RS_MASK) >> ARM_MEDIA_RS_SHIFT;
2352                 rm = in & ARM_MEDIA_RM_MASK;
2353 
2354                 if (rn != ARM_REG_R15)
2355                         len = snprintf(buf, buflen, "usada8%s %s, %s, %s, %s",
2356                             arm_cond_names[cc], arm_reg_names[rd],
2357                             arm_reg_names[rm], arm_reg_names[rs],
2358                             arm_reg_names[rn]);
2359                 else
2360                         len = snprintf(buf, buflen, "usad8%s %s, %s, %s",
2361                             arm_cond_names[cc], arm_reg_names[rd],
2362                             arm_reg_names[rm], arm_reg_names[rs]);
2363                 return (len >= buflen ? -1 : 0);
2364                 break;
2365         default:
2366                 return (-1);
2367         }
2368 }
2369 
2370 /*
2371  * Each instruction in the ARM instruction set is a uint32_t and in our case is
2372  * LE. The upper four bits determine the condition code. If the conditoin code
2373  * is undefined then we know to immediately jump there. Otherwise we go use the
2374  * next three bits to determine where we should go next and how to further
2375  * process the instruction in question. The ARM instruction manual doesn't
2376  * define this field so we're going to call it the L1_DEC or level 1 decoding
2377  * from which it will have to be further subdivided into the specific
2378  * instruction groupings that we care about.
2379  */
2380 static int
2381 arm_dis(dis_handle_t *dhp, uint32_t in, char *buf, size_t buflen)
2382 {
2383         uint8_t l1;
2384         arm_cond_code_t cc;
2385 
2386         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
2387 
2388         if (cc == ARM_COND_NACC)
2389                 return (arm_dis_uncond_insn(in, buf, buflen));
2390 
2391         l1 = (in & ARM_L1_DEC_MASK) >> ARM_L1_DEC_SHIFT;
2392 
2393         switch (l1) {
2394         case 0x0:
2395                 /*
2396                  * The l0 group is a bit complicated. We have several different
2397                  * groups of instructions to consider. The first question is
2398                  * whether bit 4 is zero or not. If it is, then we have a data
2399                  * processing immediate shift unless the opcode and + S bits
2400                  * (24-20) is of the form 0b10xx0.
2401                  *
2402                  * When bit 4 is 1, we have to then also look at bit 7. If bit
2403                  * 7 is one then we know that this is the class of multiplies /
2404                  * extra load/stores. If bit 7 is zero then we have the same
2405                  * opcode games as we did above.
2406                  */
2407                 if (in & ARM_L1_0_B4_MASK) {
2408                         if (in & ARM_L1_0_B7_MASK) {
2409                                 /*
2410                                  * Both the multiplication extensions and the
2411                                  * load and store extensions live in this
2412                                  * region. The load and store extensions can be
2413                                  * identified by having at least one of bits 5
2414                                  * and 6 set. The exceptions to this are the
2415                                  * SWP and SWPB instructions and the exclusive
2416                                  * load and store instructions which, unlike the
2417                                  * multiplication instructions. These have
2418                                  * specific values for the bits in the range of
2419                                  * 20-24.
2420                                  */
2421                                 if ((in & ARM_L1_0_ELS_MASK) != 0)
2422                                         /* Extra loads/stores */
2423                                         return (arm_dis_els(in, buf, buflen));
2424                                 if ((in & ARM_ELS_SWAP_MASK) == ARM_ELS_IS_SWAP)
2425                                         return (arm_dis_swap(in, buf, buflen));
2426                                 if ((in & ARM_ELS_EXCL_MASK) ==
2427                                     ARM_ELS_EXCL_MASK)
2428                                         return (arm_dis_lsexcl(in, buf,
2429                                             buflen));
2430                                 /* Multiplication instruction extension A3-3. */
2431                                 return (arm_dis_extmul(in, buf, buflen));
2432                         }
2433                         if ((in & ARM_L1_0_OPMASK) == ARM_L1_0_SPECOP &&
2434                             !(in & ARM_L1_0_SMASK)) {
2435                                 /* Misc. Instructions A3-4 */
2436                                 return (arm_dis_cdsp_ext(in, buf, buflen));
2437                         } else {
2438                                 /* data processing register shift */
2439                                 return (arm_dis_dpi(in, cc, buf, buflen));
2440                         }
2441                 } else {
2442                         if ((in & ARM_L1_0_OPMASK) == ARM_L1_0_SPECOP &&
2443                             !(in & ARM_L1_0_SMASK))
2444                                 /* Misc. Instructions A3-4 */
2445                                 return (arm_dis_cdsp_ext(in, buf, buflen));
2446                         else {
2447                                 /* Data processing immediate shift */
2448                                 return (arm_dis_dpi(in, cc, buf, buflen));
2449                         }
2450                 }
2451                 break;
2452         case 0x1:
2453                 /*
2454                  * In l1 group 0b001 there are a few ways to tell things apart.
2455                  * We are directed to first look at bits 20-24. Data processing
2456                  * immediate has a 4 bit opcode 24-21 followed by an S bit. We
2457                  * know it is not a data processing immediate if we have
2458                  * something of the form 0b10xx0.
2459                  */
2460                 if ((in & ARM_L1_1_OPMASK) == ARM_L1_1_SPECOP &&
2461                     !(in & ARM_L1_1_SMASK)) {
2462                         if (in & ARM_L1_1_UNDEF_MASK) {
2463                                 /* Undefined instructions */
2464                                 return (-1);
2465                         } else {
2466                                 /* Move immediate to status register */
2467                                 return (arm_dis_status_regs(in, buf, buflen));
2468                         }
2469                 } else {
2470                         /* Data processing immedaite */
2471                         return (arm_dis_dpi(in, cc, buf, buflen));
2472                 }
2473                 break;
2474         case 0x2:
2475                 /* Load/store Immediate offset */
2476                 return (arm_dis_ldstr(in, buf, buflen));
2477                 break;
2478         case 0x3:
2479                 /*
2480                  * Like other sets we use the 4th bit to make an intial
2481                  * determination. If it is zero then this is a load/store
2482                  * register offset class instruction. Following that we have a
2483                  * specical mask of 0x01f000f0 to determine whether this is an
2484                  * architecturally undefined instruction type or not.
2485                  *
2486                  * The architecturally undefined are parts of the current name
2487                  * space that just aren't used, but could be used at some point
2488                  * in the future. For now though, it's an invalid op code.
2489                  */
2490                 if (in & ARM_L1_3_B4_MASK) {
2491                         if ((in & ARM_L1_3_ARCHUN_MASK) ==
2492                             ARM_L1_3_ARCHUN_MASK) {
2493                                 /* Architecturally undefined */
2494                                 return (-1);
2495                         } else {
2496                                 /* Media instructions */
2497                                 return (arm_dis_media(in, buf, buflen));
2498                         }
2499                 } else {
2500                         /* Load/store register offset */
2501                         return (arm_dis_ldstr(in, buf, buflen));
2502                 }
2503                 break;
2504         case 0x4:
2505                 /* Load/store multiple */
2506                 return (arm_dis_ldstr_multi(in, buf, buflen));
2507                 break;
2508         case 0x5:
2509                 /* Branch and Branch with link */
2510                 return (arm_dis_branch(dhp, in, buf, buflen));
2511                 break;
2512         case 0x6:
2513                 /* coprocessor load/store && double register transfers */
2514                 return (arm_dis_coproc_lsdrt(in, buf, buflen));
2515                 break;
2516         case 0x7:
2517                 /*
2518                  * In l1 group 0b111 you can determine the three groups using
2519                  * the following logic. If the next bit after the l1 group (bit
2520                  * 24) is one than you know that it is a software interrupt.
2521                  * Otherwise it is one of the coprocessor instructions.
2522                  * Furthermore you can tell apart the data processing from the
2523                  * register transfers based on bit 4. If it is zero then it is
2524                  * a data processing instruction, otherwise it is a register
2525                  * transfer.
2526                  */
2527                 if (in & ARM_L1_7_SWINTMASK) {
2528                         /*
2529                          * The software interrupt is pretty straightforward. The
2530                          * lower 24 bits are the interrupt number. It's also
2531                          * valid for it to run with a condition code.
2532                          */
2533                         if (snprintf(buf, buflen, "swi%s %d",
2534                             arm_cond_names[cc],
2535                             in & ARM_SWI_IMM_MASK) >= buflen)
2536                                 return (-1);
2537                         return (0);
2538                 } else if (in & ARM_L1_7_COPROCMASK) {
2539                         /* coprocessor register transfers */
2540                         return (arm_dis_coproc_rt(in, buf, buflen));
2541                 } else {
2542                         /* coprocessor data processing */
2543                         return (arm_dis_coproc_dp(in, buf, buflen));
2544                 }
2545                 break;
2546         }
2547 
2548         return (-1);
2549 }
2550 
2551 static int
2552 dis_arm_supports_flags(int flags)
2553 {
2554         int archflags = flags & DIS_ARCH_MASK;
2555 
2556         return (archflags == DIS_ARM);
2557 }
2558 
2559 /*ARGSUSED*/
2560 static int
2561 dis_arm_handle_attach(dis_handle_t *dhp)
2562 {
2563         return (0);
2564 }
2565 
2566 /*ARGSUSED*/
2567 static void
2568 dis_arm_handle_detach(dis_handle_t *dhp)
2569 {
2570 }
2571 
2572 static int
2573 dis_arm_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
2574 {
2575         uint32_t in;
2576 
2577         buf[0] = '\0';
2578         dhp->dh_addr = addr;
2579         if (dhp->dh_read(dhp->dh_data, addr, &in, sizeof (in)) !=
2580             sizeof (in))
2581                 return (-1);
2582 
2583         /* Translate in case we're on sparc? */
2584         in = LE_32(in);
2585 
2586         return (arm_dis(dhp, in, buf, buflen));
2587 }
2588 
2589 /*
2590  * This is simple in a non Thumb world. If and when we do enter a world where we
2591  * support thumb instructions, then this becomes far less than simple.
2592  */
2593 /*ARGSUSED*/
2594 static uint64_t
2595 dis_arm_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
2596 {
2597         if (n <= 0)
2598                 return (pc);
2599 
2600         return (pc - n*4);
2601 }
2602 
2603 /*
2604  * If and when we support thumb, then this value should probably become two.
2605  * However, it varies based on whether or not a given instruction is in thumb
2606  * mode.
2607  */
2608 /*ARGSUSED*/
2609 static int
2610 dis_arm_min_instrlen(dis_handle_t *dhp)
2611 {
2612         return (4);
2613 }
2614 
2615 /*
2616  * Regardless of thumb, this value does not change.
2617  */
2618 /*ARGSUSED*/
2619 static int
2620 dis_arm_max_instrlen(dis_handle_t *dhp)
2621 {
2622         return (4);
2623 }
2624 
2625 /* ARGSUSED */
2626 static int
2627 dis_arm_instrlen(dis_handle_t *dhp, uint64_t pc)
2628 {
2629         return (4);
2630 }
2631 
2632 dis_arch_t dis_arch_arm = {
2633         dis_arm_supports_flags,
2634         dis_arm_handle_attach,
2635         dis_arm_handle_detach,
2636         dis_arm_disassemble,
2637         dis_arm_previnstr,
2638         dis_arm_min_instrlen,
2639         dis_arm_max_instrlen,
2640         dis_arm_instrlen
2641 };