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