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