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