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