ce338859424d614dba1e2afe7bad7c82b8963a1f
[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, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "target.h"
27 #include "arm_disassembler.h"
28 #include "log.h"
29
30
31 /*
32 * This disassembler supports two main functions for OpenOCD:
33 *
34 * - Various "disassemble" commands. OpenOCD can serve as a
35 * machine-language debugger, without help from GDB.
36 *
37 * - Single stepping. Not all ARM cores support hardware single
38 * stepping. To work without that support, the debugger must
39 * be able to decode instructions to find out where to put a
40 * "next instruction" breakpoint.
41 *
42 * In addition, interpretation of ETM trace data needs some of the
43 * decoding mechanisms.
44 *
45 * At this writing (September 2009) neither function is complete.
46 *
47 * - ARM decoding
48 * * Old-style syntax (not UAL) is generally used
49 * * VFP instructions are not understood (ARMv5 and later)
50 * except as coprocessor 10/11 operations
51 * * Most ARM instructions through ARMv6 are decoded, but some
52 * of the post-ARMv4 opcodes may not be handled yet
53 * * NEON instructions are not understood (ARMv7-A)
54 *
55 * - Thumb/Thumb2 decoding
56 * * UAL syntax should be consistently used
57 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
58 * be handled properly. Accordingly, so should the subset
59 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
60 * ARMv4T and ARMv5T.
61 * * Conditional effects of Thumb2 "IT" (if-then) instructions
62 * are not handled: the affected instructions are not shown
63 * with their now-conditional suffixes.
64 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
65 * handled (minimally for coprocessor access).
66 * * SIMD instructions, and some other Thumb2 instructions
67 * from ARMv7-A, are not understood.
68 *
69 * - ThumbEE decoding
70 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
71 * * Opcodes changed by ThumbEE mode are not handled; these
72 * instructions wrongly decode as LDM and STM.
73 *
74 * - Jazelle decoding ... no support whatsoever for Jazelle mode
75 * or decoding. ARM encourages use of the more generic ThumbEE
76 * mode, instead of Jazelle mode, in current chips.
77 *
78 * - Single-step/emulation ... spotty support, which is only weakly
79 * tested. Thumb2 is not supported. (Arguably a full simulator
80 * is not needed to support just single stepping. Recognizing
81 * branch vs non-branch instructions suffices, except when the
82 * instruction faults and triggers a synchronous exception which
83 * can be intercepted using other means.)
84 *
85 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
86 * ARM v7-R edition" gives the most complete coverage of the various
87 * generations of ARM instructions. At this writing it is publicly
88 * accessible to anyone willing to create an account at the ARM
89 * web site; see http://www.arm.com/documentation/ for information.
90 *
91 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
92 * more details relevant to the Thumb2-only processors (such as
93 * the Cortex-M implementations).
94 */
95
96 /* textual represenation of the condition field */
97 /* ALways (default) is ommitted (empty string) */
98 static const char *arm_condition_strings[] =
99 {
100 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
101 };
102
103 /* make up for C's missing ROR */
104 static uint32_t ror(uint32_t value, int places)
105 {
106 return (value >> places) | (value << (32 - places));
107 }
108
109 static int evaluate_pld(uint32_t opcode,
110 uint32_t address, struct arm_instruction *instruction)
111 {
112 /* PLD */
113 if ((opcode & 0x0d70f000) == 0x0550f000)
114 {
115 instruction->type = ARM_PLD;
116
117 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
118
119 return ERROR_OK;
120 }
121 else
122 {
123 instruction->type = ARM_UNDEFINED_INSTRUCTION;
124 return ERROR_OK;
125 }
126
127 LOG_ERROR("should never reach this point");
128 return -1;
129 }
130
131 static int evaluate_swi(uint32_t opcode,
132 uint32_t address, struct arm_instruction *instruction)
133 {
134 instruction->type = ARM_SWI;
135
136 snprintf(instruction->text, 128,
137 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
138 address, opcode, (opcode & 0xffffff));
139
140 return ERROR_OK;
141 }
142
143 static int evaluate_blx_imm(uint32_t opcode,
144 uint32_t address, struct arm_instruction *instruction)
145 {
146 int offset;
147 uint32_t immediate;
148 uint32_t target_address;
149
150 instruction->type = ARM_BLX;
151 immediate = opcode & 0x00ffffff;
152
153 /* sign extend 24-bit immediate */
154 if (immediate & 0x00800000)
155 offset = 0xff000000 | immediate;
156 else
157 offset = immediate;
158
159 /* shift two bits left */
160 offset <<= 2;
161
162 /* odd/event halfword */
163 if (opcode & 0x01000000)
164 offset |= 0x2;
165
166 target_address = address + 8 + offset;
167
168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
169
170 instruction->info.b_bl_bx_blx.reg_operand = -1;
171 instruction->info.b_bl_bx_blx.target_address = target_address;
172
173 return ERROR_OK;
174 }
175
176 static int evaluate_b_bl(uint32_t opcode,
177 uint32_t address, struct arm_instruction *instruction)
178 {
179 uint8_t L;
180 uint32_t immediate;
181 int offset;
182 uint32_t target_address;
183
184 immediate = opcode & 0x00ffffff;
185 L = (opcode & 0x01000000) >> 24;
186
187 /* sign extend 24-bit immediate */
188 if (immediate & 0x00800000)
189 offset = 0xff000000 | immediate;
190 else
191 offset = immediate;
192
193 /* shift two bits left */
194 offset <<= 2;
195
196 target_address = address + 8 + offset;
197
198 if (L)
199 instruction->type = ARM_BL;
200 else
201 instruction->type = ARM_B;
202
203 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
204 (L) ? "L" : "", COND(opcode), target_address);
205
206 instruction->info.b_bl_bx_blx.reg_operand = -1;
207 instruction->info.b_bl_bx_blx.target_address = target_address;
208
209 return ERROR_OK;
210 }
211
212 /* Coprocessor load/store and double register transfers */
213 /* both normal and extended instruction space (condition field b1111) */
214 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
215 uint32_t address, struct arm_instruction *instruction)
216 {
217 uint8_t cp_num = (opcode & 0xf00) >> 8;
218
219 /* MCRR or MRRC */
220 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
221 {
222 uint8_t cp_opcode, Rd, Rn, CRm;
223 char *mnemonic;
224
225 cp_opcode = (opcode & 0xf0) >> 4;
226 Rd = (opcode & 0xf000) >> 12;
227 Rn = (opcode & 0xf0000) >> 16;
228 CRm = (opcode & 0xf);
229
230 /* MCRR */
231 if ((opcode & 0x0ff00000) == 0x0c400000)
232 {
233 instruction->type = ARM_MCRR;
234 mnemonic = "MCRR";
235 }
236
237 /* MRRC */
238 if ((opcode & 0x0ff00000) == 0x0c500000)
239 {
240 instruction->type = ARM_MRRC;
241 mnemonic = "MRRC";
242 }
243
244 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
245 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
246 }
247 else /* LDC or STC */
248 {
249 uint8_t CRd, Rn, offset;
250 uint8_t U, N;
251 char *mnemonic;
252 char addressing_mode[32];
253
254 CRd = (opcode & 0xf000) >> 12;
255 Rn = (opcode & 0xf0000) >> 16;
256 offset = (opcode & 0xff);
257
258 /* load/store */
259 if (opcode & 0x00100000)
260 {
261 instruction->type = ARM_LDC;
262 mnemonic = "LDC";
263 }
264 else
265 {
266 instruction->type = ARM_STC;
267 mnemonic = "STC";
268 }
269
270 U = (opcode & 0x00800000) >> 23;
271 N = (opcode & 0x00400000) >> 22;
272
273 /* addressing modes */
274 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
275 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
276 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
277 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
278 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
279 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
280 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
281 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
282
283 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
284 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
285 (N) ? "L" : "",
286 cp_num, CRd, addressing_mode);
287 }
288
289 return ERROR_OK;
290 }
291
292 /* Coprocessor data processing instructions */
293 /* Coprocessor register transfer instructions */
294 /* both normal and extended instruction space (condition field b1111) */
295 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
296 uint32_t address, struct arm_instruction *instruction)
297 {
298 const char *cond;
299 char* mnemonic;
300 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
301
302 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
303 cp_num = (opcode & 0xf00) >> 8;
304 CRd_Rd = (opcode & 0xf000) >> 12;
305 CRn = (opcode & 0xf0000) >> 16;
306 CRm = (opcode & 0xf);
307 opcode_2 = (opcode & 0xe0) >> 5;
308
309 /* CDP or MRC/MCR */
310 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
311 {
312 if (opcode & 0x00100000) /* bit 20 set -> MRC */
313 {
314 instruction->type = ARM_MRC;
315 mnemonic = "MRC";
316 }
317 else /* bit 20 not set -> MCR */
318 {
319 instruction->type = ARM_MCR;
320 mnemonic = "MCR";
321 }
322
323 opcode_1 = (opcode & 0x00e00000) >> 21;
324
325 snprintf(instruction->text, 128, "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",
326 address, opcode, mnemonic, cond,
327 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
328 }
329 else /* bit 4 not set -> CDP */
330 {
331 instruction->type = ARM_CDP;
332 mnemonic = "CDP";
333
334 opcode_1 = (opcode & 0x00f00000) >> 20;
335
336 snprintf(instruction->text, 128, "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",
337 address, opcode, mnemonic, cond,
338 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
339 }
340
341 return ERROR_OK;
342 }
343
344 /* Load/store instructions */
345 static int evaluate_load_store(uint32_t opcode,
346 uint32_t address, struct arm_instruction *instruction)
347 {
348 uint8_t I, P, U, B, W, L;
349 uint8_t Rn, Rd;
350 char *operation; /* "LDR" or "STR" */
351 char *suffix; /* "", "B", "T", "BT" */
352 char offset[32];
353
354 /* examine flags */
355 I = (opcode & 0x02000000) >> 25;
356 P = (opcode & 0x01000000) >> 24;
357 U = (opcode & 0x00800000) >> 23;
358 B = (opcode & 0x00400000) >> 22;
359 W = (opcode & 0x00200000) >> 21;
360 L = (opcode & 0x00100000) >> 20;
361
362 /* target register */
363 Rd = (opcode & 0xf000) >> 12;
364
365 /* base register */
366 Rn = (opcode & 0xf0000) >> 16;
367
368 instruction->info.load_store.Rd = Rd;
369 instruction->info.load_store.Rn = Rn;
370 instruction->info.load_store.U = U;
371
372 /* determine operation */
373 if (L)
374 operation = "LDR";
375 else
376 operation = "STR";
377
378 /* determine instruction type and suffix */
379 if (B)
380 {
381 if ((P == 0) && (W == 1))
382 {
383 if (L)
384 instruction->type = ARM_LDRBT;
385 else
386 instruction->type = ARM_STRBT;
387 suffix = "BT";
388 }
389 else
390 {
391 if (L)
392 instruction->type = ARM_LDRB;
393 else
394 instruction->type = ARM_STRB;
395 suffix = "B";
396 }
397 }
398 else
399 {
400 if ((P == 0) && (W == 1))
401 {
402 if (L)
403 instruction->type = ARM_LDRT;
404 else
405 instruction->type = ARM_STRT;
406 suffix = "T";
407 }
408 else
409 {
410 if (L)
411 instruction->type = ARM_LDR;
412 else
413 instruction->type = ARM_STR;
414 suffix = "";
415 }
416 }
417
418 if (!I) /* #+-<offset_12> */
419 {
420 uint32_t offset_12 = (opcode & 0xfff);
421 if (offset_12)
422 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
423 else
424 snprintf(offset, 32, "%s", "");
425
426 instruction->info.load_store.offset_mode = 0;
427 instruction->info.load_store.offset.offset = offset_12;
428 }
429 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
430 {
431 uint8_t shift_imm, shift;
432 uint8_t Rm;
433
434 shift_imm = (opcode & 0xf80) >> 7;
435 shift = (opcode & 0x60) >> 5;
436 Rm = (opcode & 0xf);
437
438 /* LSR encodes a shift by 32 bit as 0x0 */
439 if ((shift == 0x1) && (shift_imm == 0x0))
440 shift_imm = 0x20;
441
442 /* ASR encodes a shift by 32 bit as 0x0 */
443 if ((shift == 0x2) && (shift_imm == 0x0))
444 shift_imm = 0x20;
445
446 /* ROR by 32 bit is actually a RRX */
447 if ((shift == 0x3) && (shift_imm == 0x0))
448 shift = 0x4;
449
450 instruction->info.load_store.offset_mode = 1;
451 instruction->info.load_store.offset.reg.Rm = Rm;
452 instruction->info.load_store.offset.reg.shift = shift;
453 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
454
455 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
456 {
457 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
458 }
459 else /* +-<Rm>, <Shift>, #<shift_imm> */
460 {
461 switch (shift)
462 {
463 case 0x0: /* LSL */
464 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
465 break;
466 case 0x1: /* LSR */
467 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
468 break;
469 case 0x2: /* ASR */
470 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
471 break;
472 case 0x3: /* ROR */
473 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
474 break;
475 case 0x4: /* RRX */
476 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
477 break;
478 }
479 }
480 }
481
482 if (P == 1)
483 {
484 if (W == 0) /* offset */
485 {
486 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
487 address, opcode, operation, COND(opcode), suffix,
488 Rd, Rn, offset);
489
490 instruction->info.load_store.index_mode = 0;
491 }
492 else /* pre-indexed */
493 {
494 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
495 address, opcode, operation, COND(opcode), suffix,
496 Rd, Rn, offset);
497
498 instruction->info.load_store.index_mode = 1;
499 }
500 }
501 else /* post-indexed */
502 {
503 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
504 address, opcode, operation, COND(opcode), suffix,
505 Rd, Rn, offset);
506
507 instruction->info.load_store.index_mode = 2;
508 }
509
510 return ERROR_OK;
511 }
512
513 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
514 {
515 unsigned rm = (opcode >> 0) & 0xf;
516 unsigned rd = (opcode >> 12) & 0xf;
517 unsigned rn = (opcode >> 16) & 0xf;
518 char *type, *rot;
519
520 switch ((opcode >> 24) & 0x3) {
521 case 0:
522 type = "B16";
523 break;
524 case 1:
525 sprintf(cp, "UNDEFINED");
526 return ARM_UNDEFINED_INSTRUCTION;
527 case 2:
528 type = "B";
529 break;
530 default:
531 type = "H";
532 break;
533 }
534
535 switch ((opcode >> 10) & 0x3) {
536 case 0:
537 rot = "";
538 break;
539 case 1:
540 rot = ", ROR #8";
541 break;
542 case 2:
543 rot = ", ROR #16";
544 break;
545 default:
546 rot = ", ROR #24";
547 break;
548 }
549
550 if (rn == 0xf) {
551 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
552 (opcode & (1 << 22)) ? 'U' : 'S',
553 type, COND(opcode),
554 rd, rm, rot);
555 return ARM_MOV;
556 } else {
557 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
558 (opcode & (1 << 22)) ? 'U' : 'S',
559 type, COND(opcode),
560 rd, rn, rm, rot);
561 return ARM_ADD;
562 }
563 }
564
565 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
566 {
567 char *prefix;
568 char *op;
569 int type;
570
571 switch ((opcode >> 20) & 0x7) {
572 case 1:
573 prefix = "S";
574 break;
575 case 2:
576 prefix = "Q";
577 break;
578 case 3:
579 prefix = "SH";
580 break;
581 case 5:
582 prefix = "U";
583 break;
584 case 6:
585 prefix = "UQ";
586 break;
587 case 7:
588 prefix = "UH";
589 break;
590 default:
591 goto undef;
592 }
593
594 switch ((opcode >> 5) & 0x7) {
595 case 0:
596 op = "ADD16";
597 type = ARM_ADD;
598 break;
599 case 1:
600 op = "ADDSUBX";
601 type = ARM_ADD;
602 break;
603 case 2:
604 op = "SUBADDX";
605 type = ARM_SUB;
606 break;
607 case 3:
608 op = "SUB16";
609 type = ARM_SUB;
610 break;
611 case 4:
612 op = "ADD8";
613 type = ARM_ADD;
614 break;
615 case 7:
616 op = "SUB8";
617 type = ARM_SUB;
618 break;
619 default:
620 goto undef;
621 }
622
623 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
624 (int) (opcode >> 12) & 0xf,
625 (int) (opcode >> 16) & 0xf,
626 (int) (opcode >> 0) & 0xf);
627 return type;
628
629 undef:
630 /* these opcodes might be used someday */
631 sprintf(cp, "UNDEFINED");
632 return ARM_UNDEFINED_INSTRUCTION;
633 }
634
635 /* ARMv6 and later support "media" instructions (includes SIMD) */
636 static int evaluate_media(uint32_t opcode, uint32_t address,
637 struct arm_instruction *instruction)
638 {
639 char *cp = instruction->text;
640 char *mnemonic = NULL;
641
642 sprintf(cp,
643 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
644 address, opcode);
645 cp = strchr(cp, 0);
646
647 /* parallel add/subtract */
648 if ((opcode & 0x01800000) == 0x00000000) {
649 instruction->type = evaluate_p_add_sub(opcode, address, cp);
650 return ERROR_OK;
651 }
652
653 /* halfword pack */
654 if ((opcode & 0x01f00020) == 0x00800000) {
655 char *type, *shift;
656 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
657
658 if (opcode & (1 << 6)) {
659 type = "TB";
660 shift = "ASR";
661 if (imm == 0)
662 imm = 32;
663 } else {
664 type = "BT";
665 shift = "LSL";
666 }
667 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
668 type, COND(opcode),
669 (int) (opcode >> 12) & 0xf,
670 (int) (opcode >> 16) & 0xf,
671 (int) (opcode >> 0) & 0xf,
672 shift, imm);
673 return ERROR_OK;
674 }
675
676 /* word saturate */
677 if ((opcode & 0x01a00020) == 0x00a00000) {
678 char *shift;
679 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
680
681 if (opcode & (1 << 6)) {
682 shift = "ASR";
683 if (imm == 0)
684 imm = 32;
685 } else {
686 shift = "LSL";
687 }
688
689 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
690 (opcode & (1 << 22)) ? 'U' : 'S',
691 COND(opcode),
692 (int) (opcode >> 12) & 0xf,
693 (int) (opcode >> 16) & 0x1f,
694 (int) (opcode >> 0) & 0xf,
695 shift, imm);
696 return ERROR_OK;
697 }
698
699 /* sign extension */
700 if ((opcode & 0x018000f0) == 0x00800070) {
701 instruction->type = evaluate_extend(opcode, address, cp);
702 return ERROR_OK;
703 }
704
705 /* multiplies */
706 if ((opcode & 0x01f00080) == 0x01000000) {
707 unsigned rn = (opcode >> 12) & 0xf;
708
709 if (rn != 0xf)
710 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
711 (opcode & (1 << 6)) ? 'S' : 'A',
712 (opcode & (1 << 5)) ? "X" : "",
713 COND(opcode),
714 (int) (opcode >> 16) & 0xf,
715 (int) (opcode >> 0) & 0xf,
716 (int) (opcode >> 8) & 0xf,
717 rn);
718 else
719 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
720 (opcode & (1 << 6)) ? 'S' : 'A',
721 (opcode & (1 << 5)) ? "X" : "",
722 COND(opcode),
723 (int) (opcode >> 16) & 0xf,
724 (int) (opcode >> 0) & 0xf,
725 (int) (opcode >> 8) & 0xf);
726 return ERROR_OK;
727 }
728 if ((opcode & 0x01f00000) == 0x01400000) {
729 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
730 (opcode & (1 << 6)) ? 'S' : 'A',
731 (opcode & (1 << 5)) ? "X" : "",
732 COND(opcode),
733 (int) (opcode >> 12) & 0xf,
734 (int) (opcode >> 16) & 0xf,
735 (int) (opcode >> 0) & 0xf,
736 (int) (opcode >> 8) & 0xf);
737 return ERROR_OK;
738 }
739 if ((opcode & 0x01f00000) == 0x01500000) {
740 unsigned rn = (opcode >> 12) & 0xf;
741
742 switch (opcode & 0xc0) {
743 case 3:
744 if (rn == 0xf)
745 goto undef;
746 /* FALL THROUGH */
747 case 0:
748 break;
749 default:
750 goto undef;
751 }
752
753 if (rn != 0xf)
754 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
755 (opcode & (1 << 6)) ? 'S' : 'A',
756 (opcode & (1 << 5)) ? "R" : "",
757 COND(opcode),
758 (int) (opcode >> 16) & 0xf,
759 (int) (opcode >> 0) & 0xf,
760 (int) (opcode >> 8) & 0xf,
761 rn);
762 else
763 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
764 (opcode & (1 << 5)) ? "R" : "",
765 COND(opcode),
766 (int) (opcode >> 16) & 0xf,
767 (int) (opcode >> 0) & 0xf,
768 (int) (opcode >> 8) & 0xf);
769 return ERROR_OK;
770 }
771
772
773 /* simple matches against the remaining decode bits */
774 switch (opcode & 0x01f000f0) {
775 case 0x00a00030:
776 case 0x00e00030:
777 /* parallel halfword saturate */
778 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
779 (opcode & (1 << 22)) ? 'U' : 'S',
780 COND(opcode),
781 (int) (opcode >> 12) & 0xf,
782 (int) (opcode >> 16) & 0xf,
783 (int) (opcode >> 0) & 0xf);
784 return ERROR_OK;
785 case 0x00b00030:
786 mnemonic = "REV";
787 break;
788 case 0x00b000b0:
789 mnemonic = "REV16";
790 break;
791 case 0x00f000b0:
792 mnemonic = "REVSH";
793 break;
794 case 0x008000b0:
795 /* select bytes */
796 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
797 (int) (opcode >> 12) & 0xf,
798 (int) (opcode >> 16) & 0xf,
799 (int) (opcode >> 0) & 0xf);
800 return ERROR_OK;
801 case 0x01800010:
802 /* unsigned sum of absolute differences */
803 if (((opcode >> 12) & 0xf) == 0xf)
804 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
805 (int) (opcode >> 16) & 0xf,
806 (int) (opcode >> 0) & 0xf,
807 (int) (opcode >> 8) & 0xf);
808 else
809 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
810 (int) (opcode >> 16) & 0xf,
811 (int) (opcode >> 0) & 0xf,
812 (int) (opcode >> 8) & 0xf,
813 (int) (opcode >> 12) & 0xf);
814 return ERROR_OK;
815 }
816 if (mnemonic) {
817 unsigned rm = (opcode >> 0) & 0xf;
818 unsigned rd = (opcode >> 12) & 0xf;
819
820 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
821 return ERROR_OK;
822 }
823
824 undef:
825 /* these opcodes might be used someday */
826 sprintf(cp, "UNDEFINED");
827 return ERROR_OK;
828 }
829
830 /* Miscellaneous load/store instructions */
831 static int evaluate_misc_load_store(uint32_t opcode,
832 uint32_t address, struct arm_instruction *instruction)
833 {
834 uint8_t P, U, I, W, L, S, H;
835 uint8_t Rn, Rd;
836 char *operation; /* "LDR" or "STR" */
837 char *suffix; /* "H", "SB", "SH", "D" */
838 char offset[32];
839
840 /* examine flags */
841 P = (opcode & 0x01000000) >> 24;
842 U = (opcode & 0x00800000) >> 23;
843 I = (opcode & 0x00400000) >> 22;
844 W = (opcode & 0x00200000) >> 21;
845 L = (opcode & 0x00100000) >> 20;
846 S = (opcode & 0x00000040) >> 6;
847 H = (opcode & 0x00000020) >> 5;
848
849 /* target register */
850 Rd = (opcode & 0xf000) >> 12;
851
852 /* base register */
853 Rn = (opcode & 0xf0000) >> 16;
854
855 instruction->info.load_store.Rd = Rd;
856 instruction->info.load_store.Rn = Rn;
857 instruction->info.load_store.U = U;
858
859 /* determine instruction type and suffix */
860 if (S) /* signed */
861 {
862 if (L) /* load */
863 {
864 if (H)
865 {
866 operation = "LDR";
867 instruction->type = ARM_LDRSH;
868 suffix = "SH";
869 }
870 else
871 {
872 operation = "LDR";
873 instruction->type = ARM_LDRSB;
874 suffix = "SB";
875 }
876 }
877 else /* there are no signed stores, so this is used to encode double-register load/stores */
878 {
879 suffix = "D";
880 if (H)
881 {
882 operation = "STR";
883 instruction->type = ARM_STRD;
884 }
885 else
886 {
887 operation = "LDR";
888 instruction->type = ARM_LDRD;
889 }
890 }
891 }
892 else /* unsigned */
893 {
894 suffix = "H";
895 if (L) /* load */
896 {
897 operation = "LDR";
898 instruction->type = ARM_LDRH;
899 }
900 else /* store */
901 {
902 operation = "STR";
903 instruction->type = ARM_STRH;
904 }
905 }
906
907 if (I) /* Immediate offset/index (#+-<offset_8>)*/
908 {
909 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
910 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
911
912 instruction->info.load_store.offset_mode = 0;
913 instruction->info.load_store.offset.offset = offset_8;
914 }
915 else /* Register offset/index (+-<Rm>) */
916 {
917 uint8_t Rm;
918 Rm = (opcode & 0xf);
919 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
920
921 instruction->info.load_store.offset_mode = 1;
922 instruction->info.load_store.offset.reg.Rm = Rm;
923 instruction->info.load_store.offset.reg.shift = 0x0;
924 instruction->info.load_store.offset.reg.shift_imm = 0x0;
925 }
926
927 if (P == 1)
928 {
929 if (W == 0) /* offset */
930 {
931 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
932 address, opcode, operation, COND(opcode), suffix,
933 Rd, Rn, offset);
934
935 instruction->info.load_store.index_mode = 0;
936 }
937 else /* pre-indexed */
938 {
939 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
940 address, opcode, operation, COND(opcode), suffix,
941 Rd, Rn, offset);
942
943 instruction->info.load_store.index_mode = 1;
944 }
945 }
946 else /* post-indexed */
947 {
948 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
949 address, opcode, operation, COND(opcode), suffix,
950 Rd, Rn, offset);
951
952 instruction->info.load_store.index_mode = 2;
953 }
954
955 return ERROR_OK;
956 }
957
958 /* Load/store multiples instructions */
959 static int evaluate_ldm_stm(uint32_t opcode,
960 uint32_t address, struct arm_instruction *instruction)
961 {
962 uint8_t P, U, S, W, L, Rn;
963 uint32_t register_list;
964 char *addressing_mode;
965 char *mnemonic;
966 char reg_list[69];
967 char *reg_list_p;
968 int i;
969 int first_reg = 1;
970
971 P = (opcode & 0x01000000) >> 24;
972 U = (opcode & 0x00800000) >> 23;
973 S = (opcode & 0x00400000) >> 22;
974 W = (opcode & 0x00200000) >> 21;
975 L = (opcode & 0x00100000) >> 20;
976 register_list = (opcode & 0xffff);
977 Rn = (opcode & 0xf0000) >> 16;
978
979 instruction->info.load_store_multiple.Rn = Rn;
980 instruction->info.load_store_multiple.register_list = register_list;
981 instruction->info.load_store_multiple.S = S;
982 instruction->info.load_store_multiple.W = W;
983
984 if (L)
985 {
986 instruction->type = ARM_LDM;
987 mnemonic = "LDM";
988 }
989 else
990 {
991 instruction->type = ARM_STM;
992 mnemonic = "STM";
993 }
994
995 if (P)
996 {
997 if (U)
998 {
999 instruction->info.load_store_multiple.addressing_mode = 1;
1000 addressing_mode = "IB";
1001 }
1002 else
1003 {
1004 instruction->info.load_store_multiple.addressing_mode = 3;
1005 addressing_mode = "DB";
1006 }
1007 }
1008 else
1009 {
1010 if (U)
1011 {
1012 instruction->info.load_store_multiple.addressing_mode = 0;
1013 /* "IA" is the default in UAL syntax */
1014 addressing_mode = "";
1015 }
1016 else
1017 {
1018 instruction->info.load_store_multiple.addressing_mode = 2;
1019 addressing_mode = "DA";
1020 }
1021 }
1022
1023 reg_list_p = reg_list;
1024 for (i = 0; i <= 15; i++)
1025 {
1026 if ((register_list >> i) & 1)
1027 {
1028 if (first_reg)
1029 {
1030 first_reg = 0;
1031 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
1032 }
1033 else
1034 {
1035 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
1036 }
1037 }
1038 }
1039
1040 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
1041 address, opcode, mnemonic, COND(opcode), addressing_mode,
1042 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1043
1044 return ERROR_OK;
1045 }
1046
1047 /* Multiplies, extra load/stores */
1048 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1049 uint32_t address, struct arm_instruction *instruction)
1050 {
1051 /* Multiply (accumulate) (long) and Swap/swap byte */
1052 if ((opcode & 0x000000f0) == 0x00000090)
1053 {
1054 /* Multiply (accumulate) */
1055 if ((opcode & 0x0f800000) == 0x00000000)
1056 {
1057 uint8_t Rm, Rs, Rn, Rd, S;
1058 Rm = opcode & 0xf;
1059 Rs = (opcode & 0xf00) >> 8;
1060 Rn = (opcode & 0xf000) >> 12;
1061 Rd = (opcode & 0xf0000) >> 16;
1062 S = (opcode & 0x00100000) >> 20;
1063
1064 /* examine A bit (accumulate) */
1065 if (opcode & 0x00200000)
1066 {
1067 instruction->type = ARM_MLA;
1068 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1069 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
1070 }
1071 else
1072 {
1073 instruction->type = ARM_MUL;
1074 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1075 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
1076 }
1077
1078 return ERROR_OK;
1079 }
1080
1081 /* Multiply (accumulate) long */
1082 if ((opcode & 0x0f800000) == 0x00800000)
1083 {
1084 char* mnemonic = NULL;
1085 uint8_t Rm, Rs, RdHi, RdLow, S;
1086 Rm = opcode & 0xf;
1087 Rs = (opcode & 0xf00) >> 8;
1088 RdHi = (opcode & 0xf000) >> 12;
1089 RdLow = (opcode & 0xf0000) >> 16;
1090 S = (opcode & 0x00100000) >> 20;
1091
1092 switch ((opcode & 0x00600000) >> 21)
1093 {
1094 case 0x0:
1095 instruction->type = ARM_UMULL;
1096 mnemonic = "UMULL";
1097 break;
1098 case 0x1:
1099 instruction->type = ARM_UMLAL;
1100 mnemonic = "UMLAL";
1101 break;
1102 case 0x2:
1103 instruction->type = ARM_SMULL;
1104 mnemonic = "SMULL";
1105 break;
1106 case 0x3:
1107 instruction->type = ARM_SMLAL;
1108 mnemonic = "SMLAL";
1109 break;
1110 }
1111
1112 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1113 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
1114 RdLow, RdHi, Rm, Rs);
1115
1116 return ERROR_OK;
1117 }
1118
1119 /* Swap/swap byte */
1120 if ((opcode & 0x0f800000) == 0x01000000)
1121 {
1122 uint8_t Rm, Rd, Rn;
1123 Rm = opcode & 0xf;
1124 Rd = (opcode & 0xf000) >> 12;
1125 Rn = (opcode & 0xf0000) >> 16;
1126
1127 /* examine B flag */
1128 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1129
1130 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1131 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
1132 return ERROR_OK;
1133 }
1134
1135 }
1136
1137 return evaluate_misc_load_store(opcode, address, instruction);
1138 }
1139
1140 static int evaluate_mrs_msr(uint32_t opcode,
1141 uint32_t address, struct arm_instruction *instruction)
1142 {
1143 int R = (opcode & 0x00400000) >> 22;
1144 char *PSR = (R) ? "SPSR" : "CPSR";
1145
1146 /* Move register to status register (MSR) */
1147 if (opcode & 0x00200000)
1148 {
1149 instruction->type = ARM_MSR;
1150
1151 /* immediate variant */
1152 if (opcode & 0x02000000)
1153 {
1154 uint8_t immediate = (opcode & 0xff);
1155 uint8_t rotate = (opcode & 0xf00);
1156
1157 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
1158 address, opcode, COND(opcode), PSR,
1159 (opcode & 0x10000) ? "c" : "",
1160 (opcode & 0x20000) ? "x" : "",
1161 (opcode & 0x40000) ? "s" : "",
1162 (opcode & 0x80000) ? "f" : "",
1163 ror(immediate, (rotate * 2))
1164 );
1165 }
1166 else /* register variant */
1167 {
1168 uint8_t Rm = opcode & 0xf;
1169 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1170 address, opcode, COND(opcode), PSR,
1171 (opcode & 0x10000) ? "c" : "",
1172 (opcode & 0x20000) ? "x" : "",
1173 (opcode & 0x40000) ? "s" : "",
1174 (opcode & 0x80000) ? "f" : "",
1175 Rm
1176 );
1177 }
1178
1179 }
1180 else /* Move status register to register (MRS) */
1181 {
1182 uint8_t Rd;
1183
1184 instruction->type = ARM_MRS;
1185 Rd = (opcode & 0x0000f000) >> 12;
1186
1187 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1188 address, opcode, COND(opcode), Rd, PSR);
1189 }
1190
1191 return ERROR_OK;
1192 }
1193
1194 /* Miscellaneous instructions */
1195 static int evaluate_misc_instr(uint32_t opcode,
1196 uint32_t address, struct arm_instruction *instruction)
1197 {
1198 /* MRS/MSR */
1199 if ((opcode & 0x000000f0) == 0x00000000)
1200 {
1201 evaluate_mrs_msr(opcode, address, instruction);
1202 }
1203
1204 /* BX */
1205 if ((opcode & 0x006000f0) == 0x00200010)
1206 {
1207 uint8_t Rm;
1208 instruction->type = ARM_BX;
1209 Rm = opcode & 0xf;
1210
1211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1212 address, opcode, COND(opcode), Rm);
1213
1214 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1215 instruction->info.b_bl_bx_blx.target_address = -1;
1216 }
1217
1218 /* BXJ - "Jazelle" support (ARMv5-J) */
1219 if ((opcode & 0x006000f0) == 0x00200020)
1220 {
1221 uint8_t Rm;
1222 instruction->type = ARM_BX;
1223 Rm = opcode & 0xf;
1224
1225 snprintf(instruction->text, 128,
1226 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1227 address, opcode, COND(opcode), Rm);
1228
1229 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1230 instruction->info.b_bl_bx_blx.target_address = -1;
1231 }
1232
1233 /* CLZ */
1234 if ((opcode & 0x006000f0) == 0x00600010)
1235 {
1236 uint8_t Rm, Rd;
1237 instruction->type = ARM_CLZ;
1238 Rm = opcode & 0xf;
1239 Rd = (opcode & 0xf000) >> 12;
1240
1241 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1242 address, opcode, COND(opcode), Rd, Rm);
1243 }
1244
1245 /* BLX(2) */
1246 if ((opcode & 0x006000f0) == 0x00200030)
1247 {
1248 uint8_t Rm;
1249 instruction->type = ARM_BLX;
1250 Rm = opcode & 0xf;
1251
1252 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1253 address, opcode, COND(opcode), Rm);
1254
1255 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1256 instruction->info.b_bl_bx_blx.target_address = -1;
1257 }
1258
1259 /* Enhanced DSP add/subtracts */
1260 if ((opcode & 0x0000000f0) == 0x00000050)
1261 {
1262 uint8_t Rm, Rd, Rn;
1263 char *mnemonic = NULL;
1264 Rm = opcode & 0xf;
1265 Rd = (opcode & 0xf000) >> 12;
1266 Rn = (opcode & 0xf0000) >> 16;
1267
1268 switch ((opcode & 0x00600000) >> 21)
1269 {
1270 case 0x0:
1271 instruction->type = ARM_QADD;
1272 mnemonic = "QADD";
1273 break;
1274 case 0x1:
1275 instruction->type = ARM_QSUB;
1276 mnemonic = "QSUB";
1277 break;
1278 case 0x2:
1279 instruction->type = ARM_QDADD;
1280 mnemonic = "QDADD";
1281 break;
1282 case 0x3:
1283 instruction->type = ARM_QDSUB;
1284 mnemonic = "QDSUB";
1285 break;
1286 }
1287
1288 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1289 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
1290 }
1291
1292 /* Software breakpoints */
1293 if ((opcode & 0x0000000f0) == 0x00000070)
1294 {
1295 uint32_t immediate;
1296 instruction->type = ARM_BKPT;
1297 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1298
1299 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
1300 address, opcode, immediate);
1301 }
1302
1303 /* Enhanced DSP multiplies */
1304 if ((opcode & 0x000000090) == 0x00000080)
1305 {
1306 int x = (opcode & 0x20) >> 5;
1307 int y = (opcode & 0x40) >> 6;
1308
1309 /* SMLA < x><y> */
1310 if ((opcode & 0x00600000) == 0x00000000)
1311 {
1312 uint8_t Rd, Rm, Rs, Rn;
1313 instruction->type = ARM_SMLAxy;
1314 Rd = (opcode & 0xf0000) >> 16;
1315 Rm = (opcode & 0xf);
1316 Rs = (opcode & 0xf00) >> 8;
1317 Rn = (opcode & 0xf000) >> 12;
1318
1319 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1320 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1321 Rd, Rm, Rs, Rn);
1322 }
1323
1324 /* SMLAL < x><y> */
1325 if ((opcode & 0x00600000) == 0x00400000)
1326 {
1327 uint8_t RdLow, RdHi, Rm, Rs;
1328 instruction->type = ARM_SMLAxy;
1329 RdHi = (opcode & 0xf0000) >> 16;
1330 RdLow = (opcode & 0xf000) >> 12;
1331 Rm = (opcode & 0xf);
1332 Rs = (opcode & 0xf00) >> 8;
1333
1334 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1335 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1336 RdLow, RdHi, Rm, Rs);
1337 }
1338
1339 /* SMLAW < y> */
1340 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
1341 {
1342 uint8_t Rd, Rm, Rs, Rn;
1343 instruction->type = ARM_SMLAWy;
1344 Rd = (opcode & 0xf0000) >> 16;
1345 Rm = (opcode & 0xf);
1346 Rs = (opcode & 0xf00) >> 8;
1347 Rn = (opcode & 0xf000) >> 12;
1348
1349 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1350 address, opcode, (y) ? "T" : "B", COND(opcode),
1351 Rd, Rm, Rs, Rn);
1352 }
1353
1354 /* SMUL < x><y> */
1355 if ((opcode & 0x00600000) == 0x00300000)
1356 {
1357 uint8_t Rd, Rm, Rs;
1358 instruction->type = ARM_SMULxy;
1359 Rd = (opcode & 0xf0000) >> 16;
1360 Rm = (opcode & 0xf);
1361 Rs = (opcode & 0xf00) >> 8;
1362
1363 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1364 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1365 Rd, Rm, Rs);
1366 }
1367
1368 /* SMULW < y> */
1369 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
1370 {
1371 uint8_t Rd, Rm, Rs;
1372 instruction->type = ARM_SMULWy;
1373 Rd = (opcode & 0xf0000) >> 16;
1374 Rm = (opcode & 0xf);
1375 Rs = (opcode & 0xf00) >> 8;
1376
1377 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1378 address, opcode, (y) ? "T" : "B", COND(opcode),
1379 Rd, Rm, Rs);
1380 }
1381 }
1382
1383 return ERROR_OK;
1384 }
1385
1386 static int evaluate_data_proc(uint32_t opcode,
1387 uint32_t address, struct arm_instruction *instruction)
1388 {
1389 uint8_t I, op, S, Rn, Rd;
1390 char *mnemonic = NULL;
1391 char shifter_operand[32];
1392
1393 I = (opcode & 0x02000000) >> 25;
1394 op = (opcode & 0x01e00000) >> 21;
1395 S = (opcode & 0x00100000) >> 20;
1396
1397 Rd = (opcode & 0xf000) >> 12;
1398 Rn = (opcode & 0xf0000) >> 16;
1399
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = S;
1403
1404 switch (op)
1405 {
1406 case 0x0:
1407 instruction->type = ARM_AND;
1408 mnemonic = "AND";
1409 break;
1410 case 0x1:
1411 instruction->type = ARM_EOR;
1412 mnemonic = "EOR";
1413 break;
1414 case 0x2:
1415 instruction->type = ARM_SUB;
1416 mnemonic = "SUB";
1417 break;
1418 case 0x3:
1419 instruction->type = ARM_RSB;
1420 mnemonic = "RSB";
1421 break;
1422 case 0x4:
1423 instruction->type = ARM_ADD;
1424 mnemonic = "ADD";
1425 break;
1426 case 0x5:
1427 instruction->type = ARM_ADC;
1428 mnemonic = "ADC";
1429 break;
1430 case 0x6:
1431 instruction->type = ARM_SBC;
1432 mnemonic = "SBC";
1433 break;
1434 case 0x7:
1435 instruction->type = ARM_RSC;
1436 mnemonic = "RSC";
1437 break;
1438 case 0x8:
1439 instruction->type = ARM_TST;
1440 mnemonic = "TST";
1441 break;
1442 case 0x9:
1443 instruction->type = ARM_TEQ;
1444 mnemonic = "TEQ";
1445 break;
1446 case 0xa:
1447 instruction->type = ARM_CMP;
1448 mnemonic = "CMP";
1449 break;
1450 case 0xb:
1451 instruction->type = ARM_CMN;
1452 mnemonic = "CMN";
1453 break;
1454 case 0xc:
1455 instruction->type = ARM_ORR;
1456 mnemonic = "ORR";
1457 break;
1458 case 0xd:
1459 instruction->type = ARM_MOV;
1460 mnemonic = "MOV";
1461 break;
1462 case 0xe:
1463 instruction->type = ARM_BIC;
1464 mnemonic = "BIC";
1465 break;
1466 case 0xf:
1467 instruction->type = ARM_MVN;
1468 mnemonic = "MVN";
1469 break;
1470 }
1471
1472 if (I) /* immediate shifter operand (#<immediate>)*/
1473 {
1474 uint8_t immed_8 = opcode & 0xff;
1475 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1476 uint32_t immediate;
1477
1478 immediate = ror(immed_8, rotate_imm * 2);
1479
1480 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1481
1482 instruction->info.data_proc.variant = 0;
1483 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1484 }
1485 else /* register-based shifter operand */
1486 {
1487 uint8_t shift, Rm;
1488 shift = (opcode & 0x60) >> 5;
1489 Rm = (opcode & 0xf);
1490
1491 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1492 {
1493 uint8_t shift_imm;
1494 shift_imm = (opcode & 0xf80) >> 7;
1495
1496 instruction->info.data_proc.variant = 1;
1497 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1498 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1499 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1500
1501 /* LSR encodes a shift by 32 bit as 0x0 */
1502 if ((shift == 0x1) && (shift_imm == 0x0))
1503 shift_imm = 0x20;
1504
1505 /* ASR encodes a shift by 32 bit as 0x0 */
1506 if ((shift == 0x2) && (shift_imm == 0x0))
1507 shift_imm = 0x20;
1508
1509 /* ROR by 32 bit is actually a RRX */
1510 if ((shift == 0x3) && (shift_imm == 0x0))
1511 shift = 0x4;
1512
1513 if ((shift_imm == 0x0) && (shift == 0x0))
1514 {
1515 snprintf(shifter_operand, 32, "r%i", Rm);
1516 }
1517 else
1518 {
1519 if (shift == 0x0) /* LSL */
1520 {
1521 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1522 }
1523 else if (shift == 0x1) /* LSR */
1524 {
1525 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1526 }
1527 else if (shift == 0x2) /* ASR */
1528 {
1529 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1530 }
1531 else if (shift == 0x3) /* ROR */
1532 {
1533 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1534 }
1535 else if (shift == 0x4) /* RRX */
1536 {
1537 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1538 }
1539 }
1540 }
1541 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1542 {
1543 uint8_t Rs = (opcode & 0xf00) >> 8;
1544
1545 instruction->info.data_proc.variant = 2;
1546 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1547 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1548 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1549
1550 if (shift == 0x0) /* LSL */
1551 {
1552 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1553 }
1554 else if (shift == 0x1) /* LSR */
1555 {
1556 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1557 }
1558 else if (shift == 0x2) /* ASR */
1559 {
1560 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1561 }
1562 else if (shift == 0x3) /* ROR */
1563 {
1564 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1565 }
1566 }
1567 }
1568
1569 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1570 {
1571 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1572 address, opcode, mnemonic, COND(opcode),
1573 (S) ? "S" : "", Rd, Rn, shifter_operand);
1574 }
1575 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1576 {
1577 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1578 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1579 else
1580 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1581 address, opcode, mnemonic, COND(opcode),
1582 (S) ? "S" : "", Rd, shifter_operand);
1583 }
1584 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1585 {
1586 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1587 address, opcode, mnemonic, COND(opcode),
1588 Rn, shifter_operand);
1589 }
1590
1591 return ERROR_OK;
1592 }
1593
1594 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
1595 {
1596 /* clear fields, to avoid confusion */
1597 memset(instruction, 0, sizeof(struct arm_instruction));
1598 instruction->opcode = opcode;
1599 instruction->instruction_size = 4;
1600
1601 /* catch opcodes with condition field [31:28] = b1111 */
1602 if ((opcode & 0xf0000000) == 0xf0000000)
1603 {
1604 /* Undefined instruction (or ARMv5E cache preload PLD) */
1605 if ((opcode & 0x08000000) == 0x00000000)
1606 return evaluate_pld(opcode, address, instruction);
1607
1608 /* Undefined instruction */
1609 if ((opcode & 0x0e000000) == 0x08000000)
1610 {
1611 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1612 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1613 return ERROR_OK;
1614 }
1615
1616 /* Branch and branch with link and change to Thumb */
1617 if ((opcode & 0x0e000000) == 0x0a000000)
1618 return evaluate_blx_imm(opcode, address, instruction);
1619
1620 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1621 /* Coprocessor load/store and double register transfers */
1622 if ((opcode & 0x0e000000) == 0x0c000000)
1623 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1624
1625 /* Coprocessor data processing */
1626 if ((opcode & 0x0f000100) == 0x0c000000)
1627 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1628
1629 /* Coprocessor register transfers */
1630 if ((opcode & 0x0f000010) == 0x0c000010)
1631 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1632
1633 /* Undefined instruction */
1634 if ((opcode & 0x0f000000) == 0x0f000000)
1635 {
1636 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1637 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1638 return ERROR_OK;
1639 }
1640 }
1641
1642 /* catch opcodes with [27:25] = b000 */
1643 if ((opcode & 0x0e000000) == 0x00000000)
1644 {
1645 /* Multiplies, extra load/stores */
1646 if ((opcode & 0x00000090) == 0x00000090)
1647 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1648
1649 /* Miscellaneous instructions */
1650 if ((opcode & 0x0f900000) == 0x01000000)
1651 return evaluate_misc_instr(opcode, address, instruction);
1652
1653 return evaluate_data_proc(opcode, address, instruction);
1654 }
1655
1656 /* catch opcodes with [27:25] = b001 */
1657 if ((opcode & 0x0e000000) == 0x02000000)
1658 {
1659 /* Undefined instruction */
1660 if ((opcode & 0x0fb00000) == 0x03000000)
1661 {
1662 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1663 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1664 return ERROR_OK;
1665 }
1666
1667 /* Move immediate to status register */
1668 if ((opcode & 0x0fb00000) == 0x03200000)
1669 return evaluate_mrs_msr(opcode, address, instruction);
1670
1671 return evaluate_data_proc(opcode, address, instruction);
1672
1673 }
1674
1675 /* catch opcodes with [27:25] = b010 */
1676 if ((opcode & 0x0e000000) == 0x04000000)
1677 {
1678 /* Load/store immediate offset */
1679 return evaluate_load_store(opcode, address, instruction);
1680 }
1681
1682 /* catch opcodes with [27:25] = b011 */
1683 if ((opcode & 0x0e000000) == 0x06000000)
1684 {
1685 /* Load/store register offset */
1686 if ((opcode & 0x00000010) == 0x00000000)
1687 return evaluate_load_store(opcode, address, instruction);
1688
1689 /* Architecturally Undefined instruction
1690 * ... don't expect these to ever be used
1691 */
1692 if ((opcode & 0x07f000f0) == 0x07f000f0)
1693 {
1694 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1695 snprintf(instruction->text, 128,
1696 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1697 address, opcode);
1698 return ERROR_OK;
1699 }
1700
1701 /* "media" instructions */
1702 return evaluate_media(opcode, address, instruction);
1703 }
1704
1705 /* catch opcodes with [27:25] = b100 */
1706 if ((opcode & 0x0e000000) == 0x08000000)
1707 {
1708 /* Load/store multiple */
1709 return evaluate_ldm_stm(opcode, address, instruction);
1710 }
1711
1712 /* catch opcodes with [27:25] = b101 */
1713 if ((opcode & 0x0e000000) == 0x0a000000)
1714 {
1715 /* Branch and branch with link */
1716 return evaluate_b_bl(opcode, address, instruction);
1717 }
1718
1719 /* catch opcodes with [27:25] = b110 */
1720 if ((opcode & 0x0e000000) == 0x0a000000)
1721 {
1722 /* Coprocessor load/store and double register transfers */
1723 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1724 }
1725
1726 /* catch opcodes with [27:25] = b111 */
1727 if ((opcode & 0x0e000000) == 0x0e000000)
1728 {
1729 /* Software interrupt */
1730 if ((opcode & 0x0f000000) == 0x0f000000)
1731 return evaluate_swi(opcode, address, instruction);
1732
1733 /* Coprocessor data processing */
1734 if ((opcode & 0x0f000010) == 0x0e000000)
1735 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1736
1737 /* Coprocessor register transfers */
1738 if ((opcode & 0x0f000010) == 0x0e000010)
1739 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1740 }
1741
1742 LOG_ERROR("should never reach this point");
1743 return -1;
1744 }
1745
1746 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1747 uint32_t address, struct arm_instruction *instruction)
1748 {
1749 uint32_t offset = opcode & 0x7ff;
1750 uint32_t opc = (opcode >> 11) & 0x3;
1751 uint32_t target_address;
1752 char *mnemonic = NULL;
1753
1754 /* sign extend 11-bit offset */
1755 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1756 offset = 0xfffff800 | offset;
1757
1758 target_address = address + 4 + (offset << 1);
1759
1760 switch (opc)
1761 {
1762 /* unconditional branch */
1763 case 0:
1764 instruction->type = ARM_B;
1765 mnemonic = "B";
1766 break;
1767 /* BLX suffix */
1768 case 1:
1769 instruction->type = ARM_BLX;
1770 mnemonic = "BLX";
1771 target_address &= 0xfffffffc;
1772 break;
1773 /* BL/BLX prefix */
1774 case 2:
1775 instruction->type = ARM_UNKNOWN_INSTUCTION;
1776 mnemonic = "prefix";
1777 target_address = offset << 12;
1778 break;
1779 /* BL suffix */
1780 case 3:
1781 instruction->type = ARM_BL;
1782 mnemonic = "BL";
1783 break;
1784 }
1785
1786 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1787 * these are effectively 32-bit instructions even in Thumb1.
1788 * Might be simplest to always use the Thumb2 decoder.
1789 */
1790
1791 snprintf(instruction->text, 128,
1792 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1793 address, opcode, mnemonic, target_address);
1794
1795 instruction->info.b_bl_bx_blx.reg_operand = -1;
1796 instruction->info.b_bl_bx_blx.target_address = target_address;
1797
1798 return ERROR_OK;
1799 }
1800
1801 static int evaluate_add_sub_thumb(uint16_t opcode,
1802 uint32_t address, struct arm_instruction *instruction)
1803 {
1804 uint8_t Rd = (opcode >> 0) & 0x7;
1805 uint8_t Rn = (opcode >> 3) & 0x7;
1806 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1807 uint32_t opc = opcode & (1 << 9);
1808 uint32_t reg_imm = opcode & (1 << 10);
1809 char *mnemonic;
1810
1811 if (opc)
1812 {
1813 instruction->type = ARM_SUB;
1814 mnemonic = "SUBS";
1815 }
1816 else
1817 {
1818 /* REVISIT: if reg_imm == 0, display as "MOVS" */
1819 instruction->type = ARM_ADD;
1820 mnemonic = "ADDS";
1821 }
1822
1823 instruction->info.data_proc.Rd = Rd;
1824 instruction->info.data_proc.Rn = Rn;
1825 instruction->info.data_proc.S = 1;
1826
1827 if (reg_imm)
1828 {
1829 instruction->info.data_proc.variant = 0; /*immediate*/
1830 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1831 snprintf(instruction->text, 128,
1832 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1833 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1834 }
1835 else
1836 {
1837 instruction->info.data_proc.variant = 1; /*immediate shift*/
1838 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1839 snprintf(instruction->text, 128,
1840 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1841 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1842 }
1843
1844 return ERROR_OK;
1845 }
1846
1847 static int evaluate_shift_imm_thumb(uint16_t opcode,
1848 uint32_t address, struct arm_instruction *instruction)
1849 {
1850 uint8_t Rd = (opcode >> 0) & 0x7;
1851 uint8_t Rm = (opcode >> 3) & 0x7;
1852 uint8_t imm = (opcode >> 6) & 0x1f;
1853 uint8_t opc = (opcode >> 11) & 0x3;
1854 char *mnemonic = NULL;
1855
1856 switch (opc)
1857 {
1858 case 0:
1859 instruction->type = ARM_MOV;
1860 mnemonic = "LSLS";
1861 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1862 break;
1863 case 1:
1864 instruction->type = ARM_MOV;
1865 mnemonic = "LSRS";
1866 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1867 break;
1868 case 2:
1869 instruction->type = ARM_MOV;
1870 mnemonic = "ASRS";
1871 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1872 break;
1873 }
1874
1875 if ((imm == 0) && (opc != 0))
1876 imm = 32;
1877
1878 instruction->info.data_proc.Rd = Rd;
1879 instruction->info.data_proc.Rn = -1;
1880 instruction->info.data_proc.S = 1;
1881
1882 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1883 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1884 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1885
1886 snprintf(instruction->text, 128,
1887 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1888 address, opcode, mnemonic, Rd, Rm, imm);
1889
1890 return ERROR_OK;
1891 }
1892
1893 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
1894 uint32_t address, struct arm_instruction *instruction)
1895 {
1896 uint8_t imm = opcode & 0xff;
1897 uint8_t Rd = (opcode >> 8) & 0x7;
1898 uint32_t opc = (opcode >> 11) & 0x3;
1899 char *mnemonic = NULL;
1900
1901 instruction->info.data_proc.Rd = Rd;
1902 instruction->info.data_proc.Rn = Rd;
1903 instruction->info.data_proc.S = 1;
1904 instruction->info.data_proc.variant = 0; /*immediate*/
1905 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1906
1907 switch (opc)
1908 {
1909 case 0:
1910 instruction->type = ARM_MOV;
1911 mnemonic = "MOVS";
1912 instruction->info.data_proc.Rn = -1;
1913 break;
1914 case 1:
1915 instruction->type = ARM_CMP;
1916 mnemonic = "CMP";
1917 instruction->info.data_proc.Rd = -1;
1918 break;
1919 case 2:
1920 instruction->type = ARM_ADD;
1921 mnemonic = "ADDS";
1922 break;
1923 case 3:
1924 instruction->type = ARM_SUB;
1925 mnemonic = "SUBS";
1926 break;
1927 }
1928
1929 snprintf(instruction->text, 128,
1930 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1931 address, opcode, mnemonic, Rd, imm);
1932
1933 return ERROR_OK;
1934 }
1935
1936 static int evaluate_data_proc_thumb(uint16_t opcode,
1937 uint32_t address, struct arm_instruction *instruction)
1938 {
1939 uint8_t high_reg, op, Rm, Rd,H1,H2;
1940 char *mnemonic = NULL;
1941 bool nop = false;
1942
1943 high_reg = (opcode & 0x0400) >> 10;
1944 op = (opcode & 0x03C0) >> 6;
1945
1946 Rd = (opcode & 0x0007);
1947 Rm = (opcode & 0x0038) >> 3;
1948 H1 = (opcode & 0x0080) >> 7;
1949 H2 = (opcode & 0x0040) >> 6;
1950
1951 instruction->info.data_proc.Rd = Rd;
1952 instruction->info.data_proc.Rn = Rd;
1953 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1954 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1955 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1956
1957 if (high_reg)
1958 {
1959 Rd |= H1 << 3;
1960 Rm |= H2 << 3;
1961 op >>= 2;
1962
1963 switch (op)
1964 {
1965 case 0x0:
1966 instruction->type = ARM_ADD;
1967 mnemonic = "ADD";
1968 break;
1969 case 0x1:
1970 instruction->type = ARM_CMP;
1971 mnemonic = "CMP";
1972 break;
1973 case 0x2:
1974 instruction->type = ARM_MOV;
1975 mnemonic = "MOV";
1976 if (Rd == Rm)
1977 nop = true;
1978 break;
1979 case 0x3:
1980 if ((opcode & 0x7) == 0x0)
1981 {
1982 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1983 if (H1)
1984 {
1985 instruction->type = ARM_BLX;
1986 snprintf(instruction->text, 128,
1987 "0x%8.8" PRIx32
1988 " 0x%4.4x \tBLX\tr%i",
1989 address, opcode, Rm);
1990 }
1991 else
1992 {
1993 instruction->type = ARM_BX;
1994 snprintf(instruction->text, 128,
1995 "0x%8.8" PRIx32
1996 " 0x%4.4x \tBX\tr%i",
1997 address, opcode, Rm);
1998 }
1999 }
2000 else
2001 {
2002 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2003 snprintf(instruction->text, 128,
2004 "0x%8.8" PRIx32
2005 " 0x%4.4x \t"
2006 "UNDEFINED INSTRUCTION",
2007 address, opcode);
2008 }
2009 return ERROR_OK;
2010 break;
2011 }
2012 }
2013 else
2014 {
2015 switch (op)
2016 {
2017 case 0x0:
2018 instruction->type = ARM_AND;
2019 mnemonic = "ANDS";
2020 break;
2021 case 0x1:
2022 instruction->type = ARM_EOR;
2023 mnemonic = "EORS";
2024 break;
2025 case 0x2:
2026 instruction->type = ARM_MOV;
2027 mnemonic = "LSLS";
2028 instruction->info.data_proc.variant = 2 /*register shift*/;
2029 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2030 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2031 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2032 break;
2033 case 0x3:
2034 instruction->type = ARM_MOV;
2035 mnemonic = "LSRS";
2036 instruction->info.data_proc.variant = 2 /*register shift*/;
2037 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2038 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2039 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2040 break;
2041 case 0x4:
2042 instruction->type = ARM_MOV;
2043 mnemonic = "ASRS";
2044 instruction->info.data_proc.variant = 2 /*register shift*/;
2045 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2046 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2047 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2048 break;
2049 case 0x5:
2050 instruction->type = ARM_ADC;
2051 mnemonic = "ADCS";
2052 break;
2053 case 0x6:
2054 instruction->type = ARM_SBC;
2055 mnemonic = "SBCS";
2056 break;
2057 case 0x7:
2058 instruction->type = ARM_MOV;
2059 mnemonic = "RORS";
2060 instruction->info.data_proc.variant = 2 /*register shift*/;
2061 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2062 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2063 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2064 break;
2065 case 0x8:
2066 instruction->type = ARM_TST;
2067 mnemonic = "TST";
2068 break;
2069 case 0x9:
2070 instruction->type = ARM_RSB;
2071 mnemonic = "RSBS";
2072 instruction->info.data_proc.variant = 0 /*immediate*/;
2073 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2074 instruction->info.data_proc.Rn = Rm;
2075 break;
2076 case 0xA:
2077 instruction->type = ARM_CMP;
2078 mnemonic = "CMP";
2079 break;
2080 case 0xB:
2081 instruction->type = ARM_CMN;
2082 mnemonic = "CMN";
2083 break;
2084 case 0xC:
2085 instruction->type = ARM_ORR;
2086 mnemonic = "ORRS";
2087 break;
2088 case 0xD:
2089 instruction->type = ARM_MUL;
2090 mnemonic = "MULS";
2091 break;
2092 case 0xE:
2093 instruction->type = ARM_BIC;
2094 mnemonic = "BICS";
2095 break;
2096 case 0xF:
2097 instruction->type = ARM_MVN;
2098 mnemonic = "MVNS";
2099 break;
2100 }
2101 }
2102
2103 if (nop)
2104 snprintf(instruction->text, 128,
2105 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2106 "; (%s r%i, r%i)",
2107 address, opcode, mnemonic, Rd, Rm);
2108 else
2109 snprintf(instruction->text, 128,
2110 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2111 address, opcode, mnemonic, Rd, Rm);
2112
2113 return ERROR_OK;
2114 }
2115
2116 /* PC-relative data addressing is word-aligned even with Thumb */
2117 static inline uint32_t thumb_alignpc4(uint32_t addr)
2118 {
2119 return (addr + 4) & ~3;
2120 }
2121
2122 static int evaluate_load_literal_thumb(uint16_t opcode,
2123 uint32_t address, struct arm_instruction *instruction)
2124 {
2125 uint32_t immediate;
2126 uint8_t Rd = (opcode >> 8) & 0x7;
2127
2128 instruction->type = ARM_LDR;
2129 immediate = opcode & 0x000000ff;
2130 immediate *= 4;
2131
2132 instruction->info.load_store.Rd = Rd;
2133 instruction->info.load_store.Rn = 15 /*PC*/;
2134 instruction->info.load_store.index_mode = 0; /*offset*/
2135 instruction->info.load_store.offset_mode = 0; /*immediate*/
2136 instruction->info.load_store.offset.offset = immediate;
2137
2138 snprintf(instruction->text, 128,
2139 "0x%8.8" PRIx32 " 0x%4.4x \t"
2140 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2141 address, opcode, Rd, immediate,
2142 thumb_alignpc4(address) + immediate);
2143
2144 return ERROR_OK;
2145 }
2146
2147 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2148 uint32_t address, struct arm_instruction *instruction)
2149 {
2150 uint8_t Rd = (opcode >> 0) & 0x7;
2151 uint8_t Rn = (opcode >> 3) & 0x7;
2152 uint8_t Rm = (opcode >> 6) & 0x7;
2153 uint8_t opc = (opcode >> 9) & 0x7;
2154 char *mnemonic = NULL;
2155
2156 switch (opc)
2157 {
2158 case 0:
2159 instruction->type = ARM_STR;
2160 mnemonic = "STR";
2161 break;
2162 case 1:
2163 instruction->type = ARM_STRH;
2164 mnemonic = "STRH";
2165 break;
2166 case 2:
2167 instruction->type = ARM_STRB;
2168 mnemonic = "STRB";
2169 break;
2170 case 3:
2171 instruction->type = ARM_LDRSB;
2172 mnemonic = "LDRSB";
2173 break;
2174 case 4:
2175 instruction->type = ARM_LDR;
2176 mnemonic = "LDR";
2177 break;
2178 case 5:
2179 instruction->type = ARM_LDRH;
2180 mnemonic = "LDRH";
2181 break;
2182 case 6:
2183 instruction->type = ARM_LDRB;
2184 mnemonic = "LDRB";
2185 break;
2186 case 7:
2187 instruction->type = ARM_LDRSH;
2188 mnemonic = "LDRSH";
2189 break;
2190 }
2191
2192 snprintf(instruction->text, 128,
2193 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2194 address, opcode, mnemonic, Rd, Rn, Rm);
2195
2196 instruction->info.load_store.Rd = Rd;
2197 instruction->info.load_store.Rn = Rn;
2198 instruction->info.load_store.index_mode = 0; /*offset*/
2199 instruction->info.load_store.offset_mode = 1; /*register*/
2200 instruction->info.load_store.offset.reg.Rm = Rm;
2201
2202 return ERROR_OK;
2203 }
2204
2205 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2206 uint32_t address, struct arm_instruction *instruction)
2207 {
2208 uint32_t offset = (opcode >> 6) & 0x1f;
2209 uint8_t Rd = (opcode >> 0) & 0x7;
2210 uint8_t Rn = (opcode >> 3) & 0x7;
2211 uint32_t L = opcode & (1 << 11);
2212 uint32_t B = opcode & (1 << 12);
2213 char *mnemonic;
2214 char suffix = ' ';
2215 uint32_t shift = 2;
2216
2217 if (L)
2218 {
2219 instruction->type = ARM_LDR;
2220 mnemonic = "LDR";
2221 }
2222 else
2223 {
2224 instruction->type = ARM_STR;
2225 mnemonic = "STR";
2226 }
2227
2228 if ((opcode&0xF000) == 0x8000)
2229 {
2230 suffix = 'H';
2231 shift = 1;
2232 }
2233 else if (B)
2234 {
2235 suffix = 'B';
2236 shift = 0;
2237 }
2238
2239 snprintf(instruction->text, 128,
2240 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2241 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2242
2243 instruction->info.load_store.Rd = Rd;
2244 instruction->info.load_store.Rn = Rn;
2245 instruction->info.load_store.index_mode = 0; /*offset*/
2246 instruction->info.load_store.offset_mode = 0; /*immediate*/
2247 instruction->info.load_store.offset.offset = offset << shift;
2248
2249 return ERROR_OK;
2250 }
2251
2252 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2253 uint32_t address, struct arm_instruction *instruction)
2254 {
2255 uint32_t offset = opcode & 0xff;
2256 uint8_t Rd = (opcode >> 8) & 0x7;
2257 uint32_t L = opcode & (1 << 11);
2258 char *mnemonic;
2259
2260 if (L)
2261 {
2262 instruction->type = ARM_LDR;
2263 mnemonic = "LDR";
2264 }
2265 else
2266 {
2267 instruction->type = ARM_STR;
2268 mnemonic = "STR";
2269 }
2270
2271 snprintf(instruction->text, 128,
2272 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2273 address, opcode, mnemonic, Rd, offset*4);
2274
2275 instruction->info.load_store.Rd = Rd;
2276 instruction->info.load_store.Rn = 13 /*SP*/;
2277 instruction->info.load_store.index_mode = 0; /*offset*/
2278 instruction->info.load_store.offset_mode = 0; /*immediate*/
2279 instruction->info.load_store.offset.offset = offset*4;
2280
2281 return ERROR_OK;
2282 }
2283
2284 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2285 uint32_t address, struct arm_instruction *instruction)
2286 {
2287 uint32_t imm = opcode & 0xff;
2288 uint8_t Rd = (opcode >> 8) & 0x7;
2289 uint8_t Rn;
2290 uint32_t SP = opcode & (1 << 11);
2291 char *reg_name;
2292
2293 instruction->type = ARM_ADD;
2294
2295 if (SP)
2296 {
2297 reg_name = "SP";
2298 Rn = 13;
2299 }
2300 else
2301 {
2302 reg_name = "PC";
2303 Rn = 15;
2304 }
2305
2306 snprintf(instruction->text, 128,
2307 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2308 address, opcode, Rd, reg_name, imm * 4);
2309
2310 instruction->info.data_proc.variant = 0 /* immediate */;
2311 instruction->info.data_proc.Rd = Rd;
2312 instruction->info.data_proc.Rn = Rn;
2313 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2314
2315 return ERROR_OK;
2316 }
2317
2318 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2319 uint32_t address, struct arm_instruction *instruction)
2320 {
2321 uint32_t imm = opcode & 0x7f;
2322 uint8_t opc = opcode & (1 << 7);
2323 char *mnemonic;
2324
2325
2326 if (opc)
2327 {
2328 instruction->type = ARM_SUB;
2329 mnemonic = "SUB";
2330 }
2331 else
2332 {
2333 instruction->type = ARM_ADD;
2334 mnemonic = "ADD";
2335 }
2336
2337 snprintf(instruction->text, 128,
2338 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2339 address, opcode, mnemonic, imm*4);
2340
2341 instruction->info.data_proc.variant = 0 /* immediate */;
2342 instruction->info.data_proc.Rd = 13 /*SP*/;
2343 instruction->info.data_proc.Rn = 13 /*SP*/;
2344 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2345
2346 return ERROR_OK;
2347 }
2348
2349 static int evaluate_breakpoint_thumb(uint16_t opcode,
2350 uint32_t address, struct arm_instruction *instruction)
2351 {
2352 uint32_t imm = opcode & 0xff;
2353
2354 instruction->type = ARM_BKPT;
2355
2356 snprintf(instruction->text, 128,
2357 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2358 address, opcode, imm);
2359
2360 return ERROR_OK;
2361 }
2362
2363 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2364 uint32_t address, struct arm_instruction *instruction)
2365 {
2366 uint32_t reg_list = opcode & 0xff;
2367 uint32_t L = opcode & (1 << 11);
2368 uint32_t R = opcode & (1 << 8);
2369 uint8_t Rn = (opcode >> 8) & 7;
2370 uint8_t addr_mode = 0 /* IA */;
2371 char reg_names[40];
2372 char *reg_names_p;
2373 char *mnemonic;
2374 char ptr_name[7] = "";
2375 int i;
2376
2377 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2378 * The STMIA and LDMIA opcodes are used for other instructions.
2379 */
2380
2381 if ((opcode & 0xf000) == 0xc000)
2382 { /* generic load/store multiple */
2383 char *wback = "!";
2384
2385 if (L)
2386 {
2387 instruction->type = ARM_LDM;
2388 mnemonic = "LDM";
2389 if (opcode & (1 << Rn))
2390 wback = "";
2391 }
2392 else
2393 {
2394 instruction->type = ARM_STM;
2395 mnemonic = "STM";
2396 }
2397 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2398 }
2399 else
2400 { /* push/pop */
2401 Rn = 13; /* SP */
2402 if (L)
2403 {
2404 instruction->type = ARM_LDM;
2405 mnemonic = "POP";
2406 if (R)
2407 reg_list |= (1 << 15) /*PC*/;
2408 }
2409 else
2410 {
2411 instruction->type = ARM_STM;
2412 mnemonic = "PUSH";
2413 addr_mode = 3; /*DB*/
2414 if (R)
2415 reg_list |= (1 << 14) /*LR*/;
2416 }
2417 }
2418
2419 reg_names_p = reg_names;
2420 for (i = 0; i <= 15; i++)
2421 {
2422 if (reg_list & (1 << i))
2423 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
2424 }
2425 if (reg_names_p > reg_names)
2426 reg_names_p[-2] = '\0';
2427 else /* invalid op : no registers */
2428 reg_names[0] = '\0';
2429
2430 snprintf(instruction->text, 128,
2431 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2432 address, opcode, mnemonic, ptr_name, reg_names);
2433
2434 instruction->info.load_store_multiple.register_list = reg_list;
2435 instruction->info.load_store_multiple.Rn = Rn;
2436 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2437
2438 return ERROR_OK;
2439 }
2440
2441 static int evaluate_cond_branch_thumb(uint16_t opcode,
2442 uint32_t address, struct arm_instruction *instruction)
2443 {
2444 uint32_t offset = opcode & 0xff;
2445 uint8_t cond = (opcode >> 8) & 0xf;
2446 uint32_t target_address;
2447
2448 if (cond == 0xf)
2449 {
2450 instruction->type = ARM_SWI;
2451 snprintf(instruction->text, 128,
2452 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2453 address, opcode, offset);
2454 return ERROR_OK;
2455 }
2456 else if (cond == 0xe)
2457 {
2458 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2459 snprintf(instruction->text, 128,
2460 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2461 address, opcode);
2462 return ERROR_OK;
2463 }
2464
2465 /* sign extend 8-bit offset */
2466 if (offset & 0x00000080)
2467 offset = 0xffffff00 | offset;
2468
2469 target_address = address + 4 + (offset << 1);
2470
2471 snprintf(instruction->text, 128,
2472 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2473 address, opcode,
2474 arm_condition_strings[cond], target_address);
2475
2476 instruction->type = ARM_B;
2477 instruction->info.b_bl_bx_blx.reg_operand = -1;
2478 instruction->info.b_bl_bx_blx.target_address = target_address;
2479
2480 return ERROR_OK;
2481 }
2482
2483 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2484 struct arm_instruction *instruction)
2485 {
2486 unsigned offset;
2487
2488 /* added in Thumb2 */
2489 offset = (opcode >> 3) & 0x1f;
2490 offset |= (opcode & 0x0200) >> 4;
2491
2492 snprintf(instruction->text, 128,
2493 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2494 address, opcode,
2495 (opcode & 0x0800) ? "N" : "",
2496 opcode & 0x7, address + 4 + (offset << 1));
2497
2498 return ERROR_OK;
2499 }
2500
2501 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2502 struct arm_instruction *instruction)
2503 {
2504 /* added in ARMv6 */
2505 snprintf(instruction->text, 128,
2506 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2507 address, opcode,
2508 (opcode & 0x0080) ? 'U' : 'S',
2509 (opcode & 0x0040) ? 'B' : 'H',
2510 opcode & 0x7, (opcode >> 3) & 0x7);
2511
2512 return ERROR_OK;
2513 }
2514
2515 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2516 struct arm_instruction *instruction)
2517 {
2518 /* added in ARMv6 */
2519 if ((opcode & 0x0ff0) == 0x0650)
2520 snprintf(instruction->text, 128,
2521 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2522 address, opcode,
2523 (opcode & 0x80) ? "BE" : "LE");
2524 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2525 snprintf(instruction->text, 128,
2526 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2527 address, opcode,
2528 (opcode & 0x0010) ? 'D' : 'E',
2529 (opcode & 0x0004) ? "A" : "",
2530 (opcode & 0x0002) ? "I" : "",
2531 (opcode & 0x0001) ? "F" : "");
2532
2533 return ERROR_OK;
2534 }
2535
2536 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2537 struct arm_instruction *instruction)
2538 {
2539 char *suffix;
2540
2541 /* added in ARMv6 */
2542 switch ((opcode >> 6) & 3) {
2543 case 0:
2544 suffix = "";
2545 break;
2546 case 1:
2547 suffix = "16";
2548 break;
2549 default:
2550 suffix = "SH";
2551 break;
2552 }
2553 snprintf(instruction->text, 128,
2554 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2555 address, opcode, suffix,
2556 opcode & 0x7, (opcode >> 3) & 0x7);
2557
2558 return ERROR_OK;
2559 }
2560
2561 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2562 struct arm_instruction *instruction)
2563 {
2564 char *hint;
2565
2566 switch ((opcode >> 4) & 0x0f) {
2567 case 0:
2568 hint = "NOP";
2569 break;
2570 case 1:
2571 hint = "YIELD";
2572 break;
2573 case 2:
2574 hint = "WFE";
2575 break;
2576 case 3:
2577 hint = "WFI";
2578 break;
2579 case 4:
2580 hint = "SEV";
2581 break;
2582 default:
2583 hint = "HINT (UNRECOGNIZED)";
2584 break;
2585 }
2586
2587 snprintf(instruction->text, 128,
2588 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2589 address, opcode, hint);
2590
2591 return ERROR_OK;
2592 }
2593
2594 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2595 struct arm_instruction *instruction)
2596 {
2597 unsigned cond = (opcode >> 4) & 0x0f;
2598 char *x = "", *y = "", *z = "";
2599
2600 if (opcode & 0x01)
2601 z = (opcode & 0x02) ? "T" : "E";
2602 if (opcode & 0x03)
2603 y = (opcode & 0x04) ? "T" : "E";
2604 if (opcode & 0x07)
2605 x = (opcode & 0x08) ? "T" : "E";
2606
2607 snprintf(instruction->text, 128,
2608 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2609 address, opcode,
2610 x, y, z, arm_condition_strings[cond]);
2611
2612 /* NOTE: strictly speaking, the next 1-4 instructions should
2613 * now be displayed with the relevant conditional suffix...
2614 */
2615
2616 return ERROR_OK;
2617 }
2618
2619 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2620 {
2621 /* clear fields, to avoid confusion */
2622 memset(instruction, 0, sizeof(struct arm_instruction));
2623 instruction->opcode = opcode;
2624 instruction->instruction_size = 2;
2625
2626 if ((opcode & 0xe000) == 0x0000)
2627 {
2628 /* add/substract register or immediate */
2629 if ((opcode & 0x1800) == 0x1800)
2630 return evaluate_add_sub_thumb(opcode, address, instruction);
2631 /* shift by immediate */
2632 else
2633 return evaluate_shift_imm_thumb(opcode, address, instruction);
2634 }
2635
2636 /* Add/substract/compare/move immediate */
2637 if ((opcode & 0xe000) == 0x2000)
2638 {
2639 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2640 }
2641
2642 /* Data processing instructions */
2643 if ((opcode & 0xf800) == 0x4000)
2644 {
2645 return evaluate_data_proc_thumb(opcode, address, instruction);
2646 }
2647
2648 /* Load from literal pool */
2649 if ((opcode & 0xf800) == 0x4800)
2650 {
2651 return evaluate_load_literal_thumb(opcode, address, instruction);
2652 }
2653
2654 /* Load/Store register offset */
2655 if ((opcode & 0xf000) == 0x5000)
2656 {
2657 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2658 }
2659
2660 /* Load/Store immediate offset */
2661 if (((opcode & 0xe000) == 0x6000)
2662 ||((opcode & 0xf000) == 0x8000))
2663 {
2664 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2665 }
2666
2667 /* Load/Store from/to stack */
2668 if ((opcode & 0xf000) == 0x9000)
2669 {
2670 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2671 }
2672
2673 /* Add to SP/PC */
2674 if ((opcode & 0xf000) == 0xa000)
2675 {
2676 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2677 }
2678
2679 /* Misc */
2680 if ((opcode & 0xf000) == 0xb000)
2681 {
2682 switch ((opcode >> 8) & 0x0f) {
2683 case 0x0:
2684 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2685 case 0x1:
2686 case 0x3:
2687 case 0x9:
2688 case 0xb:
2689 return evaluate_cb_thumb(opcode, address, instruction);
2690 case 0x2:
2691 return evaluate_extend_thumb(opcode, address, instruction);
2692 case 0x4:
2693 case 0x5:
2694 case 0xc:
2695 case 0xd:
2696 return evaluate_load_store_multiple_thumb(opcode, address,
2697 instruction);
2698 case 0x6:
2699 return evaluate_cps_thumb(opcode, address, instruction);
2700 case 0xa:
2701 if ((opcode & 0x00c0) == 0x0080)
2702 break;
2703 return evaluate_byterev_thumb(opcode, address, instruction);
2704 case 0xe:
2705 return evaluate_breakpoint_thumb(opcode, address, instruction);
2706 case 0xf:
2707 if (opcode & 0x000f)
2708 return evaluate_ifthen_thumb(opcode, address,
2709 instruction);
2710 else
2711 return evaluate_hint_thumb(opcode, address,
2712 instruction);
2713 }
2714
2715 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2716 snprintf(instruction->text, 128,
2717 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2718 address, opcode);
2719 return ERROR_OK;
2720 }
2721
2722 /* Load/Store multiple */
2723 if ((opcode & 0xf000) == 0xc000)
2724 {
2725 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2726 }
2727
2728 /* Conditional branch + SWI */
2729 if ((opcode & 0xf000) == 0xd000)
2730 {
2731 return evaluate_cond_branch_thumb(opcode, address, instruction);
2732 }
2733
2734 if ((opcode & 0xe000) == 0xe000)
2735 {
2736 /* Undefined instructions */
2737 if ((opcode & 0xf801) == 0xe801)
2738 {
2739 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2740 snprintf(instruction->text, 128,
2741 "0x%8.8" PRIx32 " 0x%8.8x\t"
2742 "UNDEFINED INSTRUCTION",
2743 address, opcode);
2744 return ERROR_OK;
2745 }
2746 else
2747 { /* Branch to offset */
2748 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2749 }
2750 }
2751
2752 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2753 return -1;
2754 }
2755
2756 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2757 struct arm_instruction *instruction, char *cp)
2758 {
2759 unsigned offset;
2760 unsigned b21 = 1 << 21;
2761 unsigned b22 = 1 << 22;
2762
2763 /* instead of combining two smaller 16-bit branch instructions,
2764 * Thumb2 uses only one larger 32-bit instruction.
2765 */
2766 offset = opcode & 0x7ff;
2767 offset |= (opcode & 0x03ff0000) >> 5;
2768 if (opcode & (1 << 26)) {
2769 offset |= 0xff << 23;
2770 if ((opcode & (1 << 11)) == 0)
2771 b21 = 0;
2772 if ((opcode & (1 << 13)) == 0)
2773 b22 = 0;
2774 } else {
2775 if (opcode & (1 << 11))
2776 b21 = 0;
2777 if (opcode & (1 << 13))
2778 b22 = 0;
2779 }
2780 offset |= b21;
2781 offset |= b22;
2782
2783
2784 address += 4;
2785 address += offset << 1;
2786
2787 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2788 instruction->info.b_bl_bx_blx.reg_operand = -1;
2789 instruction->info.b_bl_bx_blx.target_address = address;
2790 sprintf(cp, "%s\t%#8.8" PRIx32,
2791 (opcode & (1 << 14)) ? "BL" : "B.W",
2792 address);
2793
2794 return ERROR_OK;
2795 }
2796
2797 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2798 struct arm_instruction *instruction, char *cp)
2799 {
2800 unsigned offset;
2801 unsigned b17 = 1 << 17;
2802 unsigned b18 = 1 << 18;
2803 unsigned cond = (opcode >> 22) & 0x0f;
2804
2805 offset = opcode & 0x7ff;
2806 offset |= (opcode & 0x003f0000) >> 5;
2807 if (opcode & (1 << 26)) {
2808 offset |= 0xffff << 19;
2809 if ((opcode & (1 << 11)) == 0)
2810 b17 = 0;
2811 if ((opcode & (1 << 13)) == 0)
2812 b18 = 0;
2813 } else {
2814 if (opcode & (1 << 11))
2815 b17 = 0;
2816 if (opcode & (1 << 13))
2817 b18 = 0;
2818 }
2819 offset |= b17;
2820 offset |= b18;
2821
2822 address += 4;
2823 address += offset << 1;
2824
2825 instruction->type = ARM_B;
2826 instruction->info.b_bl_bx_blx.reg_operand = -1;
2827 instruction->info.b_bl_bx_blx.target_address = address;
2828 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2829 arm_condition_strings[cond],
2830 address);
2831
2832 return ERROR_OK;
2833 }
2834
2835 static const char *special_name(int number)
2836 {
2837 char *special = "(RESERVED)";
2838
2839 switch (number) {
2840 case 0:
2841 special = "apsr";
2842 break;
2843 case 1:
2844 special = "iapsr";
2845 break;
2846 case 2:
2847 special = "eapsr";
2848 break;
2849 case 3:
2850 special = "xpsr";
2851 break;
2852 case 5:
2853 special = "ipsr";
2854 break;
2855 case 6:
2856 special = "epsr";
2857 break;
2858 case 7:
2859 special = "iepsr";
2860 break;
2861 case 8:
2862 special = "msp";
2863 break;
2864 case 9:
2865 special = "psp";
2866 break;
2867 case 16:
2868 special = "primask";
2869 break;
2870 case 17:
2871 special = "basepri";
2872 break;
2873 case 18:
2874 special = "basepri_max";
2875 break;
2876 case 19:
2877 special = "faultmask";
2878 break;
2879 case 20:
2880 special = "control";
2881 break;
2882 }
2883 return special;
2884 }
2885
2886 static int t2ev_hint(uint32_t opcode, uint32_t address,
2887 struct arm_instruction *instruction, char *cp)
2888 {
2889 const char *mnemonic;
2890
2891 if (opcode & 0x0700) {
2892 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2893 strcpy(cp, "UNDEFINED");
2894 return ERROR_OK;
2895 }
2896
2897 if (opcode & 0x00f0) {
2898 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2899 return ERROR_OK;
2900 }
2901
2902 switch (opcode & 0x0f) {
2903 case 0:
2904 mnemonic = "NOP.W";
2905 break;
2906 case 1:
2907 mnemonic = "YIELD.W";
2908 break;
2909 case 2:
2910 mnemonic = "WFE.W";
2911 break;
2912 case 3:
2913 mnemonic = "WFI.W";
2914 break;
2915 case 4:
2916 mnemonic = "SEV.W";
2917 break;
2918 default:
2919 mnemonic = "HINT.W (UNRECOGNIZED)";
2920 break;
2921 }
2922 strcpy(cp, mnemonic);
2923 return ERROR_OK;
2924 }
2925
2926 static int t2ev_misc(uint32_t opcode, uint32_t address,
2927 struct arm_instruction *instruction, char *cp)
2928 {
2929 const char *mnemonic;
2930
2931 switch ((opcode >> 4) & 0x0f) {
2932 case 0:
2933 mnemonic = "LEAVEX";
2934 break;
2935 case 1:
2936 mnemonic = "ENTERX";
2937 break;
2938 case 2:
2939 mnemonic = "CLREX";
2940 break;
2941 case 4:
2942 mnemonic = "DSB";
2943 break;
2944 case 5:
2945 mnemonic = "DMB";
2946 break;
2947 case 6:
2948 mnemonic = "ISB";
2949 break;
2950 default:
2951 return ERROR_INVALID_ARGUMENTS;
2952 }
2953 strcpy(cp, mnemonic);
2954 return ERROR_OK;
2955 }
2956
2957 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2958 struct arm_instruction *instruction, char *cp)
2959 {
2960 /* permanently undefined */
2961 if ((opcode & 0x07f07000) == 0x07f02000) {
2962 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2963 strcpy(cp, "UNDEFINED");
2964 return ERROR_OK;
2965 }
2966
2967 switch ((opcode >> 12) & 0x5) {
2968 case 0x1:
2969 case 0x5:
2970 return t2ev_b_bl(opcode, address, instruction, cp);
2971 case 0x4:
2972 goto undef;
2973 case 0:
2974 if (((opcode >> 23) & 0x07) != 0x07)
2975 return t2ev_cond_b(opcode, address, instruction, cp);
2976 if (opcode & (1 << 26))
2977 goto undef;
2978 break;
2979 }
2980
2981 switch ((opcode >> 20) & 0x7f) {
2982 case 0x38:
2983 case 0x39:
2984 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2985 (int) (opcode >> 16) & 0x0f);
2986 return ERROR_OK;
2987 case 0x3a:
2988 return t2ev_hint(opcode, address, instruction, cp);
2989 case 0x3b:
2990 return t2ev_misc(opcode, address, instruction, cp);
2991 case 0x3c:
2992 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
2993 return ERROR_OK;
2994 case 0x3e:
2995 case 0x3f:
2996 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2997 special_name(opcode & 0xff));
2998 return ERROR_OK;
2999 }
3000
3001 undef:
3002 return ERROR_INVALID_ARGUMENTS;
3003 }
3004
3005 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3006 struct arm_instruction *instruction, char *cp)
3007 {
3008 char *mnemonic = NULL;
3009 int rn = (opcode >> 16) & 0xf;
3010 int rd = (opcode >> 8) & 0xf;
3011 unsigned immed = opcode & 0xff;
3012 unsigned func;
3013 bool one = false;
3014 char *suffix = "";
3015 char *suffix2 = "";
3016
3017 /* ARMv7-M: A5.3.2 Modified immediate constants */
3018 func = (opcode >> 11) & 0x0e;
3019 if (immed & 0x80)
3020 func |= 1;
3021 if (opcode & (1 << 26))
3022 func |= 0x10;
3023
3024 /* "Modified" immediates */
3025 switch (func >> 1) {
3026 case 0:
3027 break;
3028 case 2:
3029 immed <<= 8;
3030 /* FALLTHROUGH */
3031 case 1:
3032 immed += immed << 16;
3033 break;
3034 case 3:
3035 immed += immed << 8;
3036 immed += immed << 16;
3037 break;
3038 default:
3039 immed |= 0x80;
3040 immed = ror(immed, func);
3041 }
3042
3043 if (opcode & (1 << 20))
3044 suffix = "S";
3045
3046 switch ((opcode >> 21) & 0xf) {
3047 case 0:
3048 if (rd == 0xf) {
3049 instruction->type = ARM_TST;
3050 mnemonic = "TST";
3051 one = true;
3052 suffix = "";
3053 rd = rn;
3054 } else {
3055 instruction->type = ARM_AND;
3056 mnemonic = "AND";
3057 }
3058 break;
3059 case 1:
3060 instruction->type = ARM_BIC;
3061 mnemonic = "BIC";
3062 break;
3063 case 2:
3064 if (rn == 0xf) {
3065 instruction->type = ARM_MOV;
3066 mnemonic = "MOV";
3067 one = true;
3068 suffix2 = ".W";
3069 } else {
3070 instruction->type = ARM_ORR;
3071 mnemonic = "ORR";
3072 }
3073 break;
3074 case 3:
3075 if (rn == 0xf) {
3076 instruction->type = ARM_MVN;
3077 mnemonic = "MVN";
3078 one = true;
3079 } else {
3080 // instruction->type = ARM_ORN;
3081 mnemonic = "ORN";
3082 }
3083 break;
3084 case 4:
3085 if (rd == 0xf) {
3086 instruction->type = ARM_TEQ;
3087 mnemonic = "TEQ";
3088 one = true;
3089 suffix = "";
3090 rd = rn;
3091 } else {
3092 instruction->type = ARM_EOR;
3093 mnemonic = "EOR";
3094 }
3095 break;
3096 case 8:
3097 if (rd == 0xf) {
3098 instruction->type = ARM_CMN;
3099 mnemonic = "CMN";
3100 one = true;
3101 suffix = "";
3102 rd = rn;
3103 } else {
3104 instruction->type = ARM_ADD;
3105 mnemonic = "ADD";
3106 suffix2 = ".W";
3107 }
3108 break;
3109 case 10:
3110 instruction->type = ARM_ADC;
3111 mnemonic = "ADC";
3112 suffix2 = ".W";
3113 break;
3114 case 11:
3115 instruction->type = ARM_SBC;
3116 mnemonic = "SBC";
3117 break;
3118 case 13:
3119 if (rd == 0xf) {
3120 instruction->type = ARM_CMP;
3121 mnemonic = "CMP";
3122 one = true;
3123 suffix = "";
3124 rd = rn;
3125 } else {
3126 instruction->type = ARM_SUB;
3127 mnemonic = "SUB";
3128 }
3129 suffix2 = ".W";
3130 break;
3131 case 14:
3132 instruction->type = ARM_RSB;
3133 mnemonic = "RSB";
3134 suffix2 = ".W";
3135 break;
3136 default:
3137 return ERROR_INVALID_ARGUMENTS;
3138 }
3139
3140 if (one)
3141 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3142 mnemonic, suffix2 ,rd, immed, immed);
3143 else
3144 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3145 mnemonic, suffix, suffix2,
3146 rd, rn, immed, immed);
3147
3148 return ERROR_OK;
3149 }
3150
3151 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3152 struct arm_instruction *instruction, char *cp)
3153 {
3154 char *mnemonic = NULL;
3155 int rn = (opcode >> 16) & 0xf;
3156 int rd = (opcode >> 8) & 0xf;
3157 unsigned immed;
3158 bool add = false;
3159 bool is_signed = false;
3160
3161 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3162 if (opcode & (1 << 26))
3163 immed |= (1 << 11);
3164
3165 switch ((opcode >> 20) & 0x1f) {
3166 case 0:
3167 if (rn == 0xf) {
3168 add = true;
3169 goto do_adr;
3170 }
3171 mnemonic = "ADDW";
3172 break;
3173 case 4:
3174 immed |= (opcode >> 4) & 0xf000;
3175 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3176 return ERROR_OK;
3177 case 0x0a:
3178 if (rn == 0xf)
3179 goto do_adr;
3180 mnemonic = "SUBW";
3181 break;
3182 case 0x0c:
3183 /* move constant to top 16 bits of register */
3184 immed |= (opcode >> 4) & 0xf000;
3185 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
3186 return ERROR_OK;
3187 case 0x10:
3188 case 0x12:
3189 is_signed = true;
3190 case 0x18:
3191 case 0x1a:
3192 /* signed/unsigned saturated add */
3193 immed = (opcode >> 6) & 0x03;
3194 immed |= (opcode >> 10) & 0x1c;
3195 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3196 is_signed ? "S" : "U",
3197 rd, (int) (opcode & 0x1f) + is_signed, rn,
3198 (opcode & (1 << 21)) ? "ASR" : "LSL",
3199 immed ? immed : 32);
3200 return ERROR_OK;
3201 case 0x14:
3202 is_signed = true;
3203 /* FALLTHROUGH */
3204 case 0x1c:
3205 /* signed/unsigned bitfield extract */
3206 immed = (opcode >> 6) & 0x03;
3207 immed |= (opcode >> 10) & 0x1c;
3208 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3209 is_signed ? "S" : "U",
3210 rd, rn, immed,
3211 (int) (opcode & 0x1f) + 1);
3212 return ERROR_OK;
3213 case 0x16:
3214 immed = (opcode >> 6) & 0x03;
3215 immed |= (opcode >> 10) & 0x1c;
3216 if (rn == 0xf) /* bitfield clear */
3217 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3218 rd, immed,
3219 (int) (opcode & 0x1f) + 1 - immed);
3220 else /* bitfield insert */
3221 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3222 rd, rn, immed,
3223 (int) (opcode & 0x1f) + 1 - immed);
3224 return ERROR_OK;
3225 default:
3226 return ERROR_INVALID_ARGUMENTS;
3227 }
3228
3229 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3230 rd, rn, immed, immed);
3231 return ERROR_OK;
3232
3233 do_adr:
3234 address = thumb_alignpc4(address);
3235 if (add)
3236 address += immed;
3237 else
3238 address -= immed;
3239 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3240 * not hiding the pc-relative stuff will sometimes be useful.
3241 */
3242 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3243 return ERROR_OK;
3244 }
3245
3246 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3247 struct arm_instruction *instruction, char *cp)
3248 {
3249 unsigned op = (opcode >> 20) & 0xf;
3250 char *size = "";
3251 char *suffix = "";
3252 char *p1 = "";
3253 char *p2 = "]";
3254 unsigned immed;
3255 unsigned rn = (opcode >> 16) & 0x0f;
3256 unsigned rt = (opcode >> 12) & 0x0f;
3257
3258 if (rn == 0xf)
3259 return ERROR_INVALID_ARGUMENTS;
3260
3261 if (opcode & 0x0800)
3262 op |= 1;
3263 switch (op) {
3264 /* byte */
3265 case 0x8:
3266 case 0x9:
3267 size = "B";
3268 goto imm12;
3269 case 0x1:
3270 size = "B";
3271 goto imm8;
3272 case 0x0:
3273 size = "B";
3274 break;
3275 /* halfword */
3276 case 0xa:
3277 case 0xb:
3278 size = "H";
3279 goto imm12;
3280 case 0x3:
3281 size = "H";
3282 goto imm8;
3283 case 0x2:
3284 size = "H";
3285 break;
3286 /* word */
3287 case 0xc:
3288 case 0xd:
3289 goto imm12;
3290 case 0x5:
3291 goto imm8;
3292 case 0x4:
3293 break;
3294 /* error */
3295 default:
3296 return ERROR_INVALID_ARGUMENTS;
3297 }
3298
3299 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3300 size, rt, rn, (int) opcode & 0x0f,
3301 (int) (opcode >> 4) & 0x03);
3302 return ERROR_OK;
3303
3304 imm12:
3305 immed = opcode & 0x0fff;
3306 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3307 size, rt, rn, immed, immed);
3308 return ERROR_OK;
3309
3310 imm8:
3311 immed = opcode & 0x00ff;
3312
3313 switch (opcode & 0x700) {
3314 case 0x600:
3315 suffix = "T";
3316 break;
3317 case 0x000:
3318 case 0x200:
3319 return ERROR_INVALID_ARGUMENTS;
3320 }
3321
3322 /* two indexed modes will write back rn */
3323 if (opcode & 0x100) {
3324 if (opcode & 0x400) /* pre-indexed */
3325 p2 = "]!";
3326 else { /* post-indexed */
3327 p1 = "]";
3328 p2 = "";
3329 }
3330 }
3331
3332 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3333 size, suffix, rt, rn, p1,
3334 (opcode & 0x200) ? "" : "-",
3335 immed, p2, immed);
3336 return ERROR_OK;
3337 }
3338
3339 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3340 struct arm_instruction *instruction, char *cp)
3341 {
3342 int ra = (opcode >> 12) & 0xf;
3343
3344 switch (opcode & 0x007000f0) {
3345 case 0:
3346 if (ra == 0xf)
3347 sprintf(cp, "MUL\tr%d, r%d, r%d",
3348 (int) (opcode >> 8) & 0xf,
3349 (int) (opcode >> 16) & 0xf,
3350 (int) (opcode >> 0) & 0xf);
3351 else
3352 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3353 (int) (opcode >> 8) & 0xf,
3354 (int) (opcode >> 16) & 0xf,
3355 (int) (opcode >> 0) & 0xf, ra);
3356 break;
3357 case 0x10:
3358 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3359 (int) (opcode >> 8) & 0xf,
3360 (int) (opcode >> 16) & 0xf,
3361 (int) (opcode >> 0) & 0xf, ra);
3362 break;
3363 default:
3364 return ERROR_INVALID_ARGUMENTS;
3365 }
3366 return ERROR_OK;
3367 }
3368
3369 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3370 struct arm_instruction *instruction, char *cp)
3371 {
3372 int op = (opcode >> 4) & 0xf;
3373 char *infix = "MUL";
3374
3375 op += (opcode >> 16) & 0x70;
3376 switch (op) {
3377 case 0x40:
3378 case 0x60:
3379 infix = "MLA";
3380 /* FALLTHROUGH */
3381 case 0:
3382 case 0x20:
3383 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3384 (op & 0x20) ? 'U' : 'S',
3385 infix,
3386 (int) (opcode >> 12) & 0xf,
3387 (int) (opcode >> 8) & 0xf,
3388 (int) (opcode >> 16) & 0xf,
3389 (int) (opcode >> 0) & 0xf);
3390 break;
3391 case 0x1f:
3392 case 0x3f:
3393 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3394 (op & 0x20) ? 'U' : 'S',
3395 (int) (opcode >> 8) & 0xf,
3396 (int) (opcode >> 16) & 0xf,
3397 (int) (opcode >> 0) & 0xf);
3398 break;
3399 default:
3400 return ERROR_INVALID_ARGUMENTS;
3401 }
3402
3403 return ERROR_OK;
3404 }
3405
3406 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3407 struct arm_instruction *instruction, char *cp)
3408 {
3409 int rn = (opcode >> 16) & 0xf;
3410 int op = (opcode >> 22) & 0x6;
3411 int t = (opcode >> 21) & 1;
3412 unsigned registers = opcode & 0xffff;
3413
3414 if (opcode & (1 << 20))
3415 op |= 1;
3416
3417 switch (op) {
3418 case 2:
3419 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3420 break;
3421 case 3:
3422 if (rn == 13 && t)
3423 sprintf(cp, "POP.W\t");
3424 else
3425 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3426 break;
3427 case 4:
3428 if (rn == 13 && t)
3429 sprintf(cp, "PUSH.W\t");
3430 else
3431 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3432 break;
3433 case 5:
3434 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3435 break;
3436 default:
3437 return ERROR_INVALID_ARGUMENTS;
3438 }
3439
3440 cp = strchr(cp, 0);
3441 *cp++ = '{';
3442 for (t = 0; registers; t++, registers >>= 1) {
3443 if ((registers & 1) == 0)
3444 continue;
3445 registers &= ~1;
3446 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3447 cp = strchr(cp, 0);
3448 }
3449 *cp++ = '}';
3450 *cp++ = 0;
3451
3452 return ERROR_OK;
3453 }
3454
3455 /* load/store dual or exclusive, table branch */
3456 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3457 struct arm_instruction *instruction, char *cp)
3458 {
3459 unsigned op1op2 = (opcode >> 20) & 0x3;
3460 unsigned op3 = (opcode >> 4) & 0xf;
3461 char *mnemonic;
3462 unsigned rn = (opcode >> 16) & 0xf;
3463 unsigned rt = (opcode >> 12) & 0xf;
3464 unsigned rd = (opcode >> 8) & 0xf;
3465 unsigned imm = opcode & 0xff;
3466 char *p1 = "";
3467 char *p2 = "]";
3468
3469 op1op2 |= (opcode >> 21) & 0xc;
3470 switch (op1op2) {
3471 case 0:
3472 mnemonic = "STREX";
3473 goto strex;
3474 case 1:
3475 mnemonic = "LDREX";
3476 goto ldrex;
3477 case 2:
3478 case 6:
3479 case 8:
3480 case 10:
3481 case 12:
3482 case 14:
3483 mnemonic = "STRD";
3484 goto immediate;
3485 case 3:
3486 case 7:
3487 case 9:
3488 case 11:
3489 case 13:
3490 case 15:
3491 mnemonic = "LDRD";
3492 if (rn == 15)
3493 goto literal;
3494 else
3495 goto immediate;
3496 case 4:
3497 switch (op3) {
3498 case 4:
3499 mnemonic = "STREXB";
3500 break;
3501 case 5:
3502 mnemonic = "STREXH";
3503 break;
3504 default:
3505 return ERROR_INVALID_ARGUMENTS;
3506 }
3507 rd = opcode & 0xf;
3508 imm = 0;
3509 goto strex;
3510 case 5:
3511 switch (op3) {
3512 case 0:
3513 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3514 return ERROR_OK;
3515 case 1:
3516 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3517 return ERROR_OK;
3518 case 4:
3519 mnemonic = "LDREXB";
3520 break;
3521 case 5:
3522 mnemonic = "LDREXH";
3523 break;
3524 default:
3525 return ERROR_INVALID_ARGUMENTS;
3526 }
3527 imm = 0;
3528 goto ldrex;
3529 }
3530 return ERROR_INVALID_ARGUMENTS;
3531
3532 strex:
3533 imm <<= 2;
3534 if (imm)
3535 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3536 mnemonic, rd, rt, rn, imm, imm);
3537 else
3538 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3539 mnemonic, rd, rt, rn);
3540 return ERROR_OK;
3541
3542 ldrex:
3543 imm <<= 2;
3544 if (imm)
3545 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3546 mnemonic, rt, rn, imm, imm);
3547 else
3548 sprintf(cp, "%s\tr%u, [r%u]",
3549 mnemonic, rt, rn);
3550 return ERROR_OK;
3551
3552 immediate:
3553 /* two indexed modes will write back rn */
3554 if (opcode & (1 << 21)) {
3555 if (opcode & (1 << 24)) /* pre-indexed */
3556 p2 = "]!";
3557 else { /* post-indexed */
3558 p1 = "]";
3559 p2 = "";
3560 }
3561 }
3562
3563 imm <<= 2;
3564 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3565 mnemonic, rt, rd, rn, p1,
3566 (opcode & (1 << 23)) ? "" : "-",
3567 imm, p2, imm);
3568 return ERROR_OK;
3569
3570 literal:
3571 address = thumb_alignpc4(address);
3572 imm <<= 2;
3573 if (opcode & (1 << 23))
3574 address += imm;
3575 else
3576 address -= imm;
3577 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3578 mnemonic, rt, rd, address);
3579 return ERROR_OK;
3580 }
3581
3582 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3583 struct arm_instruction *instruction, char *cp)
3584 {
3585 int op = (opcode >> 21) & 0xf;
3586 int rd = (opcode >> 8) & 0xf;
3587 int rn = (opcode >> 16) & 0xf;
3588 int type = (opcode >> 4) & 0x3;
3589 int immed = (opcode >> 6) & 0x3;
3590 char *mnemonic;
3591 char *suffix = "";
3592
3593 immed |= (opcode >> 10) & 0x1c;
3594 if (opcode & (1 << 20))
3595 suffix = "S";
3596
3597 switch (op) {
3598 case 0:
3599 if (rd == 0xf) {
3600 if (!(opcode & (1 << 20)))
3601 return ERROR_INVALID_ARGUMENTS;
3602 instruction->type = ARM_TST;
3603 mnemonic = "TST";
3604 suffix = "";
3605 goto two;
3606 }
3607 instruction->type = ARM_AND;
3608 mnemonic = "AND";
3609 break;
3610 case 1:
3611 instruction->type = ARM_BIC;
3612 mnemonic = "BIC";
3613 break;
3614 case 2:
3615 if (rn == 0xf) {
3616 instruction->type = ARM_MOV;
3617 switch (type) {
3618 case 0:
3619 if (immed == 0) {
3620 sprintf(cp, "MOV%s.W\tr%d, r%d",
3621 suffix, rd,
3622 (int) (opcode & 0xf));
3623 return ERROR_OK;
3624 }
3625 mnemonic = "LSL";
3626 break;
3627 case 1:
3628 mnemonic = "LSR";
3629 break;
3630 case 2:
3631 mnemonic = "ASR";
3632 break;
3633 default:
3634 if (immed == 0) {
3635 sprintf(cp, "RRX%s\tr%d, r%d",
3636 suffix, rd,
3637 (int) (opcode & 0xf));
3638 return ERROR_OK;
3639 }
3640 mnemonic = "ROR";
3641 break;
3642 }
3643 goto immediate;
3644 } else {
3645 instruction->type = ARM_ORR;
3646 mnemonic = "ORR";
3647 }
3648 break;
3649 case 3:
3650 if (rn == 0xf) {
3651 instruction->type = ARM_MVN;
3652 mnemonic = "MVN";
3653 rn = rd;
3654 goto two;
3655 } else {
3656 // instruction->type = ARM_ORN;
3657 mnemonic = "ORN";
3658 }
3659 break;
3660 case 4:
3661 if (rd == 0xf) {
3662 if (!(opcode & (1 << 20)))
3663 return ERROR_INVALID_ARGUMENTS;
3664 instruction->type = ARM_TEQ;
3665 mnemonic = "TEQ";
3666 suffix = "";
3667 goto two;
3668 }
3669 instruction->type = ARM_EOR;
3670 mnemonic = "EOR";
3671 break;
3672 case 8:
3673 if (rd == 0xf) {
3674 if (!(opcode & (1 << 20)))
3675 return ERROR_INVALID_ARGUMENTS;
3676 instruction->type = ARM_CMN;
3677 mnemonic = "CMN";
3678 suffix = "";
3679 goto two;
3680 }
3681 instruction->type = ARM_ADD;
3682 mnemonic = "ADD";
3683 break;
3684 case 0xa:
3685 instruction->type = ARM_ADC;
3686 mnemonic = "ADC";
3687 break;
3688 case 0xb:
3689 instruction->type = ARM_SBC;
3690 mnemonic = "SBC";
3691 break;
3692 case 0xd:
3693 if (rd == 0xf) {
3694 if (!(opcode & (1 << 21)))
3695 return ERROR_INVALID_ARGUMENTS;
3696 instruction->type = ARM_CMP;
3697 mnemonic = "CMP";
3698 suffix = "";
3699 goto two;
3700 }
3701 instruction->type = ARM_SUB;
3702 mnemonic = "SUB";
3703 break;
3704 case 0xe:
3705 instruction->type = ARM_RSB;
3706 mnemonic = "RSB";
3707 break;
3708 default:
3709 return ERROR_INVALID_ARGUMENTS;
3710 }
3711
3712 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3713 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3714
3715 shift:
3716 cp = strchr(cp, 0);
3717
3718 switch (type) {
3719 case 0:
3720 if (immed == 0)
3721 return ERROR_OK;
3722 suffix = "LSL";
3723 break;
3724 case 1:
3725 suffix = "LSR";
3726 if (immed == 32)
3727 immed = 0;
3728 break;
3729 case 2:
3730 suffix = "ASR";
3731 if (immed == 32)
3732 immed = 0;
3733 break;
3734 case 3:
3735 if (immed == 0) {
3736 strcpy(cp, ", RRX");
3737 return ERROR_OK;
3738 }
3739 suffix = "ROR";
3740 break;
3741 }
3742 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3743 return ERROR_OK;
3744
3745 two:
3746 sprintf(cp, "%s%s.W\tr%d, r%d",
3747 mnemonic, suffix, rn, (int) (opcode & 0xf));
3748 goto shift;
3749
3750 immediate:
3751 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3752 mnemonic, suffix, rd,
3753 (int) (opcode & 0xf), immed ? immed : 32);
3754 return ERROR_OK;
3755 }
3756
3757 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3758 struct arm_instruction *instruction, char *cp)
3759 {
3760 char *mnemonic;
3761 char * suffix = "";
3762
3763 if (((opcode >> 4) & 0xf) == 0) {
3764 switch ((opcode >> 21) & 0x7) {
3765 case 0:
3766 mnemonic = "LSL";
3767 break;
3768 case 1:
3769 mnemonic = "LSR";
3770 break;
3771 case 2:
3772 mnemonic = "ASR";
3773 break;
3774 case 3:
3775 mnemonic = "ROR";
3776 break;
3777 default:
3778 return ERROR_INVALID_ARGUMENTS;
3779 }
3780
3781 instruction->type = ARM_MOV;
3782 if (opcode & (1 << 20))
3783 suffix = "S";
3784 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3785 mnemonic, suffix,
3786 (int) (opcode >> 8) & 0xf,
3787 (int) (opcode >> 16) & 0xf,
3788 (int) (opcode >> 0) & 0xf);
3789
3790 } else if (opcode & (1 << 7)) {
3791 switch ((opcode >> 20) & 0xf) {
3792 case 0:
3793 case 1:
3794 case 4:
3795 case 5:
3796 switch ((opcode >> 4) & 0x3) {
3797 case 1:
3798 suffix = ", ROR #8";
3799 break;
3800 case 2:
3801 suffix = ", ROR #16";
3802 break;
3803 case 3:
3804 suffix = ", ROR #24";
3805 break;
3806 }
3807 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3808 (opcode & (1 << 24)) ? 'U' : 'S',
3809 (opcode & (1 << 26)) ? 'B' : 'H',
3810 (int) (opcode >> 8) & 0xf,
3811 (int) (opcode >> 0) & 0xf,
3812 suffix);
3813 break;
3814 case 8:
3815 case 9:
3816 case 0xa:
3817 case 0xb:
3818 if (opcode & (1 << 6))
3819 return ERROR_INVALID_ARGUMENTS;
3820 if (((opcode >> 12) & 0xf) != 0xf)
3821 return ERROR_INVALID_ARGUMENTS;
3822 if (!(opcode & (1 << 20)))
3823 return ERROR_INVALID_ARGUMENTS;
3824
3825 switch (((opcode >> 19) & 0x04)
3826 | ((opcode >> 4) & 0x3)) {
3827 case 0:
3828 mnemonic = "REV.W";
3829 break;
3830 case 1:
3831 mnemonic = "REV16.W";
3832 break;
3833 case 2:
3834 mnemonic = "RBIT";
3835 break;
3836 case 3:
3837 mnemonic = "REVSH.W";
3838 break;
3839 case 4:
3840 mnemonic = "CLZ";
3841 break;
3842 default:
3843 return ERROR_INVALID_ARGUMENTS;
3844 }
3845 sprintf(cp, "%s\tr%d, r%d",
3846 mnemonic,
3847 (int) (opcode >> 8) & 0xf,
3848 (int) (opcode >> 0) & 0xf);
3849 break;
3850 default:
3851 return ERROR_INVALID_ARGUMENTS;
3852 }
3853 }
3854
3855 return ERROR_OK;
3856 }
3857
3858 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3859 struct arm_instruction *instruction, char *cp)
3860 {
3861 int rn = (opcode >> 16) & 0xf;
3862 int immed;
3863
3864 instruction->type = ARM_LDR;
3865
3866 if (rn == 0xf) {
3867 immed = opcode & 0x0fff;
3868 if ((opcode & (1 << 23)) == 0)
3869 immed = -immed;
3870 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3871 (int) (opcode >> 12) & 0xf,
3872 thumb_alignpc4(address) + immed);
3873 return ERROR_OK;
3874 }
3875
3876 if (opcode & (1 << 23)) {
3877 immed = opcode & 0x0fff;
3878 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3879 (int) (opcode >> 12) & 0xf,
3880 rn, immed, immed);
3881 return ERROR_OK;
3882 }
3883
3884 if (!(opcode & (0x3f << 6))) {
3885 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3886 (int) (opcode >> 12) & 0xf,
3887 rn,
3888 (int) (opcode >> 0) & 0xf,
3889 (int) (opcode >> 4) & 0x3);
3890 return ERROR_OK;
3891 }
3892
3893
3894 if (((opcode >> 8) & 0xf) == 0xe) {
3895 immed = opcode & 0x00ff;
3896
3897 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3898 (int) (opcode >> 12) & 0xf,
3899 rn, immed, immed);
3900 return ERROR_OK;
3901 }
3902
3903 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3904 char *p1 = "]", *p2 = "";
3905
3906 if (!(opcode & 0x0500))
3907 return ERROR_INVALID_ARGUMENTS;
3908
3909 immed = opcode & 0x00ff;
3910
3911 /* two indexed modes will write back rn */
3912 if (opcode & 0x100) {
3913 if (opcode & 0x400) /* pre-indexed */
3914 p2 = "]!";
3915 else { /* post-indexed */
3916 p1 = "]";
3917 p2 = "";
3918 }
3919 }
3920
3921 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3922 (int) (opcode >> 12) & 0xf,
3923 rn, p1,
3924 (opcode & 0x200) ? "" : "-",
3925 immed, p2, immed);
3926 return ERROR_OK;
3927 }
3928
3929 return ERROR_INVALID_ARGUMENTS;
3930 }
3931
3932 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3933 struct arm_instruction *instruction, char *cp)
3934 {
3935 int rn = (opcode >> 16) & 0xf;
3936 int rt = (opcode >> 12) & 0xf;
3937 int op2 = (opcode >> 6) & 0x3f;
3938 unsigned immed;
3939 char *p1 = "", *p2 = "]";
3940 char *mnemonic;
3941
3942 switch ((opcode >> 23) & 0x3) {
3943 case 0:
3944 if ((rn & rt) == 0xf) {
3945 pld_literal:
3946 immed = opcode & 0xfff;
3947 address = thumb_alignpc4(address);
3948 if (opcode & (1 << 23))
3949 address += immed;
3950 else
3951 address -= immed;
3952 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
3953 rt, address);
3954 return ERROR_OK;
3955 }
3956 if (rn == 0x0f && rt != 0x0f) {
3957 ldrb_literal:
3958 immed = opcode & 0xfff;
3959 address = thumb_alignpc4(address);
3960 if (opcode & (1 << 23))
3961 address += immed;
3962 else
3963 address -= immed;
3964 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3965 rt, address);
3966 return ERROR_OK;
3967 }
3968 if (rn == 0x0f)
3969 break;
3970 if ((op2 & 0x3c) == 0x38) {
3971 immed = opcode & 0xff;
3972 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3973 rt, rn, immed, immed);
3974 return ERROR_OK;
3975 }
3976 if ((op2 & 0x3c) == 0x30) {
3977 if (rt == 0x0f) {
3978 immed = opcode & 0xff;
3979 immed = -immed;
3980 preload_immediate:
3981 p1 = (opcode & (1 << 21)) ? "W" : "";
3982 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3983 p1, rn, immed, immed);
3984 return ERROR_OK;
3985 }
3986 mnemonic = "LDRB";
3987 ldrxb_immediate_t3:
3988 immed = opcode & 0xff;
3989 if (!(opcode & 0x200))
3990 immed = -immed;
3991
3992 /* two indexed modes will write back rn */
3993 if (opcode & 0x100) {
3994 if (opcode & 0x400) /* pre-indexed */
3995 p2 = "]!";
3996 else { /* post-indexed */
3997 p1 = "]";
3998 p2 = "";
3999 }
4000 }
4001 ldrxb_immediate_t2:
4002 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4003 mnemonic, rt, rn, p1,
4004 immed, p2, immed);
4005 return ERROR_OK;
4006 }
4007 if ((op2 & 0x24) == 0x24) {
4008 mnemonic = "LDRB";
4009 goto ldrxb_immediate_t3;
4010 }
4011 if (op2 == 0) {
4012 int rm = opcode & 0xf;
4013
4014 if (rt == 0x0f)
4015 sprintf(cp, "PLD\t");
4016 else
4017 sprintf(cp, "LDRB.W\tr%d, ", rt);
4018 immed = (opcode >> 4) & 0x3;
4019 cp = strchr(cp, 0);
4020 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4021 return ERROR_OK;
4022 }
4023 break;
4024 case 1:
4025 if ((rn & rt) == 0xf)
4026 goto pld_literal;
4027 if (rt == 0xf) {
4028 immed = opcode & 0xfff;
4029 goto preload_immediate;
4030 }
4031 if (rn == 0x0f)
4032 goto ldrb_literal;
4033 mnemonic = "LDRB.W";
4034 immed = opcode & 0xfff;
4035 goto ldrxb_immediate_t2;
4036 case 2:
4037 if ((rn & rt) == 0xf) {
4038 immed = opcode & 0xfff;
4039 address = thumb_alignpc4(address);
4040 if (opcode & (1 << 23))
4041 address += immed;
4042 else
4043 address -= immed;
4044 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4045 return ERROR_OK;
4046 }
4047 if (rn == 0xf && rt != 0xf) {
4048 ldrsb_literal:
4049 immed = opcode & 0xfff;
4050 address = thumb_alignpc4(address);
4051 if (opcode & (1 << 23))
4052 address += immed;
4053 else
4054 address -= immed;
4055 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4056 return ERROR_OK;
4057 }
4058 if (rn == 0xf)
4059 break;
4060 if ((op2 & 0x3c) == 0x38) {
4061 immed = opcode & 0xff;
4062 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4063 rt, rn, immed, immed);
4064 return ERROR_OK;
4065 }
4066 if ((op2 & 0x3c) == 0x30) {
4067 if (rt == 0xf) {
4068 immed = opcode & 0xff;
4069 immed = -immed; // pli
4070 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4071 rn, immed, -immed);
4072 return ERROR_OK;
4073 }
4074 mnemonic = "LDRSB";
4075 goto ldrxb_immediate_t3;
4076 }
4077 if ((op2 & 0x24) == 0x24) {
4078 mnemonic = "LDRSB";
4079 goto ldrxb_immediate_t3;
4080 }
4081 if (op2 == 0) {
4082 int rm = opcode & 0xf;
4083
4084 if (rt == 0x0f)
4085 sprintf(cp, "PLI\t");
4086 else
4087 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4088 immed = (opcode >> 4) & 0x3;
4089 cp = strchr(cp, 0);
4090 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4091 return ERROR_OK;
4092 }
4093 break;
4094 case 3:
4095 if (rt == 0xf) {
4096 immed = opcode & 0xfff;
4097 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4098 rn, immed, immed);
4099 return ERROR_OK;
4100 }
4101 if (rn == 0xf)
4102 goto ldrsb_literal;
4103 immed = opcode & 0xfff;
4104 mnemonic = "LDRSB";
4105 goto ldrxb_immediate_t2;
4106 }
4107
4108 return ERROR_INVALID_ARGUMENTS;
4109 }
4110
4111 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4112 struct arm_instruction *instruction, char *cp)
4113 {
4114 int rn = (opcode >> 16) & 0xf;
4115 int rt = (opcode >> 12) & 0xf;
4116 int op2 = (opcode >> 6) & 0x3f;
4117 char *sign = "";
4118 unsigned immed;
4119
4120 if (rt == 0xf) {
4121 sprintf(cp, "HINT (UNALLOCATED)");
4122 return ERROR_OK;
4123 }
4124
4125 if (opcode & (1 << 24))
4126 sign = "S";
4127
4128 if ((opcode & (1 << 23)) == 0) {
4129 if (rn == 0xf) {
4130 ldrh_literal:
4131 immed = opcode & 0xfff;
4132 address = thumb_alignpc4(address);
4133 if (opcode & (1 << 23))
4134 address += immed;
4135 else
4136 address -= immed;
4137 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4138 sign, rt, address);
4139 return ERROR_OK;
4140 }
4141 if (op2 == 0) {
4142 int rm = opcode & 0xf;
4143
4144 immed = (opcode >> 4) & 0x3;
4145 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4146 sign, rt, rn, rm, immed);
4147 return ERROR_OK;
4148 }
4149 if ((op2 & 0x3c) == 0x38) {
4150 immed = opcode & 0xff;
4151 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4152 sign, rt, rn, immed, immed);
4153 return ERROR_OK;
4154 }
4155 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4156 char *p1 = "", *p2 = "]";
4157
4158 immed = opcode & 0xff;
4159 if (!(opcode & 0x200))
4160 immed = -immed;
4161
4162 /* two indexed modes will write back rn */
4163 if (opcode & 0x100) {
4164 if (opcode & 0x400) /* pre-indexed */
4165 p2 = "]!";
4166 else { /* post-indexed */
4167 p1 = "]";
4168 p2 = "";
4169 }
4170 }
4171 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4172 sign, rt, rn, p1, immed, p2, immed);
4173 return ERROR_OK;
4174 }
4175 } else {
4176 if (rn == 0xf)
4177 goto ldrh_literal;
4178
4179 immed = opcode & 0xfff;
4180 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4181 sign, *sign ? "" : ".W",
4182 rt, rn, immed, immed);
4183 return ERROR_OK;
4184 }
4185
4186 return ERROR_INVALID_ARGUMENTS;
4187 }
4188
4189 /*
4190 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4191 * always set. That means eventual arm_simulate_step() support for Thumb2
4192 * will need work in this area.
4193 */
4194 int thumb2_opcode(target_t *target, uint32_t address, struct arm_instruction *instruction)
4195 {
4196 int retval;
4197 uint16_t op;
4198 uint32_t opcode;
4199 char *cp;
4200
4201 /* clear low bit ... it's set on function pointers */
4202 address &= ~1;
4203
4204 /* clear fields, to avoid confusion */
4205 memset(instruction, 0, sizeof(struct arm_instruction));
4206
4207 /* read first halfword, see if this is the only one */
4208 retval = target_read_u16(target, address, &op);
4209 if (retval != ERROR_OK)
4210 return retval;
4211
4212 switch (op & 0xf800) {
4213 case 0xf800:
4214 case 0xf000:
4215 case 0xe800:
4216 /* 32-bit instructions */
4217 instruction->instruction_size = 4;
4218 opcode = op << 16;
4219 retval = target_read_u16(target, address + 2, &op);
4220 if (retval != ERROR_OK)
4221 return retval;
4222 opcode |= op;
4223 instruction->opcode = opcode;
4224 break;
4225 default:
4226 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4227 return thumb_evaluate_opcode(op, address, instruction);
4228 }
4229
4230 snprintf(instruction->text, 128,
4231 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4232 address, opcode);
4233 cp = strchr(instruction->text, 0);
4234 retval = ERROR_FAIL;
4235
4236 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4237 if ((opcode & 0x1a008000) == 0x10000000)
4238 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4239
4240 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4241 else if ((opcode & 0x1a008000) == 0x12000000)
4242 retval = t2ev_data_immed(opcode, address, instruction, cp);
4243
4244 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4245 else if ((opcode & 0x18008000) == 0x10008000)
4246 retval = t2ev_b_misc(opcode, address, instruction, cp);
4247
4248 /* ARMv7-M: A5.3.5 Load/store multiple */
4249 else if ((opcode & 0x1e400000) == 0x08000000)
4250 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4251
4252 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4253 else if ((opcode & 0x1e400000) == 0x08400000)
4254 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4255
4256 /* ARMv7-M: A5.3.7 Load word */
4257 else if ((opcode & 0x1f700000) == 0x18500000)
4258 retval = t2ev_load_word(opcode, address, instruction, cp);
4259
4260 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4261 else if ((opcode & 0x1e700000) == 0x18300000)
4262 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4263
4264 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4265 else if ((opcode & 0x1e700000) == 0x18100000)
4266 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4267
4268 /* ARMv7-M: A5.3.10 Store single data item */
4269 else if ((opcode & 0x1f100000) == 0x18000000)
4270 retval = t2ev_store_single(opcode, address, instruction, cp);
4271
4272 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4273 else if ((opcode & 0x1e000000) == 0x0a000000)
4274 retval = t2ev_data_shift(opcode, address, instruction, cp);
4275
4276 /* ARMv7-M: A5.3.12 Data processing (register)
4277 * and A5.3.13 Miscellaneous operations
4278 */
4279 else if ((opcode & 0x1f000000) == 0x1a000000)
4280 retval = t2ev_data_reg(opcode, address, instruction, cp);
4281
4282 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4283 else if ((opcode & 0x1f800000) == 0x1b000000)
4284 retval = t2ev_mul32(opcode, address, instruction, cp);
4285
4286 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4287 else if ((opcode & 0x1f800000) == 0x1b800000)
4288 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4289
4290 if (retval == ERROR_OK)
4291 return retval;
4292
4293 /*
4294 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4295 * instructions; not yet handled here.
4296 */
4297
4298 if (retval == ERROR_INVALID_ARGUMENTS) {
4299 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4300 strcpy(cp, "UNDEFINED OPCODE");
4301 return ERROR_OK;
4302 }
4303
4304 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4305 opcode);
4306
4307 strcpy(cp, "(32-bit Thumb2 ...)");
4308 return ERROR_OK;
4309 }
4310
4311 int arm_access_size(struct arm_instruction *instruction)
4312 {
4313 if ((instruction->type == ARM_LDRB)
4314 || (instruction->type == ARM_LDRBT)
4315 || (instruction->type == ARM_LDRSB)
4316 || (instruction->type == ARM_STRB)
4317 || (instruction->type == ARM_STRBT))
4318 {
4319 return 1;
4320 }
4321 else if ((instruction->type == ARM_LDRH)
4322 || (instruction->type == ARM_LDRSH)
4323 || (instruction->type == ARM_STRH))
4324 {
4325 return 2;
4326 }
4327 else if ((instruction->type == ARM_LDR)
4328 || (instruction->type == ARM_LDRT)
4329 || (instruction->type == ARM_STR)
4330 || (instruction->type == ARM_STRT))
4331 {
4332 return 4;
4333 }
4334 else if ((instruction->type == ARM_LDRD)
4335 || (instruction->type == ARM_STRD))
4336 {
4337 return 8;
4338 }
4339 else
4340 {
4341 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
4342 return 0;
4343 }
4344 }

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)