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