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

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)