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