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

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)