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