749274f3690d4f0edbb8adaab4ef6a8a2e0fdd66
[openocd.git] / src / target / arm_disassembler.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2009 by David Brownell *
8 ***************************************************************************/
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include "target.h"
15 #include "arm_disassembler.h"
16 #include <helper/log.h>
17
18 #if HAVE_CAPSTONE
19 #include <capstone.h>
20 #endif
21
22 /*
23 * This disassembler supports two main functions for OpenOCD:
24 *
25 * - Various "disassemble" commands. OpenOCD can serve as a
26 * machine-language debugger, without help from GDB.
27 *
28 * - Single stepping. Not all ARM cores support hardware single
29 * stepping. To work without that support, the debugger must
30 * be able to decode instructions to find out where to put a
31 * "next instruction" breakpoint.
32 *
33 * In addition, interpretation of ETM trace data needs some of the
34 * decoding mechanisms.
35 *
36 * At this writing (September 2009) neither function is complete.
37 *
38 * - ARM decoding
39 * * Old-style syntax (not UAL) is generally used
40 * * VFP instructions are not understood (ARMv5 and later)
41 * except as coprocessor 10/11 operations
42 * * Most ARM instructions through ARMv6 are decoded, but some
43 * of the post-ARMv4 opcodes may not be handled yet
44 * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
45 * * NEON instructions are not understood (ARMv7-A)
46 *
47 * - Thumb/Thumb2 decoding
48 * * UAL syntax should be consistently used
49 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
50 * be handled properly. Accordingly, so should the subset
51 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
52 * ARMv4T and ARMv5T.
53 * * Conditional effects of Thumb2 "IT" (if-then) instructions
54 * are not handled: the affected instructions are not shown
55 * with their now-conditional suffixes.
56 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
57 * handled (minimally for coprocessor access).
58 * * SIMD instructions, and some other Thumb2 instructions
59 * from ARMv7-A, are not understood.
60 *
61 * - ThumbEE decoding
62 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
63 * * Opcodes changed by ThumbEE mode are not handled; these
64 * instructions wrongly decode as LDM and STM.
65 *
66 * - Jazelle decoding ... no support whatsoever for Jazelle mode
67 * or decoding. ARM encourages use of the more generic ThumbEE
68 * mode, instead of Jazelle mode, in current chips.
69 *
70 * - Single-step/emulation ... spotty support, which is only weakly
71 * tested. Thumb2 is not supported. (Arguably a full simulator
72 * is not needed to support just single stepping. Recognizing
73 * branch vs non-branch instructions suffices, except when the
74 * instruction faults and triggers a synchronous exception which
75 * can be intercepted using other means.)
76 *
77 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
78 * ARM v7-R edition" gives the most complete coverage of the various
79 * generations of ARM instructions. At this writing it is publicly
80 * accessible to anyone willing to create an account at the ARM
81 * web site; see http://www.arm.com/documentation/ for information.
82 *
83 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
84 * more details relevant to the Thumb2-only processors (such as
85 * the Cortex-M implementations).
86 */
87
88 /* textual representation of the condition field
89 * ALways (default) is omitted (empty string) */
90 static const char *arm_condition_strings[] = {
91 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
92 };
93
94 /* make up for C's missing ROR */
95 static uint32_t ror(uint32_t value, int places)
96 {
97 return (value >> places) | (value << (32 - places));
98 }
99
100 static int evaluate_unknown(uint32_t opcode,
101 uint32_t address, struct arm_instruction *instruction)
102 {
103 instruction->type = ARM_UNDEFINED_INSTRUCTION;
104 snprintf(instruction->text, 128,
105 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
106 "\tUNDEFINED INSTRUCTION", address, opcode);
107 return ERROR_OK;
108 }
109
110 static int evaluate_pld(uint32_t opcode,
111 uint32_t address, struct arm_instruction *instruction)
112 {
113 /* PLD */
114 if ((opcode & 0x0d30f000) == 0x0510f000) {
115 uint8_t rn;
116 uint8_t u;
117 unsigned offset;
118
119 instruction->type = ARM_PLD;
120 rn = (opcode & 0xf0000) >> 16;
121 u = (opcode & 0x00800000) >> 23;
122 if (rn == 0xf) {
123 /* literal */
124 offset = opcode & 0x0fff;
125 snprintf(instruction->text, 128,
126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d",
127 address, opcode, u ? "" : "-", offset);
128 } else {
129 uint8_t i, r;
130
131 i = (opcode & 0x02000000) >> 25;
132 r = (opcode & 0x00400000) >> 22;
133
134 if (i) {
135 /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
136 offset = (opcode & 0x0F80) >> 7;
137 uint8_t rm;
138 rm = opcode & 0xf;
139
140 if (offset == 0) {
141 /* No shift */
142 snprintf(instruction->text, 128,
143 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]",
144 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm);
145
146 } else {
147 uint8_t shift;
148 shift = (opcode & 0x60) >> 5;
149
150 if (shift == 0x0) {
151 /* LSL */
152 snprintf(instruction->text, 128,
153 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)",
154 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
155 } else if (shift == 0x1) {
156 /* LSR */
157 snprintf(instruction->text, 128,
158 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)",
159 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
160 } else if (shift == 0x2) {
161 /* ASR */
162 snprintf(instruction->text, 128,
163 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)",
164 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
165 } else if (shift == 0x3) {
166 /* ROR */
167 snprintf(instruction->text, 128,
168 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)",
169 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
170 }
171 }
172 } else {
173 /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
174 offset = opcode & 0x0fff;
175 if (offset == 0) {
176 snprintf(instruction->text, 128,
177 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]",
178 address, opcode, r ? "" : "W", rn);
179 } else {
180 snprintf(instruction->text, 128,
181 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]",
182 address, opcode, r ? "" : "W", rn, u ? "" : "-", offset);
183 }
184 }
185 }
186 return ERROR_OK;
187 }
188 /* DSB */
189 if ((opcode & 0x07f000f0) == 0x05700040) {
190 instruction->type = ARM_DSB;
191
192 char *opt;
193 switch (opcode & 0x0000000f) {
194 case 0xf:
195 opt = "SY";
196 break;
197 case 0xe:
198 opt = "ST";
199 break;
200 case 0xb:
201 opt = "ISH";
202 break;
203 case 0xa:
204 opt = "ISHST";
205 break;
206 case 0x7:
207 opt = "NSH";
208 break;
209 case 0x6:
210 opt = "NSHST";
211 break;
212 case 0x3:
213 opt = "OSH";
214 break;
215 case 0x2:
216 opt = "OSHST";
217 break;
218 default:
219 opt = "UNK";
220 }
221
222 snprintf(instruction->text,
223 128,
224 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
225 address, opcode, opt);
226
227 return ERROR_OK;
228 }
229 /* ISB */
230 if ((opcode & 0x07f000f0) == 0x05700060) {
231 instruction->type = ARM_ISB;
232
233 snprintf(instruction->text,
234 128,
235 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
236 address, opcode,
237 ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
238
239 return ERROR_OK;
240 }
241 return evaluate_unknown(opcode, address, instruction);
242 }
243
244 static int evaluate_srs(uint32_t opcode,
245 uint32_t address, struct arm_instruction *instruction)
246 {
247 const char *wback = (opcode & (1 << 21)) ? "!" : "";
248 const char *mode = "";
249
250 switch ((opcode >> 23) & 0x3) {
251 case 0:
252 mode = "DA";
253 break;
254 case 1:
255 /* "IA" is default */
256 break;
257 case 2:
258 mode = "DB";
259 break;
260 case 3:
261 mode = "IB";
262 break;
263 }
264
265 switch (opcode & 0x0e500000) {
266 case 0x08400000:
267 snprintf(instruction->text, 128, "0x%8.8" PRIx32
268 "\t0x%8.8" PRIx32
269 "\tSRS%s\tSP%s, #%d",
270 address, opcode,
271 mode, wback,
272 (unsigned)(opcode & 0x1f));
273 break;
274 case 0x08100000:
275 snprintf(instruction->text, 128, "0x%8.8" PRIx32
276 "\t0x%8.8" PRIx32
277 "\tRFE%s\tr%d%s",
278 address, opcode,
279 mode,
280 (unsigned)((opcode >> 16) & 0xf), wback);
281 break;
282 default:
283 return evaluate_unknown(opcode, address, instruction);
284 }
285 return ERROR_OK;
286 }
287
288 static int evaluate_swi(uint32_t opcode,
289 uint32_t address, struct arm_instruction *instruction)
290 {
291 instruction->type = ARM_SWI;
292
293 snprintf(instruction->text, 128,
294 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
295 address, opcode, (opcode & 0xffffff));
296
297 return ERROR_OK;
298 }
299
300 static int evaluate_blx_imm(uint32_t opcode,
301 uint32_t address, struct arm_instruction *instruction)
302 {
303 int offset;
304 uint32_t immediate;
305 uint32_t target_address;
306
307 instruction->type = ARM_BLX;
308 immediate = opcode & 0x00ffffff;
309
310 /* sign extend 24-bit immediate */
311 if (immediate & 0x00800000)
312 offset = 0xff000000 | immediate;
313 else
314 offset = immediate;
315
316 /* shift two bits left */
317 offset <<= 2;
318
319 /* odd/event halfword */
320 if (opcode & 0x01000000)
321 offset |= 0x2;
322
323 target_address = address + 8 + offset;
324
325 snprintf(instruction->text,
326 128,
327 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
328 address,
329 opcode,
330 target_address);
331
332 instruction->info.b_bl_bx_blx.reg_operand = -1;
333 instruction->info.b_bl_bx_blx.target_address = target_address;
334
335 return ERROR_OK;
336 }
337
338 static int evaluate_b_bl(uint32_t opcode,
339 uint32_t address, struct arm_instruction *instruction)
340 {
341 uint8_t l;
342 uint32_t immediate;
343 int offset;
344 uint32_t target_address;
345
346 immediate = opcode & 0x00ffffff;
347 l = (opcode & 0x01000000) >> 24;
348
349 /* sign extend 24-bit immediate */
350 if (immediate & 0x00800000)
351 offset = 0xff000000 | immediate;
352 else
353 offset = immediate;
354
355 /* shift two bits left */
356 offset <<= 2;
357
358 target_address = address + 8 + offset;
359
360 if (l)
361 instruction->type = ARM_BL;
362 else
363 instruction->type = ARM_B;
364
365 snprintf(instruction->text,
366 128,
367 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
368 address,
369 opcode,
370 (l) ? "L" : "",
371 COND(opcode),
372 target_address);
373
374 instruction->info.b_bl_bx_blx.reg_operand = -1;
375 instruction->info.b_bl_bx_blx.target_address = target_address;
376
377 return ERROR_OK;
378 }
379
380 /* Coprocessor load/store and double register transfers
381 * both normal and extended instruction space (condition field b1111) */
382 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
383 uint32_t address, struct arm_instruction *instruction)
384 {
385 uint8_t cp_num = (opcode & 0xf00) >> 8;
386
387 /* MCRR or MRRC */
388 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
389 uint8_t cp_opcode, rd, rn, crm;
390 char *mnemonic;
391
392 cp_opcode = (opcode & 0xf0) >> 4;
393 rd = (opcode & 0xf000) >> 12;
394 rn = (opcode & 0xf0000) >> 16;
395 crm = (opcode & 0xf);
396
397 /* MCRR */
398 if ((opcode & 0x0ff00000) == 0x0c400000) {
399 instruction->type = ARM_MCRR;
400 mnemonic = "MCRR";
401 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
402 /* MRRC */
403 instruction->type = ARM_MRRC;
404 mnemonic = "MRRC";
405 } else {
406 LOG_ERROR("Unknown instruction");
407 return ERROR_FAIL;
408 }
409
410 snprintf(instruction->text, 128,
411 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
412 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
413 address, opcode, mnemonic,
414 ((opcode & 0xf0000000) == 0xf0000000)
415 ? "2" : COND(opcode),
416 COND(opcode), cp_num, cp_opcode, rd, rn, crm);
417 } else {/* LDC or STC */
418 uint8_t crd, rn, offset;
419 uint8_t u;
420 char *mnemonic;
421 char addressing_mode[32];
422
423 crd = (opcode & 0xf000) >> 12;
424 rn = (opcode & 0xf0000) >> 16;
425 offset = (opcode & 0xff) << 2;
426
427 /* load/store */
428 if (opcode & 0x00100000) {
429 instruction->type = ARM_LDC;
430 mnemonic = "LDC";
431 } else {
432 instruction->type = ARM_STC;
433 mnemonic = "STC";
434 }
435
436 u = (opcode & 0x00800000) >> 23;
437
438 /* addressing modes */
439 if ((opcode & 0x01200000) == 0x01000000)/* offset */
440 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
441 rn, u ? "" : "-", offset);
442 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
443 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
444 rn, u ? "" : "-", offset);
445 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
446 snprintf(addressing_mode, 32, "[r%i], #%s%d",
447 rn, u ? "" : "-", offset);
448 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
449 snprintf(addressing_mode, 32, "[r%i], {%d}",
450 rn, offset >> 2);
451
452 snprintf(instruction->text, 128, "0x%8.8" PRIx32
453 "\t0x%8.8" PRIx32
454 "\t%s%s%s p%i, c%i, %s",
455 address, opcode, mnemonic,
456 ((opcode & 0xf0000000) == 0xf0000000)
457 ? "2" : COND(opcode),
458 (opcode & (1 << 22)) ? "L" : "",
459 cp_num, crd, addressing_mode);
460 }
461
462 return ERROR_OK;
463 }
464
465 /* Coprocessor data processing instructions
466 * Coprocessor register transfer instructions
467 * both normal and extended instruction space (condition field b1111) */
468 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
469 uint32_t address, struct arm_instruction *instruction)
470 {
471 const char *cond;
472 char *mnemonic;
473 uint8_t cp_num, opcode_1, crd_rd, crn, crm, opcode_2;
474
475 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
476 cp_num = (opcode & 0xf00) >> 8;
477 crd_rd = (opcode & 0xf000) >> 12;
478 crn = (opcode & 0xf0000) >> 16;
479 crm = (opcode & 0xf);
480 opcode_2 = (opcode & 0xe0) >> 5;
481
482 /* CDP or MRC/MCR */
483 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
484 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
485 instruction->type = ARM_MRC;
486 mnemonic = "MRC";
487 } else {/* bit 20 not set -> MCR */
488 instruction->type = ARM_MCR;
489 mnemonic = "MCR";
490 }
491
492 opcode_1 = (opcode & 0x00e00000) >> 21;
493
494 snprintf(instruction->text,
495 128,
496 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
497 address,
498 opcode,
499 mnemonic,
500 cond,
501 cp_num,
502 opcode_1,
503 crd_rd,
504 crn,
505 crm,
506 opcode_2);
507 } else {/* bit 4 not set -> CDP */
508 instruction->type = ARM_CDP;
509 mnemonic = "CDP";
510
511 opcode_1 = (opcode & 0x00f00000) >> 20;
512
513 snprintf(instruction->text,
514 128,
515 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
516 address,
517 opcode,
518 mnemonic,
519 cond,
520 cp_num,
521 opcode_1,
522 crd_rd,
523 crn,
524 crm,
525 opcode_2);
526 }
527
528 return ERROR_OK;
529 }
530
531 /* Load/store instructions */
532 static int evaluate_load_store(uint32_t opcode,
533 uint32_t address, struct arm_instruction *instruction)
534 {
535 uint8_t i, p, u, b, w, l;
536 uint8_t rn, rd;
537 char *operation;/* "LDR" or "STR" */
538 char *suffix; /* "", "B", "T", "BT" */
539 char offset[32];
540
541 /* examine flags */
542 i = (opcode & 0x02000000) >> 25;
543 p = (opcode & 0x01000000) >> 24;
544 u = (opcode & 0x00800000) >> 23;
545 b = (opcode & 0x00400000) >> 22;
546 w = (opcode & 0x00200000) >> 21;
547 l = (opcode & 0x00100000) >> 20;
548
549 /* target register */
550 rd = (opcode & 0xf000) >> 12;
551
552 /* base register */
553 rn = (opcode & 0xf0000) >> 16;
554
555 instruction->info.load_store.rd = rd;
556 instruction->info.load_store.rn = rn;
557 instruction->info.load_store.u = u;
558
559 /* determine operation */
560 if (l)
561 operation = "LDR";
562 else
563 operation = "STR";
564
565 /* determine instruction type and suffix */
566 if (b) {
567 if ((p == 0) && (w == 1)) {
568 if (l)
569 instruction->type = ARM_LDRBT;
570 else
571 instruction->type = ARM_STRBT;
572 suffix = "BT";
573 } else {
574 if (l)
575 instruction->type = ARM_LDRB;
576 else
577 instruction->type = ARM_STRB;
578 suffix = "B";
579 }
580 } else {
581 if ((p == 0) && (w == 1)) {
582 if (l)
583 instruction->type = ARM_LDRT;
584 else
585 instruction->type = ARM_STRT;
586 suffix = "T";
587 } else {
588 if (l)
589 instruction->type = ARM_LDR;
590 else
591 instruction->type = ARM_STR;
592 suffix = "";
593 }
594 }
595
596 if (!i) { /* #+-<offset_12> */
597 uint32_t offset_12 = (opcode & 0xfff);
598 if (offset_12)
599 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (u) ? "" : "-", offset_12);
600 else
601 snprintf(offset, 32, "%s", "");
602
603 instruction->info.load_store.offset_mode = 0;
604 instruction->info.load_store.offset.offset = offset_12;
605 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
606 uint8_t shift_imm, shift;
607 uint8_t rm;
608
609 shift_imm = (opcode & 0xf80) >> 7;
610 shift = (opcode & 0x60) >> 5;
611 rm = (opcode & 0xf);
612
613 /* LSR encodes a shift by 32 bit as 0x0 */
614 if ((shift == 0x1) && (shift_imm == 0x0))
615 shift_imm = 0x20;
616
617 /* ASR encodes a shift by 32 bit as 0x0 */
618 if ((shift == 0x2) && (shift_imm == 0x0))
619 shift_imm = 0x20;
620
621 /* ROR by 32 bit is actually a RRX */
622 if ((shift == 0x3) && (shift_imm == 0x0))
623 shift = 0x4;
624
625 instruction->info.load_store.offset_mode = 1;
626 instruction->info.load_store.offset.reg.rm = rm;
627 instruction->info.load_store.offset.reg.shift = shift;
628 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
629
630 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
631 snprintf(offset, 32, ", %sr%i", (u) ? "" : "-", rm);
632 else { /* +-<Rm>, <Shift>, #<shift_imm> */
633 switch (shift) {
634 case 0x0: /* LSL */
635 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (u) ? "" : "-", rm, shift_imm);
636 break;
637 case 0x1: /* LSR */
638 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (u) ? "" : "-", rm, shift_imm);
639 break;
640 case 0x2: /* ASR */
641 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (u) ? "" : "-", rm, shift_imm);
642 break;
643 case 0x3: /* ROR */
644 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (u) ? "" : "-", rm, shift_imm);
645 break;
646 case 0x4: /* RRX */
647 snprintf(offset, 32, ", %sr%i, RRX", (u) ? "" : "-", rm);
648 break;
649 }
650 }
651 }
652
653 if (p == 1) {
654 if (w == 0) { /* offset */
655 snprintf(instruction->text,
656 128,
657 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
658 address,
659 opcode,
660 operation,
661 COND(opcode),
662 suffix,
663 rd,
664 rn,
665 offset);
666
667 instruction->info.load_store.index_mode = 0;
668 } else {/* pre-indexed */
669 snprintf(instruction->text,
670 128,
671 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
672 address,
673 opcode,
674 operation,
675 COND(opcode),
676 suffix,
677 rd,
678 rn,
679 offset);
680
681 instruction->info.load_store.index_mode = 1;
682 }
683 } else {/* post-indexed */
684 snprintf(instruction->text,
685 128,
686 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
687 address,
688 opcode,
689 operation,
690 COND(opcode),
691 suffix,
692 rd,
693 rn,
694 offset);
695
696 instruction->info.load_store.index_mode = 2;
697 }
698
699 return ERROR_OK;
700 }
701
702 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
703 {
704 unsigned rm = (opcode >> 0) & 0xf;
705 unsigned rd = (opcode >> 12) & 0xf;
706 unsigned rn = (opcode >> 16) & 0xf;
707 char *type, *rot;
708
709 switch ((opcode >> 24) & 0x3) {
710 case 0:
711 type = "B16";
712 break;
713 case 1:
714 sprintf(cp, "UNDEFINED");
715 return ARM_UNDEFINED_INSTRUCTION;
716 case 2:
717 type = "B";
718 break;
719 default:
720 type = "H";
721 break;
722 }
723
724 switch ((opcode >> 10) & 0x3) {
725 case 0:
726 rot = "";
727 break;
728 case 1:
729 rot = ", ROR #8";
730 break;
731 case 2:
732 rot = ", ROR #16";
733 break;
734 default:
735 rot = ", ROR #24";
736 break;
737 }
738
739 if (rn == 0xf) {
740 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
741 (opcode & (1 << 22)) ? 'U' : 'S',
742 type, COND(opcode),
743 rd, rm, rot);
744 return ARM_MOV;
745 } else {
746 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
747 (opcode & (1 << 22)) ? 'U' : 'S',
748 type, COND(opcode),
749 rd, rn, rm, rot);
750 return ARM_ADD;
751 }
752 }
753
754 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
755 {
756 char *prefix;
757 char *op;
758 int type;
759
760 switch ((opcode >> 20) & 0x7) {
761 case 1:
762 prefix = "S";
763 break;
764 case 2:
765 prefix = "Q";
766 break;
767 case 3:
768 prefix = "SH";
769 break;
770 case 5:
771 prefix = "U";
772 break;
773 case 6:
774 prefix = "UQ";
775 break;
776 case 7:
777 prefix = "UH";
778 break;
779 default:
780 goto undef;
781 }
782
783 switch ((opcode >> 5) & 0x7) {
784 case 0:
785 op = "ADD16";
786 type = ARM_ADD;
787 break;
788 case 1:
789 op = "ADDSUBX";
790 type = ARM_ADD;
791 break;
792 case 2:
793 op = "SUBADDX";
794 type = ARM_SUB;
795 break;
796 case 3:
797 op = "SUB16";
798 type = ARM_SUB;
799 break;
800 case 4:
801 op = "ADD8";
802 type = ARM_ADD;
803 break;
804 case 7:
805 op = "SUB8";
806 type = ARM_SUB;
807 break;
808 default:
809 goto undef;
810 }
811
812 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
813 (int) (opcode >> 12) & 0xf,
814 (int) (opcode >> 16) & 0xf,
815 (int) (opcode >> 0) & 0xf);
816 return type;
817
818 undef:
819 /* these opcodes might be used someday */
820 sprintf(cp, "UNDEFINED");
821 return ARM_UNDEFINED_INSTRUCTION;
822 }
823
824 /* ARMv6 and later support "media" instructions (includes SIMD) */
825 static int evaluate_media(uint32_t opcode, uint32_t address,
826 struct arm_instruction *instruction)
827 {
828 char *cp = instruction->text;
829 char *mnemonic = NULL;
830
831 sprintf(cp,
832 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
833 address, opcode);
834 cp = strchr(cp, 0);
835
836 /* parallel add/subtract */
837 if ((opcode & 0x01800000) == 0x00000000) {
838 instruction->type = evaluate_p_add_sub(opcode, address, cp);
839 return ERROR_OK;
840 }
841
842 /* halfword pack */
843 if ((opcode & 0x01f00020) == 0x00800000) {
844 char *type, *shift;
845 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
846
847 if (opcode & (1 << 6)) {
848 type = "TB";
849 shift = "ASR";
850 if (imm == 0)
851 imm = 32;
852 } else {
853 type = "BT";
854 shift = "LSL";
855 }
856 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
857 type, COND(opcode),
858 (int) (opcode >> 12) & 0xf,
859 (int) (opcode >> 16) & 0xf,
860 (int) (opcode >> 0) & 0xf,
861 shift, imm);
862 return ERROR_OK;
863 }
864
865 /* word saturate */
866 if ((opcode & 0x01a00020) == 0x00a00000) {
867 char *shift;
868 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
869
870 if (opcode & (1 << 6)) {
871 shift = "ASR";
872 if (imm == 0)
873 imm = 32;
874 } else
875 shift = "LSL";
876
877 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
878 (opcode & (1 << 22)) ? 'U' : 'S',
879 COND(opcode),
880 (int) (opcode >> 12) & 0xf,
881 (int) (opcode >> 16) & 0x1f,
882 (int) (opcode >> 0) & 0xf,
883 shift, imm);
884 return ERROR_OK;
885 }
886
887 /* sign extension */
888 if ((opcode & 0x018000f0) == 0x00800070) {
889 instruction->type = evaluate_extend(opcode, address, cp);
890 return ERROR_OK;
891 }
892
893 /* multiplies */
894 if ((opcode & 0x01f00080) == 0x01000000) {
895 unsigned rn = (opcode >> 12) & 0xf;
896
897 if (rn != 0xf)
898 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
899 (opcode & (1 << 6)) ? 'S' : 'A',
900 (opcode & (1 << 5)) ? "X" : "",
901 COND(opcode),
902 (int) (opcode >> 16) & 0xf,
903 (int) (opcode >> 0) & 0xf,
904 (int) (opcode >> 8) & 0xf,
905 rn);
906 else
907 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
908 (opcode & (1 << 6)) ? 'S' : 'A',
909 (opcode & (1 << 5)) ? "X" : "",
910 COND(opcode),
911 (int) (opcode >> 16) & 0xf,
912 (int) (opcode >> 0) & 0xf,
913 (int) (opcode >> 8) & 0xf);
914 return ERROR_OK;
915 }
916 if ((opcode & 0x01f00000) == 0x01400000) {
917 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
918 (opcode & (1 << 6)) ? 'S' : 'A',
919 (opcode & (1 << 5)) ? "X" : "",
920 COND(opcode),
921 (int) (opcode >> 12) & 0xf,
922 (int) (opcode >> 16) & 0xf,
923 (int) (opcode >> 0) & 0xf,
924 (int) (opcode >> 8) & 0xf);
925 return ERROR_OK;
926 }
927 if ((opcode & 0x01f00000) == 0x01500000) {
928 unsigned rn = (opcode >> 12) & 0xf;
929
930 switch (opcode & 0xc0) {
931 case 3:
932 if (rn == 0xf)
933 goto undef;
934 /* FALL THROUGH */
935 case 0:
936 break;
937 default:
938 goto undef;
939 }
940
941 if (rn != 0xf)
942 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
943 (opcode & (1 << 6)) ? 'S' : 'A',
944 (opcode & (1 << 5)) ? "R" : "",
945 COND(opcode),
946 (int) (opcode >> 16) & 0xf,
947 (int) (opcode >> 0) & 0xf,
948 (int) (opcode >> 8) & 0xf,
949 rn);
950 else
951 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
952 (opcode & (1 << 5)) ? "R" : "",
953 COND(opcode),
954 (int) (opcode >> 16) & 0xf,
955 (int) (opcode >> 0) & 0xf,
956 (int) (opcode >> 8) & 0xf);
957 return ERROR_OK;
958 }
959
960 /* simple matches against the remaining decode bits */
961 switch (opcode & 0x01f000f0) {
962 case 0x00a00030:
963 case 0x00e00030:
964 /* parallel halfword saturate */
965 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
966 (opcode & (1 << 22)) ? 'U' : 'S',
967 COND(opcode),
968 (int) (opcode >> 12) & 0xf,
969 (int) (opcode >> 16) & 0xf,
970 (int) (opcode >> 0) & 0xf);
971 return ERROR_OK;
972 case 0x00b00030:
973 mnemonic = "REV";
974 break;
975 case 0x00b000b0:
976 mnemonic = "REV16";
977 break;
978 case 0x00f000b0:
979 mnemonic = "REVSH";
980 break;
981 case 0x008000b0:
982 /* select bytes */
983 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
984 (int) (opcode >> 12) & 0xf,
985 (int) (opcode >> 16) & 0xf,
986 (int) (opcode >> 0) & 0xf);
987 return ERROR_OK;
988 case 0x01800010:
989 /* unsigned sum of absolute differences */
990 if (((opcode >> 12) & 0xf) == 0xf)
991 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
992 (int) (opcode >> 16) & 0xf,
993 (int) (opcode >> 0) & 0xf,
994 (int) (opcode >> 8) & 0xf);
995 else
996 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
997 (int) (opcode >> 16) & 0xf,
998 (int) (opcode >> 0) & 0xf,
999 (int) (opcode >> 8) & 0xf,
1000 (int) (opcode >> 12) & 0xf);
1001 return ERROR_OK;
1002 }
1003 if (mnemonic) {
1004 unsigned rm = (opcode >> 0) & 0xf;
1005 unsigned rd = (opcode >> 12) & 0xf;
1006
1007 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
1008 return ERROR_OK;
1009 }
1010
1011 undef:
1012 /* these opcodes might be used someday */
1013 sprintf(cp, "UNDEFINED");
1014 return ERROR_OK;
1015 }
1016
1017 /* Miscellaneous load/store instructions */
1018 static int evaluate_misc_load_store(uint32_t opcode,
1019 uint32_t address, struct arm_instruction *instruction)
1020 {
1021 uint8_t p, u, i, w, l, s, h;
1022 uint8_t rn, rd;
1023 char *operation;/* "LDR" or "STR" */
1024 char *suffix; /* "H", "SB", "SH", "D" */
1025 char offset[32];
1026
1027 /* examine flags */
1028 p = (opcode & 0x01000000) >> 24;
1029 u = (opcode & 0x00800000) >> 23;
1030 i = (opcode & 0x00400000) >> 22;
1031 w = (opcode & 0x00200000) >> 21;
1032 l = (opcode & 0x00100000) >> 20;
1033 s = (opcode & 0x00000040) >> 6;
1034 h = (opcode & 0x00000020) >> 5;
1035
1036 /* target register */
1037 rd = (opcode & 0xf000) >> 12;
1038
1039 /* base register */
1040 rn = (opcode & 0xf0000) >> 16;
1041
1042 instruction->info.load_store.rd = rd;
1043 instruction->info.load_store.rn = rn;
1044 instruction->info.load_store.u = u;
1045
1046 /* determine instruction type and suffix */
1047 if (s) {/* signed */
1048 if (l) {/* load */
1049 if (h) {
1050 operation = "LDR";
1051 instruction->type = ARM_LDRSH;
1052 suffix = "SH";
1053 } else {
1054 operation = "LDR";
1055 instruction->type = ARM_LDRSB;
1056 suffix = "SB";
1057 }
1058 } else {/* there are no signed stores, so this is used to encode double-register
1059 *load/stores */
1060 suffix = "D";
1061 if (h) {
1062 operation = "STR";
1063 instruction->type = ARM_STRD;
1064 } else {
1065 operation = "LDR";
1066 instruction->type = ARM_LDRD;
1067 }
1068 }
1069 } else {/* unsigned */
1070 suffix = "H";
1071 if (l) {/* load */
1072 operation = "LDR";
1073 instruction->type = ARM_LDRH;
1074 } else {/* store */
1075 operation = "STR";
1076 instruction->type = ARM_STRH;
1077 }
1078 }
1079
1080 if (i) {/* Immediate offset/index (#+-<offset_8>)*/
1081 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1082 snprintf(offset, 32, "#%s0x%" PRIx32 "", (u) ? "" : "-", offset_8);
1083
1084 instruction->info.load_store.offset_mode = 0;
1085 instruction->info.load_store.offset.offset = offset_8;
1086 } else {/* Register offset/index (+-<Rm>) */
1087 uint8_t rm;
1088 rm = (opcode & 0xf);
1089 snprintf(offset, 32, "%sr%i", (u) ? "" : "-", rm);
1090
1091 instruction->info.load_store.offset_mode = 1;
1092 instruction->info.load_store.offset.reg.rm = rm;
1093 instruction->info.load_store.offset.reg.shift = 0x0;
1094 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1095 }
1096
1097 if (p == 1) {
1098 if (w == 0) { /* offset */
1099 snprintf(instruction->text,
1100 128,
1101 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1102 address,
1103 opcode,
1104 operation,
1105 COND(opcode),
1106 suffix,
1107 rd,
1108 rn,
1109 offset);
1110
1111 instruction->info.load_store.index_mode = 0;
1112 } else {/* pre-indexed */
1113 snprintf(instruction->text,
1114 128,
1115 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1116 address,
1117 opcode,
1118 operation,
1119 COND(opcode),
1120 suffix,
1121 rd,
1122 rn,
1123 offset);
1124
1125 instruction->info.load_store.index_mode = 1;
1126 }
1127 } else {/* post-indexed */
1128 snprintf(instruction->text,
1129 128,
1130 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1131 address,
1132 opcode,
1133 operation,
1134 COND(opcode),
1135 suffix,
1136 rd,
1137 rn,
1138 offset);
1139
1140 instruction->info.load_store.index_mode = 2;
1141 }
1142
1143 return ERROR_OK;
1144 }
1145
1146 /* Load/store multiples instructions */
1147 static int evaluate_ldm_stm(uint32_t opcode,
1148 uint32_t address, struct arm_instruction *instruction)
1149 {
1150 uint8_t p, u, s, w, l, rn;
1151 uint32_t register_list;
1152 char *addressing_mode;
1153 char *mnemonic;
1154 char reg_list[69];
1155 char *reg_list_p;
1156 int i;
1157 int first_reg = 1;
1158
1159 p = (opcode & 0x01000000) >> 24;
1160 u = (opcode & 0x00800000) >> 23;
1161 s = (opcode & 0x00400000) >> 22;
1162 w = (opcode & 0x00200000) >> 21;
1163 l = (opcode & 0x00100000) >> 20;
1164 register_list = (opcode & 0xffff);
1165 rn = (opcode & 0xf0000) >> 16;
1166
1167 instruction->info.load_store_multiple.rn = rn;
1168 instruction->info.load_store_multiple.register_list = register_list;
1169 instruction->info.load_store_multiple.s = s;
1170 instruction->info.load_store_multiple.w = w;
1171
1172 if (l) {
1173 instruction->type = ARM_LDM;
1174 mnemonic = "LDM";
1175 } else {
1176 instruction->type = ARM_STM;
1177 mnemonic = "STM";
1178 }
1179
1180 if (p) {
1181 if (u) {
1182 instruction->info.load_store_multiple.addressing_mode = 1;
1183 addressing_mode = "IB";
1184 } else {
1185 instruction->info.load_store_multiple.addressing_mode = 3;
1186 addressing_mode = "DB";
1187 }
1188 } else {
1189 if (u) {
1190 instruction->info.load_store_multiple.addressing_mode = 0;
1191 /* "IA" is the default in UAL syntax */
1192 addressing_mode = "";
1193 } else {
1194 instruction->info.load_store_multiple.addressing_mode = 2;
1195 addressing_mode = "DA";
1196 }
1197 }
1198
1199 reg_list_p = reg_list;
1200 for (i = 0; i <= 15; i++) {
1201 if ((register_list >> i) & 1) {
1202 if (first_reg) {
1203 first_reg = 0;
1204 reg_list_p += snprintf(reg_list_p,
1205 (reg_list + 69 - reg_list_p),
1206 "r%i",
1207 i);
1208 } else
1209 reg_list_p += snprintf(reg_list_p,
1210 (reg_list + 69 - reg_list_p),
1211 ", r%i",
1212 i);
1213 }
1214 }
1215
1216 snprintf(instruction->text, 128,
1217 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1218 "\t%s%s%s r%i%s, {%s}%s",
1219 address, opcode,
1220 mnemonic, addressing_mode, COND(opcode),
1221 rn, (w) ? "!" : "", reg_list, (s) ? "^" : "");
1222
1223 return ERROR_OK;
1224 }
1225
1226 /* Multiplies, extra load/stores */
1227 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1228 uint32_t address, struct arm_instruction *instruction)
1229 {
1230 /* Multiply (accumulate) (long) and Swap/swap byte */
1231 if ((opcode & 0x000000f0) == 0x00000090) {
1232 /* Multiply (accumulate) */
1233 if ((opcode & 0x0f800000) == 0x00000000) {
1234 uint8_t rm, rs, rn, rd, s;
1235 rm = opcode & 0xf;
1236 rs = (opcode & 0xf00) >> 8;
1237 rn = (opcode & 0xf000) >> 12;
1238 rd = (opcode & 0xf0000) >> 16;
1239 s = (opcode & 0x00100000) >> 20;
1240
1241 /* examine A bit (accumulate) */
1242 if (opcode & 0x00200000) {
1243 instruction->type = ARM_MLA;
1244 snprintf(instruction->text,
1245 128,
1246 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1247 address,
1248 opcode,
1249 COND(opcode),
1250 (s) ? "S" : "",
1251 rd,
1252 rm,
1253 rs,
1254 rn);
1255 } else {
1256 instruction->type = ARM_MUL;
1257 snprintf(instruction->text,
1258 128,
1259 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1260 address,
1261 opcode,
1262 COND(opcode),
1263 (s) ? "S" : "",
1264 rd,
1265 rm,
1266 rs);
1267 }
1268
1269 return ERROR_OK;
1270 }
1271
1272 /* Multiply (accumulate) long */
1273 if ((opcode & 0x0f800000) == 0x00800000) {
1274 char *mnemonic = NULL;
1275 uint8_t rm, rs, rd_hi, rd_low, s;
1276 rm = opcode & 0xf;
1277 rs = (opcode & 0xf00) >> 8;
1278 rd_hi = (opcode & 0xf000) >> 12;
1279 rd_low = (opcode & 0xf0000) >> 16;
1280 s = (opcode & 0x00100000) >> 20;
1281
1282 switch ((opcode & 0x00600000) >> 21) {
1283 case 0x0:
1284 instruction->type = ARM_UMULL;
1285 mnemonic = "UMULL";
1286 break;
1287 case 0x1:
1288 instruction->type = ARM_UMLAL;
1289 mnemonic = "UMLAL";
1290 break;
1291 case 0x2:
1292 instruction->type = ARM_SMULL;
1293 mnemonic = "SMULL";
1294 break;
1295 case 0x3:
1296 instruction->type = ARM_SMLAL;
1297 mnemonic = "SMLAL";
1298 break;
1299 }
1300
1301 snprintf(instruction->text,
1302 128,
1303 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1304 address,
1305 opcode,
1306 mnemonic,
1307 COND(opcode),
1308 (s) ? "S" : "",
1309 rd_low,
1310 rd_hi,
1311 rm,
1312 rs);
1313
1314 return ERROR_OK;
1315 }
1316
1317 /* Swap/swap byte */
1318 if ((opcode & 0x0f800000) == 0x01000000) {
1319 uint8_t rm, rd, rn;
1320 rm = opcode & 0xf;
1321 rd = (opcode & 0xf000) >> 12;
1322 rn = (opcode & 0xf0000) >> 16;
1323
1324 /* examine B flag */
1325 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1326
1327 snprintf(instruction->text,
1328 128,
1329 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1330 address,
1331 opcode,
1332 (opcode & 0x00400000) ? "SWPB" : "SWP",
1333 COND(opcode),
1334 rd,
1335 rm,
1336 rn);
1337 return ERROR_OK;
1338 }
1339
1340 }
1341
1342 return evaluate_misc_load_store(opcode, address, instruction);
1343 }
1344
1345 static int evaluate_mrs_msr(uint32_t opcode,
1346 uint32_t address, struct arm_instruction *instruction)
1347 {
1348 int r = (opcode & 0x00400000) >> 22;
1349 char *PSR = (r) ? "SPSR" : "CPSR";
1350
1351 /* Move register to status register (MSR) */
1352 if (opcode & 0x00200000) {
1353 instruction->type = ARM_MSR;
1354
1355 /* immediate variant */
1356 if (opcode & 0x02000000) {
1357 uint8_t immediate = (opcode & 0xff);
1358 uint8_t rotate = (opcode & 0xf00);
1359
1360 snprintf(instruction->text,
1361 128,
1362 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1363 address,
1364 opcode,
1365 COND(opcode),
1366 PSR,
1367 (opcode & 0x10000) ? "c" : "",
1368 (opcode & 0x20000) ? "x" : "",
1369 (opcode & 0x40000) ? "s" : "",
1370 (opcode & 0x80000) ? "f" : "",
1371 ror(immediate, (rotate * 2))
1372 );
1373 } else {/* register variant */
1374 uint8_t rm = opcode & 0xf;
1375 snprintf(instruction->text,
1376 128,
1377 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1378 address,
1379 opcode,
1380 COND(opcode),
1381 PSR,
1382 (opcode & 0x10000) ? "c" : "",
1383 (opcode & 0x20000) ? "x" : "",
1384 (opcode & 0x40000) ? "s" : "",
1385 (opcode & 0x80000) ? "f" : "",
1386 rm
1387 );
1388 }
1389
1390 } else {/* Move status register to register (MRS) */
1391 uint8_t rd;
1392
1393 instruction->type = ARM_MRS;
1394 rd = (opcode & 0x0000f000) >> 12;
1395
1396 snprintf(instruction->text,
1397 128,
1398 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1399 address,
1400 opcode,
1401 COND(opcode),
1402 rd,
1403 PSR);
1404 }
1405
1406 return ERROR_OK;
1407 }
1408
1409 /* Miscellaneous instructions */
1410 static int evaluate_misc_instr(uint32_t opcode,
1411 uint32_t address, struct arm_instruction *instruction)
1412 {
1413 /* MRS/MSR */
1414 if ((opcode & 0x000000f0) == 0x00000000)
1415 evaluate_mrs_msr(opcode, address, instruction);
1416
1417 /* BX */
1418 if ((opcode & 0x006000f0) == 0x00200010) {
1419 uint8_t rm;
1420 instruction->type = ARM_BX;
1421 rm = opcode & 0xf;
1422
1423 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1424 address, opcode, COND(opcode), rm);
1425
1426 instruction->info.b_bl_bx_blx.reg_operand = rm;
1427 instruction->info.b_bl_bx_blx.target_address = -1;
1428 }
1429
1430 /* BXJ - "Jazelle" support (ARMv5-J) */
1431 if ((opcode & 0x006000f0) == 0x00200020) {
1432 uint8_t rm;
1433 instruction->type = ARM_BX;
1434 rm = opcode & 0xf;
1435
1436 snprintf(instruction->text, 128,
1437 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1438 address, opcode, COND(opcode), rm);
1439
1440 instruction->info.b_bl_bx_blx.reg_operand = rm;
1441 instruction->info.b_bl_bx_blx.target_address = -1;
1442 }
1443
1444 /* CLZ */
1445 if ((opcode & 0x006000f0) == 0x00600010) {
1446 uint8_t rm, rd;
1447 instruction->type = ARM_CLZ;
1448 rm = opcode & 0xf;
1449 rd = (opcode & 0xf000) >> 12;
1450
1451 snprintf(instruction->text,
1452 128,
1453 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1454 address,
1455 opcode,
1456 COND(opcode),
1457 rd,
1458 rm);
1459 }
1460
1461 /* BLX(2) */
1462 if ((opcode & 0x006000f0) == 0x00200030) {
1463 uint8_t rm;
1464 instruction->type = ARM_BLX;
1465 rm = opcode & 0xf;
1466
1467 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1468 address, opcode, COND(opcode), rm);
1469
1470 instruction->info.b_bl_bx_blx.reg_operand = rm;
1471 instruction->info.b_bl_bx_blx.target_address = -1;
1472 }
1473
1474 /* Enhanced DSP add/subtracts */
1475 if ((opcode & 0x0000000f0) == 0x00000050) {
1476 uint8_t rm, rd, rn;
1477 char *mnemonic = NULL;
1478 rm = opcode & 0xf;
1479 rd = (opcode & 0xf000) >> 12;
1480 rn = (opcode & 0xf0000) >> 16;
1481
1482 switch ((opcode & 0x00600000) >> 21) {
1483 case 0x0:
1484 instruction->type = ARM_QADD;
1485 mnemonic = "QADD";
1486 break;
1487 case 0x1:
1488 instruction->type = ARM_QSUB;
1489 mnemonic = "QSUB";
1490 break;
1491 case 0x2:
1492 instruction->type = ARM_QDADD;
1493 mnemonic = "QDADD";
1494 break;
1495 case 0x3:
1496 instruction->type = ARM_QDSUB;
1497 mnemonic = "QDSUB";
1498 break;
1499 }
1500
1501 snprintf(instruction->text,
1502 128,
1503 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1504 address,
1505 opcode,
1506 mnemonic,
1507 COND(opcode),
1508 rd,
1509 rm,
1510 rn);
1511 }
1512
1513 /* exception return */
1514 if ((opcode & 0x0000000f0) == 0x00000060) {
1515 if (((opcode & 0x600000) >> 21) == 3)
1516 instruction->type = ARM_ERET;
1517 snprintf(instruction->text,
1518 128,
1519 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1520 address,
1521 opcode);
1522 }
1523
1524 /* exception generate instructions */
1525 if ((opcode & 0x0000000f0) == 0x00000070) {
1526 uint32_t immediate = 0;
1527 char *mnemonic = NULL;
1528
1529 switch ((opcode & 0x600000) >> 21) {
1530 case 0x1:
1531 instruction->type = ARM_BKPT;
1532 mnemonic = "BRKT";
1533 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1534 break;
1535 case 0x2:
1536 instruction->type = ARM_HVC;
1537 mnemonic = "HVC";
1538 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1539 break;
1540 case 0x3:
1541 instruction->type = ARM_SMC;
1542 mnemonic = "SMC";
1543 immediate = (opcode & 0xf);
1544 break;
1545 }
1546
1547 snprintf(instruction->text,
1548 128,
1549 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1550 address,
1551 opcode,
1552 mnemonic,
1553 immediate);
1554 }
1555
1556 /* Enhanced DSP multiplies */
1557 if ((opcode & 0x000000090) == 0x00000080) {
1558 int x = (opcode & 0x20) >> 5;
1559 int y = (opcode & 0x40) >> 6;
1560
1561 /* SMLA < x><y> */
1562 if ((opcode & 0x00600000) == 0x00000000) {
1563 uint8_t rd, rm, rs, rn;
1564 instruction->type = ARM_SMLAXY;
1565 rd = (opcode & 0xf0000) >> 16;
1566 rm = (opcode & 0xf);
1567 rs = (opcode & 0xf00) >> 8;
1568 rn = (opcode & 0xf000) >> 12;
1569
1570 snprintf(instruction->text,
1571 128,
1572 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1573 address,
1574 opcode,
1575 (x) ? "T" : "B",
1576 (y) ? "T" : "B",
1577 COND(opcode),
1578 rd,
1579 rm,
1580 rs,
1581 rn);
1582 }
1583
1584 /* SMLAL < x><y> */
1585 if ((opcode & 0x00600000) == 0x00400000) {
1586 uint8_t rd_low, rd_hi, rm, rs;
1587 instruction->type = ARM_SMLAXY;
1588 rd_hi = (opcode & 0xf0000) >> 16;
1589 rd_low = (opcode & 0xf000) >> 12;
1590 rm = (opcode & 0xf);
1591 rs = (opcode & 0xf00) >> 8;
1592
1593 snprintf(instruction->text,
1594 128,
1595 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1596 address,
1597 opcode,
1598 (x) ? "T" : "B",
1599 (y) ? "T" : "B",
1600 COND(opcode),
1601 rd_low,
1602 rd_hi,
1603 rm,
1604 rs);
1605 }
1606
1607 /* SMLAW < y> */
1608 if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) {
1609 uint8_t rd, rm, rs, rn;
1610 instruction->type = ARM_SMLAWY;
1611 rd = (opcode & 0xf0000) >> 16;
1612 rm = (opcode & 0xf);
1613 rs = (opcode & 0xf00) >> 8;
1614 rn = (opcode & 0xf000) >> 12;
1615
1616 snprintf(instruction->text,
1617 128,
1618 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1619 address,
1620 opcode,
1621 (y) ? "T" : "B",
1622 COND(opcode),
1623 rd,
1624 rm,
1625 rs,
1626 rn);
1627 }
1628
1629 /* SMUL < x><y> */
1630 if ((opcode & 0x00600000) == 0x00600000) {
1631 uint8_t rd, rm, rs;
1632 instruction->type = ARM_SMULXY;
1633 rd = (opcode & 0xf0000) >> 16;
1634 rm = (opcode & 0xf);
1635 rs = (opcode & 0xf00) >> 8;
1636
1637 snprintf(instruction->text,
1638 128,
1639 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1640 address,
1641 opcode,
1642 (x) ? "T" : "B",
1643 (y) ? "T" : "B",
1644 COND(opcode),
1645 rd,
1646 rm,
1647 rs);
1648 }
1649
1650 /* SMULW < y> */
1651 if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) {
1652 uint8_t rd, rm, rs;
1653 instruction->type = ARM_SMULWY;
1654 rd = (opcode & 0xf0000) >> 16;
1655 rm = (opcode & 0xf);
1656 rs = (opcode & 0xf00) >> 8;
1657
1658 snprintf(instruction->text,
1659 128,
1660 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1661 address,
1662 opcode,
1663 (y) ? "T" : "B",
1664 COND(opcode),
1665 rd,
1666 rm,
1667 rs);
1668 }
1669 }
1670
1671 return ERROR_OK;
1672 }
1673
1674 static int evaluate_mov_imm(uint32_t opcode,
1675 uint32_t address, struct arm_instruction *instruction)
1676 {
1677 uint16_t immediate;
1678 uint8_t rd;
1679 bool t;
1680
1681 rd = (opcode & 0xf000) >> 12;
1682 t = opcode & 0x00400000;
1683 immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
1684
1685 instruction->type = ARM_MOV;
1686 instruction->info.data_proc.rd = rd;
1687
1688 snprintf(instruction->text,
1689 128,
1690 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
1691 address,
1692 opcode,
1693 t ? "T" : "W",
1694 COND(opcode),
1695 rd,
1696 immediate);
1697
1698 return ERROR_OK;
1699 }
1700
1701 static int evaluate_data_proc(uint32_t opcode,
1702 uint32_t address, struct arm_instruction *instruction)
1703 {
1704 uint8_t i, op, s, rn, rd;
1705 char *mnemonic = NULL;
1706 char shifter_operand[32];
1707
1708 i = (opcode & 0x02000000) >> 25;
1709 op = (opcode & 0x01e00000) >> 21;
1710 s = (opcode & 0x00100000) >> 20;
1711
1712 rd = (opcode & 0xf000) >> 12;
1713 rn = (opcode & 0xf0000) >> 16;
1714
1715 instruction->info.data_proc.rd = rd;
1716 instruction->info.data_proc.rn = rn;
1717 instruction->info.data_proc.s = s;
1718
1719 switch (op) {
1720 case 0x0:
1721 instruction->type = ARM_AND;
1722 mnemonic = "AND";
1723 break;
1724 case 0x1:
1725 instruction->type = ARM_EOR;
1726 mnemonic = "EOR";
1727 break;
1728 case 0x2:
1729 instruction->type = ARM_SUB;
1730 mnemonic = "SUB";
1731 break;
1732 case 0x3:
1733 instruction->type = ARM_RSB;
1734 mnemonic = "RSB";
1735 break;
1736 case 0x4:
1737 instruction->type = ARM_ADD;
1738 mnemonic = "ADD";
1739 break;
1740 case 0x5:
1741 instruction->type = ARM_ADC;
1742 mnemonic = "ADC";
1743 break;
1744 case 0x6:
1745 instruction->type = ARM_SBC;
1746 mnemonic = "SBC";
1747 break;
1748 case 0x7:
1749 instruction->type = ARM_RSC;
1750 mnemonic = "RSC";
1751 break;
1752 case 0x8:
1753 instruction->type = ARM_TST;
1754 mnemonic = "TST";
1755 break;
1756 case 0x9:
1757 instruction->type = ARM_TEQ;
1758 mnemonic = "TEQ";
1759 break;
1760 case 0xa:
1761 instruction->type = ARM_CMP;
1762 mnemonic = "CMP";
1763 break;
1764 case 0xb:
1765 instruction->type = ARM_CMN;
1766 mnemonic = "CMN";
1767 break;
1768 case 0xc:
1769 instruction->type = ARM_ORR;
1770 mnemonic = "ORR";
1771 break;
1772 case 0xd:
1773 instruction->type = ARM_MOV;
1774 mnemonic = "MOV";
1775 break;
1776 case 0xe:
1777 instruction->type = ARM_BIC;
1778 mnemonic = "BIC";
1779 break;
1780 case 0xf:
1781 instruction->type = ARM_MVN;
1782 mnemonic = "MVN";
1783 break;
1784 }
1785
1786 if (i) {/* immediate shifter operand (#<immediate>)*/
1787 uint8_t immed_8 = opcode & 0xff;
1788 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1789 uint32_t immediate;
1790
1791 immediate = ror(immed_8, rotate_imm * 2);
1792
1793 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1794
1795 instruction->info.data_proc.variant = 0;
1796 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1797 } else {/* register-based shifter operand */
1798 uint8_t shift, rm;
1799 shift = (opcode & 0x60) >> 5;
1800 rm = (opcode & 0xf);
1801
1802 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1803 *#<shift_immediate>") */
1804 uint8_t shift_imm;
1805 shift_imm = (opcode & 0xf80) >> 7;
1806
1807 instruction->info.data_proc.variant = 1;
1808 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
1809 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1810 shift_imm;
1811 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1812
1813 /* LSR encodes a shift by 32 bit as 0x0 */
1814 if ((shift == 0x1) && (shift_imm == 0x0))
1815 shift_imm = 0x20;
1816
1817 /* ASR encodes a shift by 32 bit as 0x0 */
1818 if ((shift == 0x2) && (shift_imm == 0x0))
1819 shift_imm = 0x20;
1820
1821 /* ROR by 32 bit is actually a RRX */
1822 if ((shift == 0x3) && (shift_imm == 0x0))
1823 shift = 0x4;
1824
1825 if ((shift_imm == 0x0) && (shift == 0x0))
1826 snprintf(shifter_operand, 32, "r%i", rm);
1827 else {
1828 if (shift == 0x0) /* LSL */
1829 snprintf(shifter_operand,
1830 32,
1831 "r%i, LSL #0x%x",
1832 rm,
1833 shift_imm);
1834 else if (shift == 0x1) /* LSR */
1835 snprintf(shifter_operand,
1836 32,
1837 "r%i, LSR #0x%x",
1838 rm,
1839 shift_imm);
1840 else if (shift == 0x2) /* ASR */
1841 snprintf(shifter_operand,
1842 32,
1843 "r%i, ASR #0x%x",
1844 rm,
1845 shift_imm);
1846 else if (shift == 0x3) /* ROR */
1847 snprintf(shifter_operand,
1848 32,
1849 "r%i, ROR #0x%x",
1850 rm,
1851 shift_imm);
1852 else if (shift == 0x4) /* RRX */
1853 snprintf(shifter_operand, 32, "r%i, RRX", rm);
1854 }
1855 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1856 uint8_t rs = (opcode & 0xf00) >> 8;
1857
1858 instruction->info.data_proc.variant = 2;
1859 instruction->info.data_proc.shifter_operand.register_shift.rm = rm;
1860 instruction->info.data_proc.shifter_operand.register_shift.rs = rs;
1861 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1862
1863 if (shift == 0x0) /* LSL */
1864 snprintf(shifter_operand, 32, "r%i, LSL r%i", rm, rs);
1865 else if (shift == 0x1) /* LSR */
1866 snprintf(shifter_operand, 32, "r%i, LSR r%i", rm, rs);
1867 else if (shift == 0x2) /* ASR */
1868 snprintf(shifter_operand, 32, "r%i, ASR r%i", rm, rs);
1869 else if (shift == 0x3) /* ROR */
1870 snprintf(shifter_operand, 32, "r%i, ROR r%i", rm, rs);
1871 }
1872 }
1873
1874 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1875 *<shifter_operand> */
1876 snprintf(instruction->text,
1877 128,
1878 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1879 address,
1880 opcode,
1881 mnemonic,
1882 COND(opcode),
1883 (s) ? "S" : "",
1884 rd,
1885 rn,
1886 shifter_operand);
1887 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1888 *<shifter_operand> */
1889 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1890 snprintf(instruction->text,
1891 128,
1892 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1893 address,
1894 opcode);
1895 else
1896 snprintf(instruction->text,
1897 128,
1898 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1899 address,
1900 opcode,
1901 mnemonic,
1902 COND(opcode),
1903 (s) ? "S" : "",
1904 rd,
1905 shifter_operand);
1906 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1907 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1908 address, opcode, mnemonic, COND(opcode),
1909 rn, shifter_operand);
1910 }
1911
1912 return ERROR_OK;
1913 }
1914
1915 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1916 struct arm_instruction *instruction)
1917 {
1918 /* clear fields, to avoid confusion */
1919 memset(instruction, 0, sizeof(struct arm_instruction));
1920 instruction->opcode = opcode;
1921 instruction->instruction_size = 4;
1922
1923 /* catch opcodes with condition field [31:28] = b1111 */
1924 if ((opcode & 0xf0000000) == 0xf0000000) {
1925 /* Undefined instruction (or ARMv5E cache preload PLD) */
1926 if ((opcode & 0x08000000) == 0x00000000)
1927 return evaluate_pld(opcode, address, instruction);
1928
1929 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1930 if ((opcode & 0x0e000000) == 0x08000000)
1931 return evaluate_srs(opcode, address, instruction);
1932
1933 /* Branch and branch with link and change to Thumb */
1934 if ((opcode & 0x0e000000) == 0x0a000000)
1935 return evaluate_blx_imm(opcode, address, instruction);
1936
1937 /* Extended coprocessor opcode space (ARMv5 and higher)
1938 * Coprocessor load/store and double register transfers */
1939 if ((opcode & 0x0e000000) == 0x0c000000)
1940 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1941
1942 /* Coprocessor data processing */
1943 if ((opcode & 0x0f000100) == 0x0c000000)
1944 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1945
1946 /* Coprocessor register transfers */
1947 if ((opcode & 0x0f000010) == 0x0c000010)
1948 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1949
1950 /* Undefined instruction */
1951 if ((opcode & 0x0f000000) == 0x0f000000) {
1952 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1953 snprintf(instruction->text,
1954 128,
1955 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1956 address,
1957 opcode);
1958 return ERROR_OK;
1959 }
1960 }
1961
1962 /* catch opcodes with [27:25] = b000 */
1963 if ((opcode & 0x0e000000) == 0x00000000) {
1964 /* Multiplies, extra load/stores */
1965 if ((opcode & 0x00000090) == 0x00000090)
1966 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1967
1968 /* Miscellaneous instructions */
1969 if ((opcode & 0x0f900000) == 0x01000000)
1970 return evaluate_misc_instr(opcode, address, instruction);
1971
1972 return evaluate_data_proc(opcode, address, instruction);
1973 }
1974
1975 /* catch opcodes with [27:25] = b001 */
1976 if ((opcode & 0x0e000000) == 0x02000000) {
1977 /* 16-bit immediate load */
1978 if ((opcode & 0x0fb00000) == 0x03000000)
1979 return evaluate_mov_imm(opcode, address, instruction);
1980
1981 /* Move immediate to status register */
1982 if ((opcode & 0x0fb00000) == 0x03200000)
1983 return evaluate_mrs_msr(opcode, address, instruction);
1984
1985 return evaluate_data_proc(opcode, address, instruction);
1986
1987 }
1988
1989 /* catch opcodes with [27:25] = b010 */
1990 if ((opcode & 0x0e000000) == 0x04000000) {
1991 /* Load/store immediate offset */
1992 return evaluate_load_store(opcode, address, instruction);
1993 }
1994
1995 /* catch opcodes with [27:25] = b011 */
1996 if ((opcode & 0x0e000000) == 0x06000000) {
1997 /* Load/store register offset */
1998 if ((opcode & 0x00000010) == 0x00000000)
1999 return evaluate_load_store(opcode, address, instruction);
2000
2001 /* Architecturally Undefined instruction
2002 * ... don't expect these to ever be used
2003 */
2004 if ((opcode & 0x07f000f0) == 0x07f000f0) {
2005 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2006 snprintf(instruction->text, 128,
2007 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
2008 address, opcode);
2009 return ERROR_OK;
2010 }
2011
2012 /* "media" instructions */
2013 return evaluate_media(opcode, address, instruction);
2014 }
2015
2016 /* catch opcodes with [27:25] = b100 */
2017 if ((opcode & 0x0e000000) == 0x08000000) {
2018 /* Load/store multiple */
2019 return evaluate_ldm_stm(opcode, address, instruction);
2020 }
2021
2022 /* catch opcodes with [27:25] = b101 */
2023 if ((opcode & 0x0e000000) == 0x0a000000) {
2024 /* Branch and branch with link */
2025 return evaluate_b_bl(opcode, address, instruction);
2026 }
2027
2028 /* catch opcodes with [27:25] = b110 */
2029 if ((opcode & 0x0e000000) == 0x0c000000) {
2030 /* Coprocessor load/store and double register transfers */
2031 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
2032 }
2033
2034 /* catch opcodes with [27:25] = b111 */
2035 if ((opcode & 0x0e000000) == 0x0e000000) {
2036 /* Software interrupt */
2037 if ((opcode & 0x0f000000) == 0x0f000000)
2038 return evaluate_swi(opcode, address, instruction);
2039
2040 /* Coprocessor data processing */
2041 if ((opcode & 0x0f000010) == 0x0e000000)
2042 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2043
2044 /* Coprocessor register transfers */
2045 if ((opcode & 0x0f000010) == 0x0e000010)
2046 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2047 }
2048
2049 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
2050 (unsigned) opcode);
2051 return -1;
2052 }
2053
2054 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
2055 uint32_t address, struct arm_instruction *instruction)
2056 {
2057 uint32_t offset = opcode & 0x7ff;
2058 uint32_t opc = (opcode >> 11) & 0x3;
2059 uint32_t target_address;
2060 char *mnemonic = NULL;
2061
2062 /* sign extend 11-bit offset */
2063 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
2064 offset = 0xfffff800 | offset;
2065
2066 target_address = address + 4 + (offset << 1);
2067
2068 switch (opc) {
2069 /* unconditional branch */
2070 case 0:
2071 instruction->type = ARM_B;
2072 mnemonic = "B";
2073 break;
2074 /* BLX suffix */
2075 case 1:
2076 instruction->type = ARM_BLX;
2077 mnemonic = "BLX";
2078 target_address &= 0xfffffffc;
2079 break;
2080 /* BL/BLX prefix */
2081 case 2:
2082 instruction->type = ARM_UNKNOWN_INSTRUCTION;
2083 mnemonic = "prefix";
2084 target_address = offset << 12;
2085 break;
2086 /* BL suffix */
2087 case 3:
2088 instruction->type = ARM_BL;
2089 mnemonic = "BL";
2090 break;
2091 }
2092
2093 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2094 * these are effectively 32-bit instructions even in Thumb1. For
2095 * disassembly, it's simplest to always use the Thumb2 decoder.
2096 *
2097 * But some cores will evidently handle them as two instructions,
2098 * where exceptions may occur between the two. The ETMv3.2+ ID
2099 * register has a bit which exposes this behavior.
2100 */
2101
2102 snprintf(instruction->text, 128,
2103 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2104 address, opcode, mnemonic, target_address);
2105
2106 instruction->info.b_bl_bx_blx.reg_operand = -1;
2107 instruction->info.b_bl_bx_blx.target_address = target_address;
2108
2109 return ERROR_OK;
2110 }
2111
2112 static int evaluate_add_sub_thumb(uint16_t opcode,
2113 uint32_t address, struct arm_instruction *instruction)
2114 {
2115 uint8_t rd = (opcode >> 0) & 0x7;
2116 uint8_t rn = (opcode >> 3) & 0x7;
2117 uint8_t rm_imm = (opcode >> 6) & 0x7;
2118 uint32_t opc = opcode & (1 << 9);
2119 uint32_t reg_imm = opcode & (1 << 10);
2120 char *mnemonic;
2121
2122 if (opc) {
2123 instruction->type = ARM_SUB;
2124 mnemonic = "SUBS";
2125 } else {
2126 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2127 instruction->type = ARM_ADD;
2128 mnemonic = "ADDS";
2129 }
2130
2131 instruction->info.data_proc.rd = rd;
2132 instruction->info.data_proc.rn = rn;
2133 instruction->info.data_proc.s = 1;
2134
2135 if (reg_imm) {
2136 instruction->info.data_proc.variant = 0;/*immediate*/
2137 instruction->info.data_proc.shifter_operand.immediate.immediate = rm_imm;
2138 snprintf(instruction->text, 128,
2139 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2140 address, opcode, mnemonic, rd, rn, rm_imm);
2141 } else {
2142 instruction->info.data_proc.variant = 1;/*immediate shift*/
2143 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm_imm;
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2146 address, opcode, mnemonic, rd, rn, rm_imm);
2147 }
2148
2149 return ERROR_OK;
2150 }
2151
2152 static int evaluate_shift_imm_thumb(uint16_t opcode,
2153 uint32_t address, struct arm_instruction *instruction)
2154 {
2155 uint8_t rd = (opcode >> 0) & 0x7;
2156 uint8_t rm = (opcode >> 3) & 0x7;
2157 uint8_t imm = (opcode >> 6) & 0x1f;
2158 uint8_t opc = (opcode >> 11) & 0x3;
2159 char *mnemonic = NULL;
2160
2161 switch (opc) {
2162 case 0:
2163 instruction->type = ARM_MOV;
2164 mnemonic = "LSLS";
2165 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2166 break;
2167 case 1:
2168 instruction->type = ARM_MOV;
2169 mnemonic = "LSRS";
2170 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2171 break;
2172 case 2:
2173 instruction->type = ARM_MOV;
2174 mnemonic = "ASRS";
2175 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2176 break;
2177 }
2178
2179 if ((imm == 0) && (opc != 0))
2180 imm = 32;
2181
2182 instruction->info.data_proc.rd = rd;
2183 instruction->info.data_proc.rn = -1;
2184 instruction->info.data_proc.s = 1;
2185
2186 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2187 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2188 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2189
2190 snprintf(instruction->text, 128,
2191 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2192 address, opcode, mnemonic, rd, rm, imm);
2193
2194 return ERROR_OK;
2195 }
2196
2197 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2198 uint32_t address, struct arm_instruction *instruction)
2199 {
2200 uint8_t imm = opcode & 0xff;
2201 uint8_t rd = (opcode >> 8) & 0x7;
2202 uint32_t opc = (opcode >> 11) & 0x3;
2203 char *mnemonic = NULL;
2204
2205 instruction->info.data_proc.rd = rd;
2206 instruction->info.data_proc.rn = rd;
2207 instruction->info.data_proc.s = 1;
2208 instruction->info.data_proc.variant = 0;/*immediate*/
2209 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2210
2211 switch (opc) {
2212 case 0:
2213 instruction->type = ARM_MOV;
2214 mnemonic = "MOVS";
2215 instruction->info.data_proc.rn = -1;
2216 break;
2217 case 1:
2218 instruction->type = ARM_CMP;
2219 mnemonic = "CMP";
2220 instruction->info.data_proc.rd = -1;
2221 break;
2222 case 2:
2223 instruction->type = ARM_ADD;
2224 mnemonic = "ADDS";
2225 break;
2226 case 3:
2227 instruction->type = ARM_SUB;
2228 mnemonic = "SUBS";
2229 break;
2230 }
2231
2232 snprintf(instruction->text, 128,
2233 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2234 address, opcode, mnemonic, rd, imm);
2235
2236 return ERROR_OK;
2237 }
2238
2239 static int evaluate_data_proc_thumb(uint16_t opcode,
2240 uint32_t address, struct arm_instruction *instruction)
2241 {
2242 uint8_t high_reg, op, rm, rd, h1, h2;
2243 char *mnemonic = NULL;
2244 bool nop = false;
2245
2246 high_reg = (opcode & 0x0400) >> 10;
2247 op = (opcode & 0x03C0) >> 6;
2248
2249 rd = (opcode & 0x0007);
2250 rm = (opcode & 0x0038) >> 3;
2251 h1 = (opcode & 0x0080) >> 7;
2252 h2 = (opcode & 0x0040) >> 6;
2253
2254 instruction->info.data_proc.rd = rd;
2255 instruction->info.data_proc.rn = rd;
2256 instruction->info.data_proc.s = (!high_reg || (instruction->type == ARM_CMP));
2257 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2258 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2259
2260 if (high_reg) {
2261 rd |= h1 << 3;
2262 rm |= h2 << 3;
2263 op >>= 2;
2264
2265 switch (op) {
2266 case 0x0:
2267 instruction->type = ARM_ADD;
2268 mnemonic = "ADD";
2269 break;
2270 case 0x1:
2271 instruction->type = ARM_CMP;
2272 mnemonic = "CMP";
2273 break;
2274 case 0x2:
2275 instruction->type = ARM_MOV;
2276 mnemonic = "MOV";
2277 if (rd == rm)
2278 nop = true;
2279 break;
2280 case 0x3:
2281 if ((opcode & 0x7) == 0x0) {
2282 instruction->info.b_bl_bx_blx.reg_operand = rm;
2283 if (h1) {
2284 instruction->type = ARM_BLX;
2285 snprintf(instruction->text, 128,
2286 "0x%8.8" PRIx32
2287 " 0x%4.4x \tBLX\tr%i",
2288 address, opcode, rm);
2289 } else {
2290 instruction->type = ARM_BX;
2291 snprintf(instruction->text, 128,
2292 "0x%8.8" PRIx32
2293 " 0x%4.4x \tBX\tr%i",
2294 address, opcode, rm);
2295 }
2296 } else {
2297 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2298 snprintf(instruction->text, 128,
2299 "0x%8.8" PRIx32
2300 " 0x%4.4x \t"
2301 "UNDEFINED INSTRUCTION",
2302 address, opcode);
2303 }
2304 return ERROR_OK;
2305 }
2306 } else {
2307 switch (op) {
2308 case 0x0:
2309 instruction->type = ARM_AND;
2310 mnemonic = "ANDS";
2311 break;
2312 case 0x1:
2313 instruction->type = ARM_EOR;
2314 mnemonic = "EORS";
2315 break;
2316 case 0x2:
2317 instruction->type = ARM_MOV;
2318 mnemonic = "LSLS";
2319 instruction->info.data_proc.variant = 2 /*register shift*/;
2320 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2321 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2322 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2323 break;
2324 case 0x3:
2325 instruction->type = ARM_MOV;
2326 mnemonic = "LSRS";
2327 instruction->info.data_proc.variant = 2 /*register shift*/;
2328 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2329 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2330 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2331 break;
2332 case 0x4:
2333 instruction->type = ARM_MOV;
2334 mnemonic = "ASRS";
2335 instruction->info.data_proc.variant = 2 /*register shift*/;
2336 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2337 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2338 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2339 break;
2340 case 0x5:
2341 instruction->type = ARM_ADC;
2342 mnemonic = "ADCS";
2343 break;
2344 case 0x6:
2345 instruction->type = ARM_SBC;
2346 mnemonic = "SBCS";
2347 break;
2348 case 0x7:
2349 instruction->type = ARM_MOV;
2350 mnemonic = "RORS";
2351 instruction->info.data_proc.variant = 2 /*register shift*/;
2352 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2353 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2354 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2355 break;
2356 case 0x8:
2357 instruction->type = ARM_TST;
2358 mnemonic = "TST";
2359 break;
2360 case 0x9:
2361 instruction->type = ARM_RSB;
2362 mnemonic = "RSBS";
2363 instruction->info.data_proc.variant = 0 /*immediate*/;
2364 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2365 instruction->info.data_proc.rn = rm;
2366 break;
2367 case 0xA:
2368 instruction->type = ARM_CMP;
2369 mnemonic = "CMP";
2370 break;
2371 case 0xB:
2372 instruction->type = ARM_CMN;
2373 mnemonic = "CMN";
2374 break;
2375 case 0xC:
2376 instruction->type = ARM_ORR;
2377 mnemonic = "ORRS";
2378 break;
2379 case 0xD:
2380 instruction->type = ARM_MUL;
2381 mnemonic = "MULS";
2382 break;
2383 case 0xE:
2384 instruction->type = ARM_BIC;
2385 mnemonic = "BICS";
2386 break;
2387 case 0xF:
2388 instruction->type = ARM_MVN;
2389 mnemonic = "MVNS";
2390 break;
2391 }
2392 }
2393
2394 if (nop)
2395 snprintf(instruction->text, 128,
2396 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2397 "; (%s r%i, r%i)",
2398 address, opcode, mnemonic, rd, rm);
2399 else
2400 snprintf(instruction->text, 128,
2401 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2402 address, opcode, mnemonic, rd, rm);
2403
2404 return ERROR_OK;
2405 }
2406
2407 /* PC-relative data addressing is word-aligned even with Thumb */
2408 static inline uint32_t thumb_alignpc4(uint32_t addr)
2409 {
2410 return (addr + 4) & ~3;
2411 }
2412
2413 static int evaluate_load_literal_thumb(uint16_t opcode,
2414 uint32_t address, struct arm_instruction *instruction)
2415 {
2416 uint32_t immediate;
2417 uint8_t rd = (opcode >> 8) & 0x7;
2418
2419 instruction->type = ARM_LDR;
2420 immediate = opcode & 0x000000ff;
2421 immediate *= 4;
2422
2423 instruction->info.load_store.rd = rd;
2424 instruction->info.load_store.rn = 15 /*PC*/;
2425 instruction->info.load_store.index_mode = 0; /*offset*/
2426 instruction->info.load_store.offset_mode = 0; /*immediate*/
2427 instruction->info.load_store.offset.offset = immediate;
2428
2429 snprintf(instruction->text, 128,
2430 "0x%8.8" PRIx32 " 0x%4.4x \t"
2431 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2432 address, opcode, rd, immediate,
2433 thumb_alignpc4(address) + immediate);
2434
2435 return ERROR_OK;
2436 }
2437
2438 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2439 uint32_t address, struct arm_instruction *instruction)
2440 {
2441 uint8_t rd = (opcode >> 0) & 0x7;
2442 uint8_t rn = (opcode >> 3) & 0x7;
2443 uint8_t rm = (opcode >> 6) & 0x7;
2444 uint8_t opc = (opcode >> 9) & 0x7;
2445 char *mnemonic = NULL;
2446
2447 switch (opc) {
2448 case 0:
2449 instruction->type = ARM_STR;
2450 mnemonic = "STR";
2451 break;
2452 case 1:
2453 instruction->type = ARM_STRH;
2454 mnemonic = "STRH";
2455 break;
2456 case 2:
2457 instruction->type = ARM_STRB;
2458 mnemonic = "STRB";
2459 break;
2460 case 3:
2461 instruction->type = ARM_LDRSB;
2462 mnemonic = "LDRSB";
2463 break;
2464 case 4:
2465 instruction->type = ARM_LDR;
2466 mnemonic = "LDR";
2467 break;
2468 case 5:
2469 instruction->type = ARM_LDRH;
2470 mnemonic = "LDRH";
2471 break;
2472 case 6:
2473 instruction->type = ARM_LDRB;
2474 mnemonic = "LDRB";
2475 break;
2476 case 7:
2477 instruction->type = ARM_LDRSH;
2478 mnemonic = "LDRSH";
2479 break;
2480 }
2481
2482 snprintf(instruction->text, 128,
2483 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2484 address, opcode, mnemonic, rd, rn, rm);
2485
2486 instruction->info.load_store.rd = rd;
2487 instruction->info.load_store.rn = rn;
2488 instruction->info.load_store.index_mode = 0; /*offset*/
2489 instruction->info.load_store.offset_mode = 1; /*register*/
2490 instruction->info.load_store.offset.reg.rm = rm;
2491
2492 return ERROR_OK;
2493 }
2494
2495 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2496 uint32_t address, struct arm_instruction *instruction)
2497 {
2498 uint32_t offset = (opcode >> 6) & 0x1f;
2499 uint8_t rd = (opcode >> 0) & 0x7;
2500 uint8_t rn = (opcode >> 3) & 0x7;
2501 uint32_t l = opcode & (1 << 11);
2502 uint32_t b = opcode & (1 << 12);
2503 char *mnemonic;
2504 char suffix = ' ';
2505 uint32_t shift = 2;
2506
2507 if (l) {
2508 instruction->type = ARM_LDR;
2509 mnemonic = "LDR";
2510 } else {
2511 instruction->type = ARM_STR;
2512 mnemonic = "STR";
2513 }
2514
2515 if ((opcode&0xF000) == 0x8000) {
2516 suffix = 'H';
2517 shift = 1;
2518 } else if (b) {
2519 suffix = 'B';
2520 shift = 0;
2521 }
2522
2523 snprintf(instruction->text, 128,
2524 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2525 address, opcode, mnemonic, suffix, rd, rn, offset << shift);
2526
2527 instruction->info.load_store.rd = rd;
2528 instruction->info.load_store.rn = rn;
2529 instruction->info.load_store.index_mode = 0; /*offset*/
2530 instruction->info.load_store.offset_mode = 0; /*immediate*/
2531 instruction->info.load_store.offset.offset = offset << shift;
2532
2533 return ERROR_OK;
2534 }
2535
2536 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2537 uint32_t address, struct arm_instruction *instruction)
2538 {
2539 uint32_t offset = opcode & 0xff;
2540 uint8_t rd = (opcode >> 8) & 0x7;
2541 uint32_t l = opcode & (1 << 11);
2542 char *mnemonic;
2543
2544 if (l) {
2545 instruction->type = ARM_LDR;
2546 mnemonic = "LDR";
2547 } else {
2548 instruction->type = ARM_STR;
2549 mnemonic = "STR";
2550 }
2551
2552 snprintf(instruction->text, 128,
2553 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2554 address, opcode, mnemonic, rd, offset*4);
2555
2556 instruction->info.load_store.rd = rd;
2557 instruction->info.load_store.rn = 13 /*SP*/;
2558 instruction->info.load_store.index_mode = 0; /*offset*/
2559 instruction->info.load_store.offset_mode = 0; /*immediate*/
2560 instruction->info.load_store.offset.offset = offset*4;
2561
2562 return ERROR_OK;
2563 }
2564
2565 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2566 uint32_t address, struct arm_instruction *instruction)
2567 {
2568 uint32_t imm = opcode & 0xff;
2569 uint8_t rd = (opcode >> 8) & 0x7;
2570 uint8_t rn;
2571 uint32_t sp = opcode & (1 << 11);
2572 const char *reg_name;
2573
2574 instruction->type = ARM_ADD;
2575
2576 if (sp) {
2577 reg_name = "SP";
2578 rn = 13;
2579 } else {
2580 reg_name = "PC";
2581 rn = 15;
2582 }
2583
2584 snprintf(instruction->text, 128,
2585 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2586 address, opcode, rd, reg_name, imm * 4);
2587
2588 instruction->info.data_proc.variant = 0 /* immediate */;
2589 instruction->info.data_proc.rd = rd;
2590 instruction->info.data_proc.rn = rn;
2591 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2592
2593 return ERROR_OK;
2594 }
2595
2596 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2597 uint32_t address, struct arm_instruction *instruction)
2598 {
2599 uint32_t imm = opcode & 0x7f;
2600 uint8_t opc = opcode & (1 << 7);
2601 char *mnemonic;
2602
2603
2604 if (opc) {
2605 instruction->type = ARM_SUB;
2606 mnemonic = "SUB";
2607 } else {
2608 instruction->type = ARM_ADD;
2609 mnemonic = "ADD";
2610 }
2611
2612 snprintf(instruction->text, 128,
2613 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2614 address, opcode, mnemonic, imm*4);
2615
2616 instruction->info.data_proc.variant = 0 /* immediate */;
2617 instruction->info.data_proc.rd = 13 /*SP*/;
2618 instruction->info.data_proc.rn = 13 /*SP*/;
2619 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2620
2621 return ERROR_OK;
2622 }
2623
2624 static int evaluate_breakpoint_thumb(uint16_t opcode,
2625 uint32_t address, struct arm_instruction *instruction)
2626 {
2627 uint32_t imm = opcode & 0xff;
2628
2629 instruction->type = ARM_BKPT;
2630
2631 snprintf(instruction->text, 128,
2632 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2633 address, opcode, imm);
2634
2635 return ERROR_OK;
2636 }
2637
2638 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2639 uint32_t address, struct arm_instruction *instruction)
2640 {
2641 uint32_t reg_list = opcode & 0xff;
2642 uint32_t l = opcode & (1 << 11);
2643 uint32_t r = opcode & (1 << 8);
2644 uint8_t rn = (opcode >> 8) & 7;
2645 uint8_t addr_mode = 0 /* IA */;
2646 char reg_names[40];
2647 char *reg_names_p;
2648 char *mnemonic;
2649 char ptr_name[7] = "";
2650 int i;
2651
2652 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2653 * The STMIA and LDMIA opcodes are used for other instructions.
2654 */
2655
2656 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2657 char *wback = "!";
2658
2659 if (l) {
2660 instruction->type = ARM_LDM;
2661 mnemonic = "LDM";
2662 if (opcode & (1 << rn))
2663 wback = "";
2664 } else {
2665 instruction->type = ARM_STM;
2666 mnemonic = "STM";
2667 }
2668 snprintf(ptr_name, sizeof(ptr_name), "r%i%s, ", rn, wback);
2669 } else {/* push/pop */
2670 rn = 13;/* SP */
2671 if (l) {
2672 instruction->type = ARM_LDM;
2673 mnemonic = "POP";
2674 if (r)
2675 reg_list |= (1 << 15) /*PC*/;
2676 } else {
2677 instruction->type = ARM_STM;
2678 mnemonic = "PUSH";
2679 addr_mode = 3; /*DB*/
2680 if (r)
2681 reg_list |= (1 << 14) /*LR*/;
2682 }
2683 }
2684
2685 reg_names_p = reg_names;
2686 for (i = 0; i <= 15; i++) {
2687 if (reg_list & (1 << i))
2688 reg_names_p += snprintf(reg_names_p,
2689 (reg_names + 40 - reg_names_p),
2690 "r%i, ",
2691 i);
2692 }
2693 if (reg_names_p > reg_names)
2694 reg_names_p[-2] = '\0';
2695 else /* invalid op : no registers */
2696 reg_names[0] = '\0';
2697
2698 snprintf(instruction->text, 128,
2699 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2700 address, opcode, mnemonic, ptr_name, reg_names);
2701
2702 instruction->info.load_store_multiple.register_list = reg_list;
2703 instruction->info.load_store_multiple.rn = rn;
2704 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2705
2706 return ERROR_OK;
2707 }
2708
2709 static int evaluate_cond_branch_thumb(uint16_t opcode,
2710 uint32_t address, struct arm_instruction *instruction)
2711 {
2712 uint32_t offset = opcode & 0xff;
2713 uint8_t cond = (opcode >> 8) & 0xf;
2714 uint32_t target_address;
2715
2716 if (cond == 0xf) {
2717 instruction->type = ARM_SWI;
2718 snprintf(instruction->text, 128,
2719 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2720 address, opcode, offset);
2721 return ERROR_OK;
2722 } else if (cond == 0xe) {
2723 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2724 snprintf(instruction->text, 128,
2725 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2726 address, opcode);
2727 return ERROR_OK;
2728 }
2729
2730 /* sign extend 8-bit offset */
2731 if (offset & 0x00000080)
2732 offset = 0xffffff00 | offset;
2733
2734 target_address = address + 4 + (offset << 1);
2735
2736 snprintf(instruction->text, 128,
2737 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2738 address, opcode,
2739 arm_condition_strings[cond], target_address);
2740
2741 instruction->type = ARM_B;
2742 instruction->info.b_bl_bx_blx.reg_operand = -1;
2743 instruction->info.b_bl_bx_blx.target_address = target_address;
2744
2745 return ERROR_OK;
2746 }
2747
2748 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2749 struct arm_instruction *instruction)
2750 {
2751 unsigned offset;
2752
2753 /* added in Thumb2 */
2754 offset = (opcode >> 3) & 0x1f;
2755 offset |= (opcode & 0x0200) >> 4;
2756
2757 snprintf(instruction->text, 128,
2758 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2759 address, opcode,
2760 (opcode & 0x0800) ? "N" : "",
2761 opcode & 0x7, address + 4 + (offset << 1));
2762
2763 return ERROR_OK;
2764 }
2765
2766 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2767 struct arm_instruction *instruction)
2768 {
2769 /* added in ARMv6 */
2770 snprintf(instruction->text, 128,
2771 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2772 address, opcode,
2773 (opcode & 0x0080) ? 'U' : 'S',
2774 (opcode & 0x0040) ? 'B' : 'H',
2775 opcode & 0x7, (opcode >> 3) & 0x7);
2776
2777 return ERROR_OK;
2778 }
2779
2780 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2781 struct arm_instruction *instruction)
2782 {
2783 /* added in ARMv6 */
2784 if ((opcode & 0x0ff0) == 0x0650)
2785 snprintf(instruction->text, 128,
2786 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2787 address, opcode,
2788 (opcode & 0x80) ? "BE" : "LE");
2789 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2790 snprintf(instruction->text, 128,
2791 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2792 address, opcode,
2793 (opcode & 0x0010) ? 'D' : 'E',
2794 (opcode & 0x0004) ? "A" : "",
2795 (opcode & 0x0002) ? "I" : "",
2796 (opcode & 0x0001) ? "F" : "");
2797
2798 return ERROR_OK;
2799 }
2800
2801 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2802 struct arm_instruction *instruction)
2803 {
2804 char *suffix;
2805
2806 /* added in ARMv6 */
2807 switch ((opcode >> 6) & 3) {
2808 case 0:
2809 suffix = "";
2810 break;
2811 case 1:
2812 suffix = "16";
2813 break;
2814 default:
2815 suffix = "SH";
2816 break;
2817 }
2818 snprintf(instruction->text, 128,
2819 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2820 address, opcode, suffix,
2821 opcode & 0x7, (opcode >> 3) & 0x7);
2822
2823 return ERROR_OK;
2824 }
2825
2826 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2827 struct arm_instruction *instruction)
2828 {
2829 char *hint;
2830
2831 switch ((opcode >> 4) & 0x0f) {
2832 case 0:
2833 hint = "NOP";
2834 break;
2835 case 1:
2836 hint = "YIELD";
2837 break;
2838 case 2:
2839 hint = "WFE";
2840 break;
2841 case 3:
2842 hint = "WFI";
2843 break;
2844 case 4:
2845 hint = "SEV";
2846 break;
2847 default:
2848 hint = "HINT (UNRECOGNIZED)";
2849 break;
2850 }
2851
2852 snprintf(instruction->text, 128,
2853 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2854 address, opcode, hint);
2855
2856 return ERROR_OK;
2857 }
2858
2859 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2860 struct arm_instruction *instruction)
2861 {
2862 unsigned cond = (opcode >> 4) & 0x0f;
2863 char *x = "", *y = "", *z = "";
2864
2865 if (opcode & 0x01)
2866 z = (opcode & 0x02) ? "T" : "E";
2867 if (opcode & 0x03)
2868 y = (opcode & 0x04) ? "T" : "E";
2869 if (opcode & 0x07)
2870 x = (opcode & 0x08) ? "T" : "E";
2871
2872 snprintf(instruction->text, 128,
2873 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2874 address, opcode,
2875 x, y, z, arm_condition_strings[cond]);
2876
2877 /* NOTE: strictly speaking, the next 1-4 instructions should
2878 * now be displayed with the relevant conditional suffix...
2879 */
2880
2881 return ERROR_OK;
2882 }
2883
2884 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2885 {
2886 /* clear fields, to avoid confusion */
2887 memset(instruction, 0, sizeof(struct arm_instruction));
2888 instruction->opcode = opcode;
2889 instruction->instruction_size = 2;
2890
2891 if ((opcode & 0xe000) == 0x0000) {
2892 /* add/subtract register or immediate */
2893 if ((opcode & 0x1800) == 0x1800)
2894 return evaluate_add_sub_thumb(opcode, address, instruction);
2895 /* shift by immediate */
2896 else
2897 return evaluate_shift_imm_thumb(opcode, address, instruction);
2898 }
2899
2900 /* Add/subtract/compare/move immediate */
2901 if ((opcode & 0xe000) == 0x2000)
2902 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2903
2904 /* Data processing instructions */
2905 if ((opcode & 0xf800) == 0x4000)
2906 return evaluate_data_proc_thumb(opcode, address, instruction);
2907
2908 /* Load from literal pool */
2909 if ((opcode & 0xf800) == 0x4800)
2910 return evaluate_load_literal_thumb(opcode, address, instruction);
2911
2912 /* Load/Store register offset */
2913 if ((opcode & 0xf000) == 0x5000)
2914 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2915
2916 /* Load/Store immediate offset */
2917 if (((opcode & 0xe000) == 0x6000)
2918 || ((opcode & 0xf000) == 0x8000))
2919 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2920
2921 /* Load/Store from/to stack */
2922 if ((opcode & 0xf000) == 0x9000)
2923 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2924
2925 /* Add to SP/PC */
2926 if ((opcode & 0xf000) == 0xa000)
2927 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2928
2929 /* Misc */
2930 if ((opcode & 0xf000) == 0xb000) {
2931 switch ((opcode >> 8) & 0x0f) {
2932 case 0x0:
2933 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2934 case 0x1:
2935 case 0x3:
2936 case 0x9:
2937 case 0xb:
2938 return evaluate_cb_thumb(opcode, address, instruction);
2939 case 0x2:
2940 return evaluate_extend_thumb(opcode, address, instruction);
2941 case 0x4:
2942 case 0x5:
2943 case 0xc:
2944 case 0xd:
2945 return evaluate_load_store_multiple_thumb(opcode, address,
2946 instruction);
2947 case 0x6:
2948 return evaluate_cps_thumb(opcode, address, instruction);
2949 case 0xa:
2950 if ((opcode & 0x00c0) == 0x0080)
2951 break;
2952 return evaluate_byterev_thumb(opcode, address, instruction);
2953 case 0xe:
2954 return evaluate_breakpoint_thumb(opcode, address, instruction);
2955 case 0xf:
2956 if (opcode & 0x000f)
2957 return evaluate_ifthen_thumb(opcode, address,
2958 instruction);
2959 else
2960 return evaluate_hint_thumb(opcode, address,
2961 instruction);
2962 }
2963
2964 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2965 snprintf(instruction->text, 128,
2966 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2967 address, opcode);
2968 return ERROR_OK;
2969 }
2970
2971 /* Load/Store multiple */
2972 if ((opcode & 0xf000) == 0xc000)
2973 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2974
2975 /* Conditional branch + SWI */
2976 if ((opcode & 0xf000) == 0xd000)
2977 return evaluate_cond_branch_thumb(opcode, address, instruction);
2978
2979 if ((opcode & 0xe000) == 0xe000) {
2980 /* Undefined instructions */
2981 if ((opcode & 0xf801) == 0xe801) {
2982 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2983 snprintf(instruction->text, 128,
2984 "0x%8.8" PRIx32 " 0x%8.8x\t"
2985 "UNDEFINED INSTRUCTION",
2986 address, opcode);
2987 return ERROR_OK;
2988 } else /* Branch to offset */
2989 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2990 }
2991
2992 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2993 return -1;
2994 }
2995
2996 int arm_access_size(struct arm_instruction *instruction)
2997 {
2998 if ((instruction->type == ARM_LDRB)
2999 || (instruction->type == ARM_LDRBT)
3000 || (instruction->type == ARM_LDRSB)
3001 || (instruction->type == ARM_STRB)
3002 || (instruction->type == ARM_STRBT))
3003 return 1;
3004 else if ((instruction->type == ARM_LDRH)
3005 || (instruction->type == ARM_LDRSH)
3006 || (instruction->type == ARM_STRH))
3007 return 2;
3008 else if ((instruction->type == ARM_LDR)
3009 || (instruction->type == ARM_LDRT)
3010 || (instruction->type == ARM_STR)
3011 || (instruction->type == ARM_STRT))
3012 return 4;
3013 else if ((instruction->type == ARM_LDRD)
3014 || (instruction->type == ARM_STRD))
3015 return 8;
3016 else {
3017 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
3018 instruction->type);
3019 return 0;
3020 }
3021 }
3022
3023 #if HAVE_CAPSTONE
3024 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
3025 {
3026 uint32_t opcode = 0;
3027
3028 memcpy(&opcode, insn->bytes, insn->size);
3029
3030 if (insn->size == 4) {
3031 uint16_t opcode_high = opcode >> 16;
3032 opcode = opcode & 0xffff;
3033
3034 command_print(cmd, "0x%08" PRIx64" %04x %04x\t%s%s%s",
3035 insn->address, opcode, opcode_high, insn->mnemonic,
3036 insn->op_str[0] ? "\t" : "", insn->op_str);
3037 } else {
3038 command_print(cmd, "0x%08" PRIx64" %04x\t%s%s%s",
3039 insn->address, opcode, insn->mnemonic,
3040 insn->op_str[0] ? "\t" : "", insn->op_str);
3041 }
3042 }
3043
3044 int arm_disassemble(struct command_invocation *cmd, struct target *target,
3045 target_addr_t address, size_t count, bool thumb_mode)
3046 {
3047 csh handle;
3048 int ret;
3049 cs_insn *insn;
3050 cs_mode mode;
3051
3052 if (!cs_support(CS_ARCH_ARM)) {
3053 LOG_ERROR("ARM architecture not supported by capstone");
3054 return ERROR_FAIL;
3055 }
3056
3057 mode = CS_MODE_LITTLE_ENDIAN;
3058
3059 if (thumb_mode)
3060 mode |= CS_MODE_THUMB;
3061
3062 ret = cs_open(CS_ARCH_ARM, mode, &handle);
3063
3064 if (ret != CS_ERR_OK) {
3065 LOG_ERROR("cs_open() failed: %s", cs_strerror(ret));
3066 return ERROR_FAIL;
3067 }
3068
3069 ret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
3070
3071 if (ret != CS_ERR_OK) {
3072 LOG_ERROR("cs_option() failed: %s", cs_strerror(ret));
3073 cs_close(&handle);
3074 return ERROR_FAIL;
3075 }
3076
3077 insn = cs_malloc(handle);
3078
3079 if (!insn) {
3080 LOG_ERROR("cs_malloc() failed\n");
3081 cs_close(&handle);
3082 return ERROR_FAIL;
3083 }
3084
3085 while (count > 0) {
3086 uint8_t buffer[4];
3087
3088 ret = target_read_buffer(target, address, sizeof(buffer), buffer);
3089
3090 if (ret != ERROR_OK) {
3091 cs_free(insn, 1);
3092 cs_close(&handle);
3093 return ret;
3094 }
3095
3096 size_t size = sizeof(buffer);
3097 const uint8_t *tmp = buffer;
3098
3099 ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
3100
3101 if (!ret) {
3102 LOG_ERROR("cs_disasm_iter() failed: %s",
3103 cs_strerror(cs_errno(handle)));
3104 cs_free(insn, 1);
3105 cs_close(&handle);
3106 return ERROR_FAIL;
3107 }
3108
3109 print_opcode(cmd, insn);
3110 count--;
3111 }
3112
3113 cs_free(insn, 1);
3114 cs_close(&handle);
3115
3116 return ERROR_OK;
3117 }
3118 #endif /* HAVE_CAPSTONE */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)