1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include "arm_disassembler.h"
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings[] =
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value, int places)
39 return (value >> places) | (value << (32 - places));
42 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
45 if ((opcode & 0x0d70f0000) == 0x0550f000)
47 instruction->type = ARM_PLD;
49 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
55 instruction->type = ARM_UNDEFINED_INSTRUCTION;
59 LOG_ERROR("should never reach this point");
63 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
65 instruction->type = ARM_SWI;
67 snprintf(instruction->text, 128,
68 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
69 address, opcode, (opcode & 0xffffff));
74 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
78 uint32_t target_address;
80 instruction->type = ARM_BLX;
81 immediate = opcode & 0x00ffffff;
83 /* sign extend 24-bit immediate */
84 if (immediate & 0x00800000)
85 offset = 0xff000000 | immediate;
89 /* shift two bits left */
92 /* odd/event halfword */
93 if (opcode & 0x01000000)
96 target_address = address + 8 + offset;
98 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
100 instruction->info.b_bl_bx_blx.reg_operand = -1;
101 instruction->info.b_bl_bx_blx.target_address = target_address;
106 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
111 uint32_t target_address;
113 immediate = opcode & 0x00ffffff;
114 L = (opcode & 0x01000000) >> 24;
116 /* sign extend 24-bit immediate */
117 if (immediate & 0x00800000)
118 offset = 0xff000000 | immediate;
122 /* shift two bits left */
125 target_address = address + 8 + offset;
128 instruction->type = ARM_BL;
130 instruction->type = ARM_B;
132 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
133 (L) ? "L" : "", COND(opcode), target_address);
135 instruction->info.b_bl_bx_blx.reg_operand = -1;
136 instruction->info.b_bl_bx_blx.target_address = target_address;
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
145 uint8_t cp_num = (opcode & 0xf00) >> 8;
148 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
150 uint8_t cp_opcode, Rd, Rn, CRm;
153 cp_opcode = (opcode & 0xf0) >> 4;
154 Rd = (opcode & 0xf000) >> 12;
155 Rn = (opcode & 0xf0000) >> 16;
156 CRm = (opcode & 0xf);
159 if ((opcode & 0x0ff00000) == 0x0c400000)
161 instruction->type = ARM_MCRR;
166 if ((opcode & 0x0ff00000) == 0x0c500000)
168 instruction->type = ARM_MRRC;
172 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
173 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
175 else /* LDC or STC */
177 uint8_t CRd, Rn, offset;
180 char addressing_mode[32];
182 CRd = (opcode & 0xf000) >> 12;
183 Rn = (opcode & 0xf0000) >> 16;
184 offset = (opcode & 0xff);
187 if (opcode & 0x00100000)
189 instruction->type = ARM_LDC;
194 instruction->type = ARM_STC;
198 U = (opcode & 0x00800000) >> 23;
199 N = (opcode & 0x00400000) >> 22;
201 /* addressing modes */
202 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
204 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
206 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
208 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
212 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
214 cp_num, CRd, addressing_mode);
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
227 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
229 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
230 cp_num = (opcode & 0xf00) >> 8;
231 CRd_Rd = (opcode & 0xf000) >> 12;
232 CRn = (opcode & 0xf0000) >> 16;
233 CRm = (opcode & 0xf);
234 opcode_2 = (opcode & 0xe0) >> 5;
237 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
239 if (opcode & 0x00100000) /* bit 20 set -> MRC */
241 instruction->type = ARM_MRC;
244 else /* bit 20 not set -> MCR */
246 instruction->type = ARM_MCR;
250 opcode_1 = (opcode & 0x00e00000) >> 21;
252 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
253 address, opcode, mnemonic, cond,
254 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
256 else /* bit 4 not set -> CDP */
258 instruction->type = ARM_CDP;
261 opcode_1 = (opcode & 0x00f00000) >> 20;
263 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
264 address, opcode, mnemonic, cond,
265 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
274 uint8_t I, P, U, B, W, L;
276 char *operation; /* "LDR" or "STR" */
277 char *suffix; /* "", "B", "T", "BT" */
281 I = (opcode & 0x02000000) >> 25;
282 P = (opcode & 0x01000000) >> 24;
283 U = (opcode & 0x00800000) >> 23;
284 B = (opcode & 0x00400000) >> 22;
285 W = (opcode & 0x00200000) >> 21;
286 L = (opcode & 0x00100000) >> 20;
288 /* target register */
289 Rd = (opcode & 0xf000) >> 12;
292 Rn = (opcode & 0xf0000) >> 16;
294 instruction->info.load_store.Rd = Rd;
295 instruction->info.load_store.Rn = Rn;
296 instruction->info.load_store.U = U;
298 /* determine operation */
304 /* determine instruction type and suffix */
307 if ((P == 0) && (W == 1))
310 instruction->type = ARM_LDRBT;
312 instruction->type = ARM_STRBT;
318 instruction->type = ARM_LDRB;
320 instruction->type = ARM_STRB;
326 if ((P == 0) && (W == 1))
329 instruction->type = ARM_LDRT;
331 instruction->type = ARM_STRT;
337 instruction->type = ARM_LDR;
339 instruction->type = ARM_STR;
344 if (!I) /* #+-<offset_12> */
346 uint32_t offset_12 = (opcode & 0xfff);
348 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
350 snprintf(offset, 32, "%s", "");
352 instruction->info.load_store.offset_mode = 0;
353 instruction->info.load_store.offset.offset = offset_12;
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
357 uint8_t shift_imm, shift;
360 shift_imm = (opcode & 0xf80) >> 7;
361 shift = (opcode & 0x60) >> 5;
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift == 0x1) && (shift_imm == 0x0))
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift == 0x2) && (shift_imm == 0x0))
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift == 0x3) && (shift_imm == 0x0))
376 instruction->info.load_store.offset_mode = 1;
377 instruction->info.load_store.offset.reg.Rm = Rm;
378 instruction->info.load_store.offset.reg.shift = shift;
379 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
381 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
383 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
390 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
393 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
396 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
399 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
402 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
410 if (W == 0) /* offset */
412 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
413 address, opcode, operation, COND(opcode), suffix,
416 instruction->info.load_store.index_mode = 0;
418 else /* pre-indexed */
420 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
421 address, opcode, operation, COND(opcode), suffix,
424 instruction->info.load_store.index_mode = 1;
427 else /* post-indexed */
429 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
430 address, opcode, operation, COND(opcode), suffix,
433 instruction->info.load_store.index_mode = 2;
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
442 uint8_t P, U, I, W, L, S, H;
444 char *operation; /* "LDR" or "STR" */
445 char *suffix; /* "H", "SB", "SH", "D" */
449 P = (opcode & 0x01000000) >> 24;
450 U = (opcode & 0x00800000) >> 23;
451 I = (opcode & 0x00400000) >> 22;
452 W = (opcode & 0x00200000) >> 21;
453 L = (opcode & 0x00100000) >> 20;
454 S = (opcode & 0x00000040) >> 6;
455 H = (opcode & 0x00000020) >> 5;
457 /* target register */
458 Rd = (opcode & 0xf000) >> 12;
461 Rn = (opcode & 0xf0000) >> 16;
463 instruction->info.load_store.Rd = Rd;
464 instruction->info.load_store.Rn = Rn;
465 instruction->info.load_store.U = U;
467 /* determine instruction type and suffix */
475 instruction->type = ARM_LDRSH;
481 instruction->type = ARM_LDRSB;
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
491 instruction->type = ARM_STRD;
496 instruction->type = ARM_LDRD;
506 instruction->type = ARM_LDRH;
511 instruction->type = ARM_STRH;
515 if (I) /* Immediate offset/index (#+-<offset_8>)*/
517 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
518 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
520 instruction->info.load_store.offset_mode = 0;
521 instruction->info.load_store.offset.offset = offset_8;
523 else /* Register offset/index (+-<Rm>) */
527 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
529 instruction->info.load_store.offset_mode = 1;
530 instruction->info.load_store.offset.reg.Rm = Rm;
531 instruction->info.load_store.offset.reg.shift = 0x0;
532 instruction->info.load_store.offset.reg.shift_imm = 0x0;
537 if (W == 0) /* offset */
539 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
540 address, opcode, operation, COND(opcode), suffix,
543 instruction->info.load_store.index_mode = 0;
545 else /* pre-indexed */
547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
548 address, opcode, operation, COND(opcode), suffix,
551 instruction->info.load_store.index_mode = 1;
554 else /* post-indexed */
556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
557 address, opcode, operation, COND(opcode), suffix,
560 instruction->info.load_store.index_mode = 2;
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
569 uint8_t P, U, S, W, L, Rn;
570 uint32_t register_list;
571 char *addressing_mode;
578 P = (opcode & 0x01000000) >> 24;
579 U = (opcode & 0x00800000) >> 23;
580 S = (opcode & 0x00400000) >> 22;
581 W = (opcode & 0x00200000) >> 21;
582 L = (opcode & 0x00100000) >> 20;
583 register_list = (opcode & 0xffff);
584 Rn = (opcode & 0xf0000) >> 16;
586 instruction->info.load_store_multiple.Rn = Rn;
587 instruction->info.load_store_multiple.register_list = register_list;
588 instruction->info.load_store_multiple.S = S;
589 instruction->info.load_store_multiple.W = W;
593 instruction->type = ARM_LDM;
598 instruction->type = ARM_STM;
606 instruction->info.load_store_multiple.addressing_mode = 1;
607 addressing_mode = "IB";
611 instruction->info.load_store_multiple.addressing_mode = 3;
612 addressing_mode = "DB";
619 instruction->info.load_store_multiple.addressing_mode = 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode = "";
625 instruction->info.load_store_multiple.addressing_mode = 2;
626 addressing_mode = "DA";
630 reg_list_p = reg_list;
631 for (i = 0; i <= 15; i++)
633 if ((register_list >> i) & 1)
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
642 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
647 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
648 address, opcode, mnemonic, COND(opcode), addressing_mode,
649 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode & 0x000000f0) == 0x00000090)
660 /* Multiply (accumulate) */
661 if ((opcode & 0x0f800000) == 0x00000000)
663 uint8_t Rm, Rs, Rn, Rd, S;
665 Rs = (opcode & 0xf00) >> 8;
666 Rn = (opcode & 0xf000) >> 12;
667 Rd = (opcode & 0xf0000) >> 16;
668 S = (opcode & 0x00100000) >> 20;
670 /* examine A bit (accumulate) */
671 if (opcode & 0x00200000)
673 instruction->type = ARM_MLA;
674 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
675 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
679 instruction->type = ARM_MUL;
680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
681 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
687 /* Multiply (accumulate) long */
688 if ((opcode & 0x0f800000) == 0x00800000)
690 char* mnemonic = NULL;
691 uint8_t Rm, Rs, RdHi, RdLow, S;
693 Rs = (opcode & 0xf00) >> 8;
694 RdHi = (opcode & 0xf000) >> 12;
695 RdLow = (opcode & 0xf0000) >> 16;
696 S = (opcode & 0x00100000) >> 20;
698 switch ((opcode & 0x00600000) >> 21)
701 instruction->type = ARM_UMULL;
705 instruction->type = ARM_UMLAL;
709 instruction->type = ARM_SMULL;
713 instruction->type = ARM_SMLAL;
718 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
719 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
720 RdLow, RdHi, Rm, Rs);
726 if ((opcode & 0x0f800000) == 0x01000000)
730 Rd = (opcode & 0xf000) >> 12;
731 Rn = (opcode & 0xf0000) >> 16;
734 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
736 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
737 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
743 return evaluate_misc_load_store(opcode, address, instruction);
746 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
748 int R = (opcode & 0x00400000) >> 22;
749 char *PSR = (R) ? "SPSR" : "CPSR";
751 /* Move register to status register (MSR) */
752 if (opcode & 0x00200000)
754 instruction->type = ARM_MSR;
756 /* immediate variant */
757 if (opcode & 0x02000000)
759 uint8_t immediate = (opcode & 0xff);
760 uint8_t rotate = (opcode & 0xf00);
762 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
763 address, opcode, COND(opcode), PSR,
764 (opcode & 0x10000) ? "c" : "",
765 (opcode & 0x20000) ? "x" : "",
766 (opcode & 0x40000) ? "s" : "",
767 (opcode & 0x80000) ? "f" : "",
768 ror(immediate, (rotate * 2))
771 else /* register variant */
773 uint8_t Rm = opcode & 0xf;
774 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
775 address, opcode, COND(opcode), PSR,
776 (opcode & 0x10000) ? "c" : "",
777 (opcode & 0x20000) ? "x" : "",
778 (opcode & 0x40000) ? "s" : "",
779 (opcode & 0x80000) ? "f" : "",
785 else /* Move status register to register (MRS) */
789 instruction->type = ARM_MRS;
790 Rd = (opcode & 0x0000f000) >> 12;
792 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
793 address, opcode, COND(opcode), Rd, PSR);
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
803 if ((opcode & 0x000000f0) == 0x00000000)
805 evaluate_mrs_msr(opcode, address, instruction);
809 if ((opcode & 0x006000f0) == 0x00200010)
812 instruction->type = ARM_BX;
815 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
816 address, opcode, COND(opcode), Rm);
818 instruction->info.b_bl_bx_blx.reg_operand = Rm;
819 instruction->info.b_bl_bx_blx.target_address = -1;
823 if ((opcode & 0x006000f0) == 0x00600010)
826 instruction->type = ARM_CLZ;
828 Rd = (opcode & 0xf000) >> 12;
830 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
831 address, opcode, COND(opcode), Rd, Rm);
835 if ((opcode & 0x006000f0) == 0x00200030)
838 instruction->type = ARM_BLX;
841 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
842 address, opcode, COND(opcode), Rm);
844 instruction->info.b_bl_bx_blx.reg_operand = Rm;
845 instruction->info.b_bl_bx_blx.target_address = -1;
848 /* Enhanced DSP add/subtracts */
849 if ((opcode & 0x0000000f0) == 0x00000050)
852 char *mnemonic = NULL;
854 Rd = (opcode & 0xf000) >> 12;
855 Rn = (opcode & 0xf0000) >> 16;
857 switch ((opcode & 0x00600000) >> 21)
860 instruction->type = ARM_QADD;
864 instruction->type = ARM_QSUB;
868 instruction->type = ARM_QDADD;
872 instruction->type = ARM_QDSUB;
877 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
878 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
881 /* Software breakpoints */
882 if ((opcode & 0x0000000f0) == 0x00000070)
885 instruction->type = ARM_BKPT;
886 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
888 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
889 address, opcode, immediate);
892 /* Enhanced DSP multiplies */
893 if ((opcode & 0x000000090) == 0x00000080)
895 int x = (opcode & 0x20) >> 5;
896 int y = (opcode & 0x40) >> 6;
899 if ((opcode & 0x00600000) == 0x00000000)
901 uint8_t Rd, Rm, Rs, Rn;
902 instruction->type = ARM_SMLAxy;
903 Rd = (opcode & 0xf0000) >> 16;
905 Rs = (opcode & 0xf00) >> 8;
906 Rn = (opcode & 0xf000) >> 12;
908 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
914 if ((opcode & 0x00600000) == 0x00400000)
916 uint8_t RdLow, RdHi, Rm, Rs;
917 instruction->type = ARM_SMLAxy;
918 RdHi = (opcode & 0xf0000) >> 16;
919 RdLow = (opcode & 0xf000) >> 12;
921 Rs = (opcode & 0xf00) >> 8;
923 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
925 RdLow, RdHi, Rm, Rs);
929 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
931 uint8_t Rd, Rm, Rs, Rn;
932 instruction->type = ARM_SMLAWy;
933 Rd = (opcode & 0xf0000) >> 16;
935 Rs = (opcode & 0xf00) >> 8;
936 Rn = (opcode & 0xf000) >> 12;
938 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address, opcode, (y) ? "T" : "B", COND(opcode),
944 if ((opcode & 0x00600000) == 0x00300000)
947 instruction->type = ARM_SMULxy;
948 Rd = (opcode & 0xf0000) >> 16;
950 Rs = (opcode & 0xf00) >> 8;
952 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
953 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
958 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
961 instruction->type = ARM_SMULWy;
962 Rd = (opcode & 0xf0000) >> 16;
964 Rs = (opcode & 0xf00) >> 8;
966 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
967 address, opcode, (y) ? "T" : "B", COND(opcode),
975 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
977 uint8_t I, op, S, Rn, Rd;
978 char *mnemonic = NULL;
979 char shifter_operand[32];
981 I = (opcode & 0x02000000) >> 25;
982 op = (opcode & 0x01e00000) >> 21;
983 S = (opcode & 0x00100000) >> 20;
985 Rd = (opcode & 0xf000) >> 12;
986 Rn = (opcode & 0xf0000) >> 16;
988 instruction->info.data_proc.Rd = Rd;
989 instruction->info.data_proc.Rn = Rn;
990 instruction->info.data_proc.S = S;
995 instruction->type = ARM_AND;
999 instruction->type = ARM_EOR;
1003 instruction->type = ARM_SUB;
1007 instruction->type = ARM_RSB;
1011 instruction->type = ARM_ADD;
1015 instruction->type = ARM_ADC;
1019 instruction->type = ARM_SBC;
1023 instruction->type = ARM_RSC;
1027 instruction->type = ARM_TST;
1031 instruction->type = ARM_TEQ;
1035 instruction->type = ARM_CMP;
1039 instruction->type = ARM_CMN;
1043 instruction->type = ARM_ORR;
1047 instruction->type = ARM_MOV;
1051 instruction->type = ARM_BIC;
1055 instruction->type = ARM_MVN;
1060 if (I) /* immediate shifter operand (#<immediate>)*/
1062 uint8_t immed_8 = opcode & 0xff;
1063 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1066 immediate = ror(immed_8, rotate_imm * 2);
1068 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1070 instruction->info.data_proc.variant = 0;
1071 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1073 else /* register-based shifter operand */
1076 shift = (opcode & 0x60) >> 5;
1077 Rm = (opcode & 0xf);
1079 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1082 shift_imm = (opcode & 0xf80) >> 7;
1084 instruction->info.data_proc.variant = 1;
1085 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1086 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x1) && (shift_imm == 0x0))
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift == 0x2) && (shift_imm == 0x0))
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift == 0x3) && (shift_imm == 0x0))
1101 if ((shift_imm == 0x0) && (shift == 0x0))
1103 snprintf(shifter_operand, 32, "r%i", Rm);
1107 if (shift == 0x0) /* LSL */
1109 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1111 else if (shift == 0x1) /* LSR */
1113 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1115 else if (shift == 0x2) /* ASR */
1117 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1119 else if (shift == 0x3) /* ROR */
1121 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1123 else if (shift == 0x4) /* RRX */
1125 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1131 uint8_t Rs = (opcode & 0xf00) >> 8;
1133 instruction->info.data_proc.variant = 2;
1134 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1135 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1136 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1138 if (shift == 0x0) /* LSL */
1140 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1142 else if (shift == 0x1) /* LSR */
1144 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1146 else if (shift == 0x2) /* ASR */
1148 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1150 else if (shift == 0x3) /* ROR */
1152 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1157 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1160 address, opcode, mnemonic, COND(opcode),
1161 (S) ? "S" : "", Rd, Rn, shifter_operand);
1163 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1165 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1169 address, opcode, mnemonic, COND(opcode),
1170 (S) ? "S" : "", Rd, shifter_operand);
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1174 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1175 address, opcode, mnemonic, COND(opcode),
1176 Rn, shifter_operand);
1182 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1184 /* clear fields, to avoid confusion */
1185 memset(instruction, 0, sizeof(arm_instruction_t));
1186 instruction->opcode = opcode;
1187 instruction->instruction_size = 4;
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode & 0xf0000000) == 0xf0000000)
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode & 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode, address, instruction);
1196 /* Undefined instruction */
1197 if ((opcode & 0x0e000000) == 0x08000000)
1199 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1200 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode & 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode, address, instruction);
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode & 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1213 /* Coprocessor data processing */
1214 if ((opcode & 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1217 /* Coprocessor register transfers */
1218 if ((opcode & 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1221 /* Undefined instruction */
1222 if ((opcode & 0x0f000000) == 0x0f000000)
1224 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1225 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode & 0x0e000000) == 0x00000000)
1233 /* Multiplies, extra load/stores */
1234 if ((opcode & 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1237 /* Miscellaneous instructions */
1238 if ((opcode & 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode, address, instruction);
1241 return evaluate_data_proc(opcode, address, instruction);
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode & 0x0e000000) == 0x02000000)
1247 /* Undefined instruction */
1248 if ((opcode & 0x0fb00000) == 0x03000000)
1250 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1251 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1255 /* Move immediate to status register */
1256 if ((opcode & 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode, address, instruction);
1259 return evaluate_data_proc(opcode, address, instruction);
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode & 0x0e000000) == 0x04000000)
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode, address, instruction);
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode & 0x0e000000) == 0x06000000)
1273 /* Undefined instruction */
1274 if ((opcode & 0x00000010) == 0x00000010)
1276 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1277 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode, address, instruction);
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode & 0x0e000000) == 0x08000000)
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode, address, instruction);
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode & 0x0e000000) == 0x0a000000)
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode, address, instruction);
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode & 0x0e000000) == 0x0a000000)
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode & 0x0e000000) == 0x0e000000)
1310 /* Software interrupt */
1311 if ((opcode & 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode, address, instruction);
1314 /* Coprocessor data processing */
1315 if ((opcode & 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1318 /* Coprocessor register transfers */
1319 if ((opcode & 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1323 LOG_ERROR("should never reach this point");
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1329 uint32_t offset = opcode & 0x7ff;
1330 uint32_t opc = (opcode >> 11) & 0x3;
1331 uint32_t target_address;
1332 char *mnemonic = NULL;
1334 /* sign extend 11-bit offset */
1335 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1336 offset = 0xfffff800 | offset;
1338 target_address = address + 4 + (offset << 1);
1342 /* unconditional branch */
1344 instruction->type = ARM_B;
1349 instruction->type = ARM_BLX;
1354 instruction->type = ARM_UNKNOWN_INSTUCTION;
1355 mnemonic = "prefix";
1356 target_address = offset << 12;
1360 instruction->type = ARM_BL;
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1370 snprintf(instruction->text, 128,
1371 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1372 address, opcode, mnemonic, target_address);
1374 instruction->info.b_bl_bx_blx.reg_operand = -1;
1375 instruction->info.b_bl_bx_blx.target_address = target_address;
1380 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1382 uint8_t Rd = (opcode >> 0) & 0x7;
1383 uint8_t Rn = (opcode >> 3) & 0x7;
1384 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1385 uint32_t opc = opcode & (1 << 9);
1386 uint32_t reg_imm = opcode & (1 << 10);
1391 instruction->type = ARM_SUB;
1396 instruction->type = ARM_ADD;
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = 1;
1406 instruction->info.data_proc.variant = 0; /*immediate*/
1407 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1408 snprintf(instruction->text, 128,
1409 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1414 instruction->info.data_proc.variant = 1; /*immediate shift*/
1415 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1416 snprintf(instruction->text, 128,
1417 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1424 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1426 uint8_t Rd = (opcode >> 0) & 0x7;
1427 uint8_t Rm = (opcode >> 3) & 0x7;
1428 uint8_t imm = (opcode >> 6) & 0x1f;
1429 uint8_t opc = (opcode >> 11) & 0x3;
1430 char *mnemonic = NULL;
1435 instruction->type = ARM_MOV;
1437 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1440 instruction->type = ARM_MOV;
1442 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1445 instruction->type = ARM_MOV;
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1451 if ((imm == 0) && (opc != 0))
1454 instruction->info.data_proc.Rd = Rd;
1455 instruction->info.data_proc.Rn = -1;
1456 instruction->info.data_proc.S = 1;
1458 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1459 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1460 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1462 snprintf(instruction->text, 128,
1463 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address, opcode, mnemonic, Rd, Rm, imm);
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1471 uint8_t imm = opcode & 0xff;
1472 uint8_t Rd = (opcode >> 8) & 0x7;
1473 uint32_t opc = (opcode >> 11) & 0x3;
1474 char *mnemonic = NULL;
1476 instruction->info.data_proc.Rd = Rd;
1477 instruction->info.data_proc.Rn = Rd;
1478 instruction->info.data_proc.S = 1;
1479 instruction->info.data_proc.variant = 0; /*immediate*/
1480 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1485 instruction->type = ARM_MOV;
1487 instruction->info.data_proc.Rn = -1;
1490 instruction->type = ARM_CMP;
1492 instruction->info.data_proc.Rd = -1;
1495 instruction->type = ARM_ADD;
1499 instruction->type = ARM_SUB;
1504 snprintf(instruction->text, 128,
1505 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address, opcode, mnemonic, Rd, imm);
1511 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1513 uint8_t high_reg, op, Rm, Rd,H1,H2;
1514 char *mnemonic = NULL;
1516 high_reg = (opcode & 0x0400) >> 10;
1517 op = (opcode & 0x03C0) >> 6;
1519 Rd = (opcode & 0x0007);
1520 Rm = (opcode & 0x0038) >> 3;
1521 H1 = (opcode & 0x0080) >> 7;
1522 H2 = (opcode & 0x0040) >> 6;
1524 instruction->info.data_proc.Rd = Rd;
1525 instruction->info.data_proc.Rn = Rd;
1526 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1527 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1528 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1539 instruction->type = ARM_ADD;
1543 instruction->type = ARM_CMP;
1547 instruction->type = ARM_MOV;
1551 if ((opcode & 0x7) == 0x0)
1553 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1556 instruction->type = ARM_BLX;
1557 snprintf(instruction->text, 128,
1559 " 0x%4.4x \tBLX\tr%i",
1560 address, opcode, Rm);
1564 instruction->type = ARM_BX;
1565 snprintf(instruction->text, 128,
1567 " 0x%4.4x \tBX\tr%i",
1568 address, opcode, Rm);
1573 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1574 snprintf(instruction->text, 128,
1577 "UNDEFINED INSTRUCTION",
1589 instruction->type = ARM_AND;
1593 instruction->type = ARM_EOR;
1597 instruction->type = ARM_MOV;
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1601 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1602 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1605 instruction->type = ARM_MOV;
1607 instruction->info.data_proc.variant = 2 /*register shift*/;
1608 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1609 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1610 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1613 instruction->type = ARM_MOV;
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1617 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1618 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1621 instruction->type = ARM_ADC;
1625 instruction->type = ARM_SBC;
1629 instruction->type = ARM_MOV;
1631 instruction->info.data_proc.variant = 2 /*register shift*/;
1632 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1633 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1634 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1637 instruction->type = ARM_TST;
1641 instruction->type = ARM_RSB;
1643 instruction->info.data_proc.variant = 0 /*immediate*/;
1644 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1645 instruction->info.data_proc.Rn = Rm;
1648 instruction->type = ARM_CMP;
1652 instruction->type = ARM_CMN;
1656 instruction->type = ARM_ORR;
1660 instruction->type = ARM_MUL;
1664 instruction->type = ARM_BIC;
1668 instruction->type = ARM_MVN;
1674 snprintf(instruction->text, 128,
1675 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1676 address, opcode, mnemonic, Rd, Rm);
1681 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1684 uint8_t Rd = (opcode >> 8) & 0x7;
1686 instruction->type = ARM_LDR;
1687 immediate = opcode & 0x000000ff;
1689 snprintf(instruction->text, 128,
1690 "0x%8.8" PRIx32 " 0x%4.4x \tLDR\tr%i, [pc, #%#" PRIx32 "]",
1691 address, opcode, Rd, immediate*4);
1693 instruction->info.load_store.Rd = Rd;
1694 instruction->info.load_store.Rn = 15 /*PC*/;
1695 instruction->info.load_store.index_mode = 0; /*offset*/
1696 instruction->info.load_store.offset_mode = 0; /*immediate*/
1697 instruction->info.load_store.offset.offset = immediate*4;
1702 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1704 uint8_t Rd = (opcode >> 0) & 0x7;
1705 uint8_t Rn = (opcode >> 3) & 0x7;
1706 uint8_t Rm = (opcode >> 6) & 0x7;
1707 uint8_t opc = (opcode >> 9) & 0x7;
1708 char *mnemonic = NULL;
1713 instruction->type = ARM_STR;
1717 instruction->type = ARM_STRH;
1721 instruction->type = ARM_STRB;
1725 instruction->type = ARM_LDRSB;
1729 instruction->type = ARM_LDR;
1733 instruction->type = ARM_LDRH;
1737 instruction->type = ARM_LDRB;
1741 instruction->type = ARM_LDRSH;
1746 snprintf(instruction->text, 128,
1747 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1748 address, opcode, mnemonic, Rd, Rn, Rm);
1750 instruction->info.load_store.Rd = Rd;
1751 instruction->info.load_store.Rn = Rn;
1752 instruction->info.load_store.index_mode = 0; /*offset*/
1753 instruction->info.load_store.offset_mode = 1; /*register*/
1754 instruction->info.load_store.offset.reg.Rm = Rm;
1759 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1761 uint32_t offset = (opcode >> 6) & 0x1f;
1762 uint8_t Rd = (opcode >> 0) & 0x7;
1763 uint8_t Rn = (opcode >> 3) & 0x7;
1764 uint32_t L = opcode & (1 << 11);
1765 uint32_t B = opcode & (1 << 12);
1772 instruction->type = ARM_LDR;
1777 instruction->type = ARM_STR;
1781 if ((opcode&0xF000) == 0x8000)
1792 snprintf(instruction->text, 128,
1793 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1794 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1796 instruction->info.load_store.Rd = Rd;
1797 instruction->info.load_store.Rn = Rn;
1798 instruction->info.load_store.index_mode = 0; /*offset*/
1799 instruction->info.load_store.offset_mode = 0; /*immediate*/
1800 instruction->info.load_store.offset.offset = offset << shift;
1805 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1807 uint32_t offset = opcode & 0xff;
1808 uint8_t Rd = (opcode >> 8) & 0x7;
1809 uint32_t L = opcode & (1 << 11);
1814 instruction->type = ARM_LDR;
1819 instruction->type = ARM_STR;
1823 snprintf(instruction->text, 128,
1824 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1825 address, opcode, mnemonic, Rd, offset*4);
1827 instruction->info.load_store.Rd = Rd;
1828 instruction->info.load_store.Rn = 13 /*SP*/;
1829 instruction->info.load_store.index_mode = 0; /*offset*/
1830 instruction->info.load_store.offset_mode = 0; /*immediate*/
1831 instruction->info.load_store.offset.offset = offset*4;
1836 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1838 uint32_t imm = opcode & 0xff;
1839 uint8_t Rd = (opcode >> 8) & 0x7;
1841 uint32_t SP = opcode & (1 << 11);
1844 instruction->type = ARM_ADD;
1857 snprintf(instruction->text, 128,
1858 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1859 address, opcode, Rd, reg_name, imm * 4);
1861 instruction->info.data_proc.variant = 0 /* immediate */;
1862 instruction->info.data_proc.Rd = Rd;
1863 instruction->info.data_proc.Rn = Rn;
1864 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1869 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1871 uint32_t imm = opcode & 0x7f;
1872 uint8_t opc = opcode & (1 << 7);
1878 instruction->type = ARM_SUB;
1883 instruction->type = ARM_ADD;
1887 snprintf(instruction->text, 128,
1888 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1889 address, opcode, mnemonic, imm*4);
1891 instruction->info.data_proc.variant = 0 /* immediate */;
1892 instruction->info.data_proc.Rd = 13 /*SP*/;
1893 instruction->info.data_proc.Rn = 13 /*SP*/;
1894 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1899 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1901 uint32_t imm = opcode & 0xff;
1903 instruction->type = ARM_BKPT;
1905 snprintf(instruction->text, 128,
1906 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1907 address, opcode, imm);
1912 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1914 uint32_t reg_list = opcode & 0xff;
1915 uint32_t L = opcode & (1 << 11);
1916 uint32_t R = opcode & (1 << 8);
1917 uint8_t Rn = (opcode >> 8) & 7;
1918 uint8_t addr_mode = 0 /* IA */;
1922 char ptr_name[7] = "";
1925 if ((opcode & 0xf000) == 0xc000)
1926 { /* generic load/store multiple */
1929 instruction->type = ARM_LDM;
1934 instruction->type = ARM_STM;
1937 snprintf(ptr_name,7,"r%i!, ",Rn);
1944 instruction->type = ARM_LDM;
1947 reg_list |= (1 << 15) /*PC*/;
1951 instruction->type = ARM_STM;
1953 addr_mode = 3; /*DB*/
1955 reg_list |= (1 << 14) /*LR*/;
1959 reg_names_p = reg_names;
1960 for (i = 0; i <= 15; i++)
1962 if (reg_list & (1 << i))
1963 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1965 if (reg_names_p > reg_names)
1966 reg_names_p[-2] = '\0';
1967 else /* invalid op : no registers */
1968 reg_names[0] = '\0';
1970 snprintf(instruction->text, 128,
1971 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1972 address, opcode, mnemonic, ptr_name, reg_names);
1974 instruction->info.load_store_multiple.register_list = reg_list;
1975 instruction->info.load_store_multiple.Rn = Rn;
1976 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1981 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1983 uint32_t offset = opcode & 0xff;
1984 uint8_t cond = (opcode >> 8) & 0xf;
1985 uint32_t target_address;
1989 instruction->type = ARM_SWI;
1990 snprintf(instruction->text, 128,
1991 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
1992 address, opcode, offset);
1995 else if (cond == 0xe)
1997 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1998 snprintf(instruction->text, 128,
1999 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2004 /* sign extend 8-bit offset */
2005 if (offset & 0x00000080)
2006 offset = 0xffffff00 | offset;
2008 target_address = address + 4 + (offset << 1);
2010 snprintf(instruction->text, 128,
2011 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2013 arm_condition_strings[cond], target_address);
2015 instruction->type = ARM_B;
2016 instruction->info.b_bl_bx_blx.reg_operand = -1;
2017 instruction->info.b_bl_bx_blx.target_address = target_address;
2022 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2023 arm_instruction_t *instruction)
2027 /* added in Thumb2 */
2028 offset = (opcode >> 3) & 0x1f;
2029 offset |= (opcode & 0x0200) >> 4;
2031 snprintf(instruction->text, 128,
2032 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2034 (opcode & 0x0800) ? "N" : "",
2035 opcode & 0x7, address + 4 + (offset << 1));
2040 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2041 arm_instruction_t *instruction)
2043 /* added in ARMv6 */
2044 snprintf(instruction->text, 128,
2045 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2047 (opcode & 0x0080) ? 'U' : 'S',
2048 (opcode & 0x0040) ? 'B' : 'H',
2049 opcode & 0x7, (opcode >> 3) & 0x7);
2054 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2055 arm_instruction_t *instruction)
2057 /* added in ARMv6 */
2058 if ((opcode & 0x0ff0) == 0x0650)
2059 snprintf(instruction->text, 128,
2060 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2062 (opcode & 0x80) ? "BE" : "LE");
2063 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2064 snprintf(instruction->text, 128,
2065 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2067 (opcode & 0x0010) ? 'D' : 'E',
2068 (opcode & 0x0004) ? "A" : "",
2069 (opcode & 0x0002) ? "I" : "",
2070 (opcode & 0x0001) ? "F" : "");
2075 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2076 arm_instruction_t *instruction)
2080 /* added in ARMv6 */
2081 switch (opcode & 0x00c0) {
2092 snprintf(instruction->text, 128,
2093 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2094 address, opcode, suffix,
2095 opcode & 0x7, (opcode >> 3) & 0x7);
2100 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2101 arm_instruction_t *instruction)
2105 switch ((opcode >> 4) & 0x0f) {
2122 hint = "HINT (UNRECOGNIZED)";
2126 snprintf(instruction->text, 128,
2127 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2128 address, opcode, hint);
2133 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2134 arm_instruction_t *instruction)
2136 unsigned cond = (opcode >> 4) & 0x0f;
2137 char *x = "", *y = "", *z = "";
2140 z = (opcode & 0x02) ? "T" : "E";
2142 y = (opcode & 0x04) ? "T" : "E";
2144 x = (opcode & 0x08) ? "T" : "E";
2146 snprintf(instruction->text, 128,
2147 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2149 x, y, z, arm_condition_strings[cond]);
2151 /* NOTE: strictly speaking, the next 1-4 instructions should
2152 * now be displayed with the relevant conditional suffix...
2158 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2160 /* clear fields, to avoid confusion */
2161 memset(instruction, 0, sizeof(arm_instruction_t));
2162 instruction->opcode = opcode;
2163 instruction->instruction_size = 2;
2165 if ((opcode & 0xe000) == 0x0000)
2167 /* add/substract register or immediate */
2168 if ((opcode & 0x1800) == 0x1800)
2169 return evaluate_add_sub_thumb(opcode, address, instruction);
2170 /* shift by immediate */
2172 return evaluate_shift_imm_thumb(opcode, address, instruction);
2175 /* Add/substract/compare/move immediate */
2176 if ((opcode & 0xe000) == 0x2000)
2178 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2181 /* Data processing instructions */
2182 if ((opcode & 0xf800) == 0x4000)
2184 return evaluate_data_proc_thumb(opcode, address, instruction);
2187 /* Load from literal pool */
2188 if ((opcode & 0xf800) == 0x4800)
2190 return evaluate_load_literal_thumb(opcode, address, instruction);
2193 /* Load/Store register offset */
2194 if ((opcode & 0xf000) == 0x5000)
2196 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2199 /* Load/Store immediate offset */
2200 if (((opcode & 0xe000) == 0x6000)
2201 ||((opcode & 0xf000) == 0x8000))
2203 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2206 /* Load/Store from/to stack */
2207 if ((opcode & 0xf000) == 0x9000)
2209 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2213 if ((opcode & 0xf000) == 0xa000)
2215 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2219 if ((opcode & 0xf000) == 0xb000)
2221 switch ((opcode >> 8) & 0x0f) {
2223 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2228 return evaluate_cb_thumb(opcode, address, instruction);
2230 return evaluate_extend_thumb(opcode, address, instruction);
2235 return evaluate_load_store_multiple_thumb(opcode, address,
2238 return evaluate_cps_thumb(opcode, address, instruction);
2240 if ((opcode & 0x00c0) == 0x0080)
2242 return evaluate_byterev_thumb(opcode, address, instruction);
2244 return evaluate_breakpoint_thumb(opcode, address, instruction);
2246 if (opcode & 0x000f)
2247 return evaluate_ifthen_thumb(opcode, address,
2250 return evaluate_hint_thumb(opcode, address,
2254 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2255 snprintf(instruction->text, 128,
2256 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2261 /* Load/Store multiple */
2262 if ((opcode & 0xf000) == 0xc000)
2264 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2267 /* Conditional branch + SWI */
2268 if ((opcode & 0xf000) == 0xd000)
2270 return evaluate_cond_branch_thumb(opcode, address, instruction);
2273 if ((opcode & 0xe000) == 0xe000)
2275 /* Undefined instructions */
2276 if ((opcode & 0xf801) == 0xe801)
2278 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2279 snprintf(instruction->text, 128,
2280 "0x%8.8" PRIx32 " 0x%8.8x\t"
2281 "UNDEFINED INSTRUCTION",
2286 { /* Branch to offset */
2287 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2291 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2295 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2296 arm_instruction_t *instruction, char *cp)
2299 unsigned b21 = 1 << 21;
2300 unsigned b22 = 1 << 22;
2302 /* instead of combining two smaller 16-bit branch instructions,
2303 * Thumb2 uses only one larger 32-bit instruction.
2305 offset = opcode & 0x7ff;
2306 offset |= (opcode & 0x03ff0000) >> 5;
2307 if (opcode & (1 << 26)) {
2308 offset |= 0xff << 23;
2309 if ((opcode & (1 << 11)) == 0)
2311 if ((opcode & (1 << 13)) == 0)
2314 if (opcode & (1 << 11))
2316 if (opcode & (1 << 13))
2324 address += offset << 1;
2326 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2327 instruction->info.b_bl_bx_blx.reg_operand = -1;
2328 instruction->info.b_bl_bx_blx.target_address = address;
2329 sprintf(cp, "%s\t%#8.8" PRIx32,
2330 (opcode & (1 << 14)) ? "BL" : "B.W",
2336 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2337 arm_instruction_t *instruction, char *cp)
2340 unsigned b17 = 1 << 17;
2341 unsigned b18 = 1 << 18;
2342 unsigned cond = (opcode >> 22) & 0x0f;
2344 offset = opcode & 0x7ff;
2345 offset |= (opcode & 0x003f0000) >> 5;
2346 if (opcode & (1 << 26)) {
2347 offset |= 0xffff << 19;
2348 if ((opcode & (1 << 11)) == 0)
2350 if ((opcode & (1 << 13)) == 0)
2353 if (opcode & (1 << 11))
2355 if (opcode & (1 << 13))
2362 address += offset << 1;
2364 instruction->type = ARM_B;
2365 instruction->info.b_bl_bx_blx.reg_operand = -1;
2366 instruction->info.b_bl_bx_blx.target_address = address;
2367 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2368 arm_condition_strings[cond],
2374 static const char *special_name(int number)
2376 char *special = "(RESERVED)";
2407 special = "primask";
2410 special = "basepri";
2413 special = "basepri_max";
2416 special = "faultmask";
2419 special = "control";
2425 static int t2ev_hint(uint32_t opcode, uint32_t address,
2426 arm_instruction_t *instruction, char *cp)
2428 const char *mnemonic;
2430 if (opcode & 0x0700) {
2431 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2432 strcpy(cp, "UNDEFINED");
2436 if (opcode & 0x00f0) {
2437 sprintf(cp, "DBG\t#%d", opcode & 0xf);
2441 switch (opcode & 0x0f) {
2446 mnemonic = "YIELD.W";
2458 mnemonic = "HINT.W (UNRECOGNIZED)";
2461 strcpy(cp, mnemonic);
2465 static int t2ev_misc(uint32_t opcode, uint32_t address,
2466 arm_instruction_t *instruction, char *cp)
2468 const char *mnemonic;
2470 switch ((opcode >> 4) & 0x0f) {
2484 return ERROR_INVALID_ARGUMENTS;
2486 strcpy(cp, mnemonic);
2490 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2491 arm_instruction_t *instruction, char *cp)
2493 /* permanently undefined */
2494 if ((opcode & 0x07f07000) == 0x07f02000) {
2495 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2496 strcpy(cp, "UNDEFINED");
2500 switch ((opcode >> 12) & 0x5) {
2503 return t2ev_b_bl(opcode, address, instruction, cp);
2507 if (((opcode >> 23) & 0x07) == 0x07)
2508 return t2ev_cond_b(opcode, address, instruction, cp);
2509 if (opcode & (1 << 26))
2514 switch ((opcode >> 20) & 0x7f) {
2517 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2518 (opcode >> 16) & 0x0f);
2521 return t2ev_hint(opcode, address, instruction, cp);
2523 return t2ev_misc(opcode, address, instruction, cp);
2526 sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
2527 special_name(opcode & 0xff));
2532 return ERROR_INVALID_ARGUMENTS;
2535 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2536 arm_instruction_t *instruction, char *cp)
2538 char *mnemonic = NULL;
2539 int rn = (opcode >> 16) & 0xf;
2540 int rd = (opcode >> 8) & 0xf;
2541 unsigned immed = opcode & 0xff;
2546 /* ARMv7-M: A5.3.2 Modified immediate constants */
2547 func = (opcode >> 11) & 0x0e;
2550 if (opcode & (1 << 26))
2553 /* "Modified" immediates */
2554 switch (func >> 1) {
2561 immed += immed << 16;
2564 immed += immed << 8;
2565 immed += immed << 16;
2569 immed = ror(immed, func);
2572 if (opcode & (1 << 20))
2575 switch ((opcode >> 21) & 0xf) {
2578 instruction->type = ARM_TST;
2584 instruction->type = ARM_AND;
2589 instruction->type = ARM_BIC;
2594 instruction->type = ARM_MOV;
2598 instruction->type = ARM_ORR;
2604 instruction->type = ARM_MVN;
2608 // instruction->type = ARM_ORN;
2614 instruction->type = ARM_TEQ;
2620 instruction->type = ARM_EOR;
2626 instruction->type = ARM_CMN;
2632 instruction->type = ARM_ADD;
2637 instruction->type = ARM_ADC;
2641 instruction->type = ARM_SBC;
2646 instruction->type = ARM_CMP;
2652 instruction->type = ARM_SUB;
2657 instruction->type = ARM_RSB;
2661 return ERROR_INVALID_ARGUMENTS;
2665 sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
2666 mnemonic, rd, immed, immed);
2668 sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
2669 mnemonic, suffix, rd, rn, immed, immed);
2675 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2676 * always set. That means eventual arm_simulate_step() support for Thumb2
2677 * will need work in this area.
2679 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2686 /* clear low bit ... it's set on function pointers */
2689 /* clear fields, to avoid confusion */
2690 memset(instruction, 0, sizeof(arm_instruction_t));
2692 /* read first halfword, see if this is the only one */
2693 retval = target_read_u16(target, address, &op);
2694 if (retval != ERROR_OK)
2697 switch (op & 0xf800) {
2701 /* 32-bit instructions */
2702 instruction->instruction_size = 4;
2704 retval = target_read_u16(target, address + 2, &op);
2705 if (retval != ERROR_OK)
2708 instruction->opcode = opcode;
2711 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2712 return thumb_evaluate_opcode(op, address, instruction);
2715 snprintf(instruction->text, 128,
2716 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
2718 cp = strchr(instruction->text, 0);
2719 retval = ERROR_FAIL;
2721 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
2722 if ((opcode & 0x1a008000) == 0x10000000)
2723 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
2725 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
2726 else if ((opcode & 0x18008000) == 0x10008000)
2727 retval = t2ev_b_misc(opcode, address, instruction, cp);
2729 /* FIXME decode more 32-bit instructions */
2731 if (retval == ERROR_OK)
2734 if (retval == ERROR_INVALID_ARGUMENTS) {
2735 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2736 strcpy(cp, "UNDEFINED OPCODE");
2740 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2742 strcpy(cp, "(32-bit Thumb2 ...)");
2746 int arm_access_size(arm_instruction_t *instruction)
2748 if ((instruction->type == ARM_LDRB)
2749 || (instruction->type == ARM_LDRBT)
2750 || (instruction->type == ARM_LDRSB)
2751 || (instruction->type == ARM_STRB)
2752 || (instruction->type == ARM_STRBT))
2756 else if ((instruction->type == ARM_LDRH)
2757 || (instruction->type == ARM_LDRSH)
2758 || (instruction->type == ARM_STRH))
2762 else if ((instruction->type == ARM_LDR)
2763 || (instruction->type == ARM_LDRT)
2764 || (instruction->type == ARM_STR)
2765 || (instruction->type == ARM_STRT))
2769 else if ((instruction->type == ARM_LDRD)
2770 || (instruction->type == ARM_STRD))
2776 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);