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;
1517 high_reg = (opcode & 0x0400) >> 10;
1518 op = (opcode & 0x03C0) >> 6;
1520 Rd = (opcode & 0x0007);
1521 Rm = (opcode & 0x0038) >> 3;
1522 H1 = (opcode & 0x0080) >> 7;
1523 H2 = (opcode & 0x0040) >> 6;
1525 instruction->info.data_proc.Rd = Rd;
1526 instruction->info.data_proc.Rn = Rd;
1527 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1528 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1529 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1540 instruction->type = ARM_ADD;
1544 instruction->type = ARM_CMP;
1548 instruction->type = ARM_MOV;
1554 if ((opcode & 0x7) == 0x0)
1556 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1559 instruction->type = ARM_BLX;
1560 snprintf(instruction->text, 128,
1562 " 0x%4.4x \tBLX\tr%i",
1563 address, opcode, Rm);
1567 instruction->type = ARM_BX;
1568 snprintf(instruction->text, 128,
1570 " 0x%4.4x \tBX\tr%i",
1571 address, opcode, Rm);
1576 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1577 snprintf(instruction->text, 128,
1580 "UNDEFINED INSTRUCTION",
1592 instruction->type = ARM_AND;
1596 instruction->type = ARM_EOR;
1600 instruction->type = ARM_MOV;
1602 instruction->info.data_proc.variant = 2 /*register shift*/;
1603 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1604 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1605 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1608 instruction->type = ARM_MOV;
1610 instruction->info.data_proc.variant = 2 /*register shift*/;
1611 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1612 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1613 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1616 instruction->type = ARM_MOV;
1618 instruction->info.data_proc.variant = 2 /*register shift*/;
1619 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1620 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1621 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1624 instruction->type = ARM_ADC;
1628 instruction->type = ARM_SBC;
1632 instruction->type = ARM_MOV;
1634 instruction->info.data_proc.variant = 2 /*register shift*/;
1635 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1636 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1637 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1640 instruction->type = ARM_TST;
1644 instruction->type = ARM_RSB;
1646 instruction->info.data_proc.variant = 0 /*immediate*/;
1647 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1648 instruction->info.data_proc.Rn = Rm;
1651 instruction->type = ARM_CMP;
1655 instruction->type = ARM_CMN;
1659 instruction->type = ARM_ORR;
1663 instruction->type = ARM_MUL;
1667 instruction->type = ARM_BIC;
1671 instruction->type = ARM_MVN;
1678 snprintf(instruction->text, 128,
1679 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
1681 address, opcode, mnemonic, Rd, Rm);
1683 snprintf(instruction->text, 128,
1684 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1685 address, opcode, mnemonic, Rd, Rm);
1690 /* PC-relative data addressing is word-aligned even with Thumb */
1691 static inline uint32_t thumb_alignpc4(uint32_t addr)
1693 return (addr + 4) & ~3;
1696 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1699 uint8_t Rd = (opcode >> 8) & 0x7;
1701 instruction->type = ARM_LDR;
1702 immediate = opcode & 0x000000ff;
1705 instruction->info.load_store.Rd = Rd;
1706 instruction->info.load_store.Rn = 15 /*PC*/;
1707 instruction->info.load_store.index_mode = 0; /*offset*/
1708 instruction->info.load_store.offset_mode = 0; /*immediate*/
1709 instruction->info.load_store.offset.offset = immediate;
1711 snprintf(instruction->text, 128,
1712 "0x%8.8" PRIx32 " 0x%4.4x \t"
1713 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
1714 address, opcode, Rd, immediate,
1715 thumb_alignpc4(address) + immediate);
1720 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1722 uint8_t Rd = (opcode >> 0) & 0x7;
1723 uint8_t Rn = (opcode >> 3) & 0x7;
1724 uint8_t Rm = (opcode >> 6) & 0x7;
1725 uint8_t opc = (opcode >> 9) & 0x7;
1726 char *mnemonic = NULL;
1731 instruction->type = ARM_STR;
1735 instruction->type = ARM_STRH;
1739 instruction->type = ARM_STRB;
1743 instruction->type = ARM_LDRSB;
1747 instruction->type = ARM_LDR;
1751 instruction->type = ARM_LDRH;
1755 instruction->type = ARM_LDRB;
1759 instruction->type = ARM_LDRSH;
1764 snprintf(instruction->text, 128,
1765 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1766 address, opcode, mnemonic, Rd, Rn, Rm);
1768 instruction->info.load_store.Rd = Rd;
1769 instruction->info.load_store.Rn = Rn;
1770 instruction->info.load_store.index_mode = 0; /*offset*/
1771 instruction->info.load_store.offset_mode = 1; /*register*/
1772 instruction->info.load_store.offset.reg.Rm = Rm;
1777 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1779 uint32_t offset = (opcode >> 6) & 0x1f;
1780 uint8_t Rd = (opcode >> 0) & 0x7;
1781 uint8_t Rn = (opcode >> 3) & 0x7;
1782 uint32_t L = opcode & (1 << 11);
1783 uint32_t B = opcode & (1 << 12);
1790 instruction->type = ARM_LDR;
1795 instruction->type = ARM_STR;
1799 if ((opcode&0xF000) == 0x8000)
1810 snprintf(instruction->text, 128,
1811 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1812 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1814 instruction->info.load_store.Rd = Rd;
1815 instruction->info.load_store.Rn = Rn;
1816 instruction->info.load_store.index_mode = 0; /*offset*/
1817 instruction->info.load_store.offset_mode = 0; /*immediate*/
1818 instruction->info.load_store.offset.offset = offset << shift;
1823 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1825 uint32_t offset = opcode & 0xff;
1826 uint8_t Rd = (opcode >> 8) & 0x7;
1827 uint32_t L = opcode & (1 << 11);
1832 instruction->type = ARM_LDR;
1837 instruction->type = ARM_STR;
1841 snprintf(instruction->text, 128,
1842 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1843 address, opcode, mnemonic, Rd, offset*4);
1845 instruction->info.load_store.Rd = Rd;
1846 instruction->info.load_store.Rn = 13 /*SP*/;
1847 instruction->info.load_store.index_mode = 0; /*offset*/
1848 instruction->info.load_store.offset_mode = 0; /*immediate*/
1849 instruction->info.load_store.offset.offset = offset*4;
1854 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1856 uint32_t imm = opcode & 0xff;
1857 uint8_t Rd = (opcode >> 8) & 0x7;
1859 uint32_t SP = opcode & (1 << 11);
1862 instruction->type = ARM_ADD;
1875 snprintf(instruction->text, 128,
1876 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1877 address, opcode, Rd, reg_name, imm * 4);
1879 instruction->info.data_proc.variant = 0 /* immediate */;
1880 instruction->info.data_proc.Rd = Rd;
1881 instruction->info.data_proc.Rn = Rn;
1882 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1887 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1889 uint32_t imm = opcode & 0x7f;
1890 uint8_t opc = opcode & (1 << 7);
1896 instruction->type = ARM_SUB;
1901 instruction->type = ARM_ADD;
1905 snprintf(instruction->text, 128,
1906 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1907 address, opcode, mnemonic, imm*4);
1909 instruction->info.data_proc.variant = 0 /* immediate */;
1910 instruction->info.data_proc.Rd = 13 /*SP*/;
1911 instruction->info.data_proc.Rn = 13 /*SP*/;
1912 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1917 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1919 uint32_t imm = opcode & 0xff;
1921 instruction->type = ARM_BKPT;
1923 snprintf(instruction->text, 128,
1924 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1925 address, opcode, imm);
1930 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1932 uint32_t reg_list = opcode & 0xff;
1933 uint32_t L = opcode & (1 << 11);
1934 uint32_t R = opcode & (1 << 8);
1935 uint8_t Rn = (opcode >> 8) & 7;
1936 uint8_t addr_mode = 0 /* IA */;
1940 char ptr_name[7] = "";
1943 if ((opcode & 0xf000) == 0xc000)
1944 { /* generic load/store multiple */
1947 instruction->type = ARM_LDM;
1952 instruction->type = ARM_STM;
1955 snprintf(ptr_name,7,"r%i!, ",Rn);
1962 instruction->type = ARM_LDM;
1965 reg_list |= (1 << 15) /*PC*/;
1969 instruction->type = ARM_STM;
1971 addr_mode = 3; /*DB*/
1973 reg_list |= (1 << 14) /*LR*/;
1977 reg_names_p = reg_names;
1978 for (i = 0; i <= 15; i++)
1980 if (reg_list & (1 << i))
1981 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1983 if (reg_names_p > reg_names)
1984 reg_names_p[-2] = '\0';
1985 else /* invalid op : no registers */
1986 reg_names[0] = '\0';
1988 snprintf(instruction->text, 128,
1989 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1990 address, opcode, mnemonic, ptr_name, reg_names);
1992 instruction->info.load_store_multiple.register_list = reg_list;
1993 instruction->info.load_store_multiple.Rn = Rn;
1994 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1999 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2001 uint32_t offset = opcode & 0xff;
2002 uint8_t cond = (opcode >> 8) & 0xf;
2003 uint32_t target_address;
2007 instruction->type = ARM_SWI;
2008 snprintf(instruction->text, 128,
2009 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2010 address, opcode, offset);
2013 else if (cond == 0xe)
2015 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2016 snprintf(instruction->text, 128,
2017 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2022 /* sign extend 8-bit offset */
2023 if (offset & 0x00000080)
2024 offset = 0xffffff00 | offset;
2026 target_address = address + 4 + (offset << 1);
2028 snprintf(instruction->text, 128,
2029 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2031 arm_condition_strings[cond], target_address);
2033 instruction->type = ARM_B;
2034 instruction->info.b_bl_bx_blx.reg_operand = -1;
2035 instruction->info.b_bl_bx_blx.target_address = target_address;
2040 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2041 arm_instruction_t *instruction)
2045 /* added in Thumb2 */
2046 offset = (opcode >> 3) & 0x1f;
2047 offset |= (opcode & 0x0200) >> 4;
2049 snprintf(instruction->text, 128,
2050 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2052 (opcode & 0x0800) ? "N" : "",
2053 opcode & 0x7, address + 4 + (offset << 1));
2058 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2059 arm_instruction_t *instruction)
2061 /* added in ARMv6 */
2062 snprintf(instruction->text, 128,
2063 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2065 (opcode & 0x0080) ? 'U' : 'S',
2066 (opcode & 0x0040) ? 'B' : 'H',
2067 opcode & 0x7, (opcode >> 3) & 0x7);
2072 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2073 arm_instruction_t *instruction)
2075 /* added in ARMv6 */
2076 if ((opcode & 0x0ff0) == 0x0650)
2077 snprintf(instruction->text, 128,
2078 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2080 (opcode & 0x80) ? "BE" : "LE");
2081 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2082 snprintf(instruction->text, 128,
2083 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2085 (opcode & 0x0010) ? 'D' : 'E',
2086 (opcode & 0x0004) ? "A" : "",
2087 (opcode & 0x0002) ? "I" : "",
2088 (opcode & 0x0001) ? "F" : "");
2093 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2094 arm_instruction_t *instruction)
2098 /* added in ARMv6 */
2099 switch (opcode & 0x00c0) {
2110 snprintf(instruction->text, 128,
2111 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2112 address, opcode, suffix,
2113 opcode & 0x7, (opcode >> 3) & 0x7);
2118 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2119 arm_instruction_t *instruction)
2123 switch ((opcode >> 4) & 0x0f) {
2140 hint = "HINT (UNRECOGNIZED)";
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2146 address, opcode, hint);
2151 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2152 arm_instruction_t *instruction)
2154 unsigned cond = (opcode >> 4) & 0x0f;
2155 char *x = "", *y = "", *z = "";
2158 z = (opcode & 0x02) ? "T" : "E";
2160 y = (opcode & 0x04) ? "T" : "E";
2162 x = (opcode & 0x08) ? "T" : "E";
2164 snprintf(instruction->text, 128,
2165 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2167 x, y, z, arm_condition_strings[cond]);
2169 /* NOTE: strictly speaking, the next 1-4 instructions should
2170 * now be displayed with the relevant conditional suffix...
2176 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2178 /* clear fields, to avoid confusion */
2179 memset(instruction, 0, sizeof(arm_instruction_t));
2180 instruction->opcode = opcode;
2181 instruction->instruction_size = 2;
2183 if ((opcode & 0xe000) == 0x0000)
2185 /* add/substract register or immediate */
2186 if ((opcode & 0x1800) == 0x1800)
2187 return evaluate_add_sub_thumb(opcode, address, instruction);
2188 /* shift by immediate */
2190 return evaluate_shift_imm_thumb(opcode, address, instruction);
2193 /* Add/substract/compare/move immediate */
2194 if ((opcode & 0xe000) == 0x2000)
2196 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2199 /* Data processing instructions */
2200 if ((opcode & 0xf800) == 0x4000)
2202 return evaluate_data_proc_thumb(opcode, address, instruction);
2205 /* Load from literal pool */
2206 if ((opcode & 0xf800) == 0x4800)
2208 return evaluate_load_literal_thumb(opcode, address, instruction);
2211 /* Load/Store register offset */
2212 if ((opcode & 0xf000) == 0x5000)
2214 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2217 /* Load/Store immediate offset */
2218 if (((opcode & 0xe000) == 0x6000)
2219 ||((opcode & 0xf000) == 0x8000))
2221 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2224 /* Load/Store from/to stack */
2225 if ((opcode & 0xf000) == 0x9000)
2227 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2231 if ((opcode & 0xf000) == 0xa000)
2233 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2237 if ((opcode & 0xf000) == 0xb000)
2239 switch ((opcode >> 8) & 0x0f) {
2241 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2246 return evaluate_cb_thumb(opcode, address, instruction);
2248 return evaluate_extend_thumb(opcode, address, instruction);
2253 return evaluate_load_store_multiple_thumb(opcode, address,
2256 return evaluate_cps_thumb(opcode, address, instruction);
2258 if ((opcode & 0x00c0) == 0x0080)
2260 return evaluate_byterev_thumb(opcode, address, instruction);
2262 return evaluate_breakpoint_thumb(opcode, address, instruction);
2264 if (opcode & 0x000f)
2265 return evaluate_ifthen_thumb(opcode, address,
2268 return evaluate_hint_thumb(opcode, address,
2272 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2273 snprintf(instruction->text, 128,
2274 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2279 /* Load/Store multiple */
2280 if ((opcode & 0xf000) == 0xc000)
2282 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2285 /* Conditional branch + SWI */
2286 if ((opcode & 0xf000) == 0xd000)
2288 return evaluate_cond_branch_thumb(opcode, address, instruction);
2291 if ((opcode & 0xe000) == 0xe000)
2293 /* Undefined instructions */
2294 if ((opcode & 0xf801) == 0xe801)
2296 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2297 snprintf(instruction->text, 128,
2298 "0x%8.8" PRIx32 " 0x%8.8x\t"
2299 "UNDEFINED INSTRUCTION",
2304 { /* Branch to offset */
2305 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2309 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2313 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2314 arm_instruction_t *instruction, char *cp)
2317 unsigned b21 = 1 << 21;
2318 unsigned b22 = 1 << 22;
2320 /* instead of combining two smaller 16-bit branch instructions,
2321 * Thumb2 uses only one larger 32-bit instruction.
2323 offset = opcode & 0x7ff;
2324 offset |= (opcode & 0x03ff0000) >> 5;
2325 if (opcode & (1 << 26)) {
2326 offset |= 0xff << 23;
2327 if ((opcode & (1 << 11)) == 0)
2329 if ((opcode & (1 << 13)) == 0)
2332 if (opcode & (1 << 11))
2334 if (opcode & (1 << 13))
2342 address += offset << 1;
2344 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2345 instruction->info.b_bl_bx_blx.reg_operand = -1;
2346 instruction->info.b_bl_bx_blx.target_address = address;
2347 sprintf(cp, "%s\t%#8.8" PRIx32,
2348 (opcode & (1 << 14)) ? "BL" : "B.W",
2354 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2355 arm_instruction_t *instruction, char *cp)
2358 unsigned b17 = 1 << 17;
2359 unsigned b18 = 1 << 18;
2360 unsigned cond = (opcode >> 22) & 0x0f;
2362 offset = opcode & 0x7ff;
2363 offset |= (opcode & 0x003f0000) >> 5;
2364 if (opcode & (1 << 26)) {
2365 offset |= 0xffff << 19;
2366 if ((opcode & (1 << 11)) == 0)
2368 if ((opcode & (1 << 13)) == 0)
2371 if (opcode & (1 << 11))
2373 if (opcode & (1 << 13))
2380 address += offset << 1;
2382 instruction->type = ARM_B;
2383 instruction->info.b_bl_bx_blx.reg_operand = -1;
2384 instruction->info.b_bl_bx_blx.target_address = address;
2385 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2386 arm_condition_strings[cond],
2392 static const char *special_name(int number)
2394 char *special = "(RESERVED)";
2425 special = "primask";
2428 special = "basepri";
2431 special = "basepri_max";
2434 special = "faultmask";
2437 special = "control";
2443 static int t2ev_hint(uint32_t opcode, uint32_t address,
2444 arm_instruction_t *instruction, char *cp)
2446 const char *mnemonic;
2448 if (opcode & 0x0700) {
2449 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2450 strcpy(cp, "UNDEFINED");
2454 if (opcode & 0x00f0) {
2455 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2459 switch (opcode & 0x0f) {
2464 mnemonic = "YIELD.W";
2476 mnemonic = "HINT.W (UNRECOGNIZED)";
2479 strcpy(cp, mnemonic);
2483 static int t2ev_misc(uint32_t opcode, uint32_t address,
2484 arm_instruction_t *instruction, char *cp)
2486 const char *mnemonic;
2488 switch ((opcode >> 4) & 0x0f) {
2502 return ERROR_INVALID_ARGUMENTS;
2504 strcpy(cp, mnemonic);
2508 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2509 arm_instruction_t *instruction, char *cp)
2511 /* permanently undefined */
2512 if ((opcode & 0x07f07000) == 0x07f02000) {
2513 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2514 strcpy(cp, "UNDEFINED");
2518 switch ((opcode >> 12) & 0x5) {
2521 return t2ev_b_bl(opcode, address, instruction, cp);
2525 if (((opcode >> 23) & 0x07) != 0x07)
2526 return t2ev_cond_b(opcode, address, instruction, cp);
2527 if (opcode & (1 << 26))
2532 switch ((opcode >> 20) & 0x7f) {
2535 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2536 (int) (opcode >> 16) & 0x0f);
2539 return t2ev_hint(opcode, address, instruction, cp);
2541 return t2ev_misc(opcode, address, instruction, cp);
2544 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2545 special_name(opcode & 0xff));
2550 return ERROR_INVALID_ARGUMENTS;
2553 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2554 arm_instruction_t *instruction, char *cp)
2556 char *mnemonic = NULL;
2557 int rn = (opcode >> 16) & 0xf;
2558 int rd = (opcode >> 8) & 0xf;
2559 unsigned immed = opcode & 0xff;
2565 /* ARMv7-M: A5.3.2 Modified immediate constants */
2566 func = (opcode >> 11) & 0x0e;
2569 if (opcode & (1 << 26))
2572 /* "Modified" immediates */
2573 switch (func >> 1) {
2580 immed += immed << 16;
2583 immed += immed << 8;
2584 immed += immed << 16;
2588 immed = ror(immed, func);
2591 if (opcode & (1 << 20))
2594 switch ((opcode >> 21) & 0xf) {
2597 instruction->type = ARM_TST;
2604 instruction->type = ARM_AND;
2609 instruction->type = ARM_BIC;
2614 instruction->type = ARM_MOV;
2619 instruction->type = ARM_ORR;
2625 instruction->type = ARM_MVN;
2629 // instruction->type = ARM_ORN;
2635 instruction->type = ARM_TEQ;
2641 instruction->type = ARM_EOR;
2647 instruction->type = ARM_CMN;
2653 instruction->type = ARM_ADD;
2659 instruction->type = ARM_ADC;
2663 instruction->type = ARM_SBC;
2668 instruction->type = ARM_CMP;
2674 instruction->type = ARM_SUB;
2680 instruction->type = ARM_RSB;
2685 return ERROR_INVALID_ARGUMENTS;
2689 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
2690 mnemonic, suffix2 ,rd, immed, immed);
2692 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
2693 mnemonic, suffix, suffix2,
2694 rd, rn, immed, immed);
2699 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2700 arm_instruction_t *instruction, char *cp)
2702 char *mnemonic = NULL;
2703 int rn = (opcode >> 16) & 0xf;
2704 int rd = (opcode >> 8) & 0xf;
2707 bool is_signed = false;
2709 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2710 if (opcode & (1 << 27))
2713 switch ((opcode >> 20) & 0x1f) {
2730 /* move constant to top 16 bits of register */
2731 immed |= (opcode >> 4) & 0xf000;
2732 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2739 /* signed/unsigned saturated add */
2740 immed = (opcode >> 6) & 0x03;
2741 immed |= (opcode >> 10) & 0x1c;
2742 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2743 is_signed ? "S" : "U",
2744 rd, (int) (opcode & 0x1f) + 1, rn,
2745 (opcode & (1 << 21)) ? "ASR" : "LSL",
2746 immed ? immed : 32);
2752 /* signed/unsigned bitfield extract */
2753 immed = (opcode >> 6) & 0x03;
2754 immed |= (opcode >> 10) & 0x1c;
2755 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2756 is_signed ? "S" : "U",
2758 (int) (opcode & 0x1f) + 1);
2761 immed = (opcode >> 6) & 0x03;
2762 immed |= (opcode >> 10) & 0x1c;
2763 if (rn == 0xf) /* bitfield clear */
2764 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2766 (int) (opcode & 0x1f) + 1 - immed);
2767 else /* bitfield insert */
2768 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2770 (int) (opcode & 0x1f) + 1 - immed);
2773 return ERROR_INVALID_ARGUMENTS;
2776 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2777 rd, rn, immed, immed);
2781 address = thumb_alignpc4(address);
2786 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2787 * not hiding the pc-relative stuff will sometimes be useful.
2789 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2793 static int t2ev_store_single(uint32_t opcode, uint32_t address,
2794 arm_instruction_t *instruction, char *cp)
2796 unsigned op = (opcode >> 20) & 0xf;
2802 unsigned rn = (opcode >> 16) & 0x0f;
2803 unsigned rt = (opcode >> 12) & 0x0f;
2806 return ERROR_INVALID_ARGUMENTS;
2808 if (opcode & 0x0800)
2843 return ERROR_INVALID_ARGUMENTS;
2846 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
2847 size, rt, rn, (int) opcode & 0x0f,
2848 (int) (opcode >> 4) & 0x03);
2851 immed = opcode & 0x0fff;
2852 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
2853 size, rt, rn, immed, immed);
2857 immed = opcode & 0x00ff;
2859 switch (opcode & 0x700) {
2865 return ERROR_INVALID_ARGUMENTS;
2868 /* two indexed modes will write back rn */
2869 if (opcode & 0x100) {
2870 if (opcode & 0x400) /* pre-indexed */
2872 else { /* post-indexed */
2878 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
2879 size, suffix, rt, rn, p1,
2880 (opcode & 0x200) ? "" : "-",
2885 static int t2ev_mul32(uint32_t opcode, uint32_t address,
2886 arm_instruction_t *instruction, char *cp)
2888 int ra = (opcode >> 12) & 0xf;
2890 switch (opcode & 0x007000f0) {
2893 sprintf(cp, "MUL\tr%d, r%d, r%d",
2894 (int) (opcode >> 8) & 0xf,
2895 (int) (opcode >> 16) & 0xf,
2896 (int) (opcode >> 0) & 0xf);
2898 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
2899 (int) (opcode >> 8) & 0xf,
2900 (int) (opcode >> 16) & 0xf,
2901 (int) (opcode >> 0) & 0xf, ra);
2904 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
2905 (int) (opcode >> 8) & 0xf,
2906 (int) (opcode >> 16) & 0xf,
2907 (int) (opcode >> 0) & 0xf, ra);
2910 return ERROR_INVALID_ARGUMENTS;
2915 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
2916 arm_instruction_t *instruction, char *cp)
2918 int op = (opcode >> 4) & 0xf;
2919 char *infix = "MUL";
2921 op += (opcode >> 16) & 0x70;
2929 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
2930 (op & 0x20) ? 'U' : 'S',
2932 (int) (opcode >> 12) & 0xf,
2933 (int) (opcode >> 8) & 0xf,
2934 (int) (opcode >> 16) & 0xf,
2935 (int) (opcode >> 0) & 0xf);
2939 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
2940 (op & 0x20) ? 'U' : 'S',
2941 (int) (opcode >> 8) & 0xf,
2942 (int) (opcode >> 16) & 0xf,
2943 (int) (opcode >> 0) & 0xf);
2946 return ERROR_INVALID_ARGUMENTS;
2952 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
2953 arm_instruction_t *instruction, char *cp)
2955 int rn = (opcode >> 16) & 0xf;
2956 int op = (opcode >> 22) & 0x6;
2957 int t = (opcode >> 21) & 1;
2958 unsigned registers = opcode & 0xffff;
2960 if (opcode & (1 << 20))
2965 sprintf(cp, "STMB\tr%d%s, ", rn, t ? "!" : "");
2969 sprintf(cp, "POP\t");
2971 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
2975 sprintf(cp, "PUSH\t");
2977 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
2980 sprintf(cp, "LDMB\tr%d%s, ", rn, t ? "!" : "");
2983 return ERROR_INVALID_ARGUMENTS;
2988 for (t = 0; registers; t++, registers >>= 1) {
2989 if ((registers & 1) == 0)
2992 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3001 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3002 arm_instruction_t *instruction, char *cp)
3004 int op = (opcode >> 21) & 0xf;
3005 int rd = (opcode >> 8) & 0xf;
3006 int rn = (opcode >> 16) & 0xf;
3007 int type = (opcode >> 4) & 0x3;
3008 int immed = (opcode >> 6) & 0x3;
3012 immed |= (opcode >> 10) & 0x7;
3013 if (opcode & (1 << 21))
3019 if (!(opcode & (1 << 21)))
3020 return ERROR_INVALID_ARGUMENTS;
3021 instruction->type = ARM_TST;
3025 instruction->type = ARM_AND;
3029 instruction->type = ARM_BIC;
3034 instruction->type = ARM_MOV;
3038 sprintf(cp, "MOV%s.W\tr%d, r%d",
3040 (int) (opcode & 0xf));
3053 sprintf(cp, "RRX%s.W\tr%d, r%d",
3055 (int) (opcode & 0xf));
3063 instruction->type = ARM_ORR;
3069 instruction->type = ARM_MVN;
3074 // instruction->type = ARM_ORN;
3080 if (!(opcode & (1 << 21)))
3081 return ERROR_INVALID_ARGUMENTS;
3082 instruction->type = ARM_TEQ;
3086 instruction->type = ARM_EOR;
3091 if (!(opcode & (1 << 21)))
3092 return ERROR_INVALID_ARGUMENTS;
3093 instruction->type = ARM_CMN;
3097 instruction->type = ARM_ADD;
3101 instruction->type = ARM_ADC;
3105 instruction->type = ARM_SBC;
3110 if (!(opcode & (1 << 21)))
3111 return ERROR_INVALID_ARGUMENTS;
3112 instruction->type = ARM_CMP;
3116 instruction->type = ARM_SUB;
3120 instruction->type = ARM_RSB;
3124 return ERROR_INVALID_ARGUMENTS;
3127 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3128 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3153 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3157 sprintf(cp, "%s%s.W\tr%d, r%d",
3158 mnemonic, suffix, rn, (int) (opcode & 0xf));
3162 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3163 mnemonic, suffix, rd,
3164 (int) (opcode & 0xf), immed ? immed : 32);
3168 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3169 arm_instruction_t *instruction, char *cp)
3174 if (((opcode >> 4) & 0xf) == 0) {
3175 switch ((opcode >> 21) & 0x7) {
3189 return ERROR_INVALID_ARGUMENTS;
3192 instruction->type = ARM_MOV;
3193 if (opcode & (1 << 20))
3195 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3197 (int) (opcode >> 8) & 0xf,
3198 (int) (opcode >> 16) & 0xf,
3199 (int) (opcode >> 0) & 0xf);
3201 } else if (opcode & (1 << 7)) {
3202 switch ((opcode >> 24) & 0xf) {
3207 switch ((opcode >> 4) & 0x3) {
3209 suffix = ", ROR #8";
3212 suffix = ", ROR #16";
3215 suffix = ", ROR #24";
3218 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3219 (opcode & (1 << 24)) ? 'U' : 'S',
3220 (opcode & (1 << 26)) ? 'B' : 'H',
3221 (int) (opcode >> 8) & 0xf,
3222 (int) (opcode >> 16) & 0xf,
3229 if (opcode & (1 << 6))
3230 return ERROR_INVALID_ARGUMENTS;
3231 if (~opcode & (0xff << 12))
3232 return ERROR_INVALID_ARGUMENTS;
3233 if (!(opcode & (1 << 20)))
3234 return ERROR_INVALID_ARGUMENTS;
3236 switch (((opcode >> 19) & 0x04)
3237 | ((opcode >> 4) & 0x3)) {
3242 mnemonic = "REV16.W";
3248 mnemonic = "REVSH.W";
3254 return ERROR_INVALID_ARGUMENTS;
3256 sprintf(cp, "%s\tr%d, r%d",
3258 (int) (opcode >> 8) & 0xf,
3259 (int) (opcode >> 0) & 0xf);
3262 return ERROR_INVALID_ARGUMENTS;
3269 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3270 arm_instruction_t *instruction, char *cp)
3272 int rn = (opcode >> 16) & 0xf;
3275 instruction->type = ARM_LDR;
3278 immed = opcode & 0x0fff;
3279 if (opcode & (1 << 23))
3281 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3282 (int) (opcode >> 12) & 0xf,
3283 thumb_alignpc4(address) + immed);
3287 if (opcode & (1 << 23)) {
3288 immed = opcode & 0x0fff;
3289 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3290 (int) (opcode >> 12) & 0xf,
3295 if (!(opcode & (0x3f << 6))) {
3296 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3297 (int) (opcode >> 12) & 0xf,
3299 (int) (opcode >> 0) & 0xf,
3300 (int) (opcode >> 4) & 0x3);
3305 if (((opcode >> 8) & 0xf) == 0xe) {
3306 immed = opcode & 0x00ff;
3308 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3309 (int) (opcode >> 12) & 0xf,
3314 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3315 char *p1 = "]", *p2 = "";
3317 if (!(opcode & 0x0600))
3318 return ERROR_INVALID_ARGUMENTS;
3320 immed = opcode & 0x00ff;
3322 /* two indexed modes will write back rn */
3323 if (opcode & 0x100) {
3324 if (opcode & 0x400) /* pre-indexed */
3326 else { /* post-indexed */
3332 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3333 (int) (opcode >> 12) & 0xf,
3335 (opcode & 0x200) ? "" : "-",
3340 return ERROR_INVALID_ARGUMENTS;
3344 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
3345 * always set. That means eventual arm_simulate_step() support for Thumb2
3346 * will need work in this area.
3348 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
3355 /* clear low bit ... it's set on function pointers */
3358 /* clear fields, to avoid confusion */
3359 memset(instruction, 0, sizeof(arm_instruction_t));
3361 /* read first halfword, see if this is the only one */
3362 retval = target_read_u16(target, address, &op);
3363 if (retval != ERROR_OK)
3366 switch (op & 0xf800) {
3370 /* 32-bit instructions */
3371 instruction->instruction_size = 4;
3373 retval = target_read_u16(target, address + 2, &op);
3374 if (retval != ERROR_OK)
3377 instruction->opcode = opcode;
3380 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
3381 return thumb_evaluate_opcode(op, address, instruction);
3384 snprintf(instruction->text, 128,
3385 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
3387 cp = strchr(instruction->text, 0);
3388 retval = ERROR_FAIL;
3390 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3391 if ((opcode & 0x1a008000) == 0x10000000)
3392 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3394 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3395 else if ((opcode & 0x1a008000) == 0x12000000)
3396 retval = t2ev_data_immed(opcode, address, instruction, cp);
3398 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3399 else if ((opcode & 0x18008000) == 0x10008000)
3400 retval = t2ev_b_misc(opcode, address, instruction, cp);
3402 /* ARMv7-M: A5.3.5 Load/store multiple */
3403 else if ((opcode & 0x1e400000) == 0x08000000)
3404 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3406 /* ARMv7-M: A5.3.7 Load word */
3407 else if ((opcode & 0x1f700000) == 0x18500000)
3408 retval = t2ev_load_word(opcode, address, instruction, cp);
3410 /* ARMv7-M: A5.3.10 Store single data item */
3411 else if ((opcode & 0x1f100000) == 0x18000000)
3412 retval = t2ev_store_single(opcode, address, instruction, cp);
3414 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
3415 else if ((opcode & 0x1e000000) == 0x0a000000)
3416 retval = t2ev_data_shift(opcode, address, instruction, cp);
3418 /* ARMv7-M: A5.3.12 Data processing (register) */
3419 else if ((opcode & 0x1f000000) == 0x1a000000)
3420 retval = t2ev_data_reg(opcode, address, instruction, cp);
3422 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3423 else if ((opcode & 0x1f800000) == 0x1b000000)
3424 retval = t2ev_mul32(opcode, address, instruction, cp);
3426 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3427 else if ((opcode & 0x1f800000) == 0x1b800000)
3428 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3430 /* FIXME decode more 32-bit instructions */
3432 if (retval == ERROR_OK)
3435 if (retval == ERROR_INVALID_ARGUMENTS) {
3436 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3437 strcpy(cp, "UNDEFINED OPCODE");
3441 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
3444 strcpy(cp, "(32-bit Thumb2 ...)");
3448 int arm_access_size(arm_instruction_t *instruction)
3450 if ((instruction->type == ARM_LDRB)
3451 || (instruction->type == ARM_LDRBT)
3452 || (instruction->type == ARM_LDRSB)
3453 || (instruction->type == ARM_STRB)
3454 || (instruction->type == ARM_STRBT))
3458 else if ((instruction->type == ARM_LDRH)
3459 || (instruction->type == ARM_LDRSH)
3460 || (instruction->type == ARM_STRH))
3464 else if ((instruction->type == ARM_LDR)
3465 || (instruction->type == ARM_LDRT)
3466 || (instruction->type == ARM_STR)
3467 || (instruction->type == ARM_STRT))
3471 else if ((instruction->type == ARM_LDRD)
3472 || (instruction->type == ARM_STRD))
3478 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);