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, "0x%8.8" PRIx32 "\t0x%4.4x\t%s 0x%8.8" PRIx32 , address, opcode,mnemonic, target_address);
1372 instruction->info.b_bl_bx_blx.reg_operand = -1;
1373 instruction->info.b_bl_bx_blx.target_address = target_address;
1378 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1380 uint8_t Rd = (opcode >> 0) & 0x7;
1381 uint8_t Rn = (opcode >> 3) & 0x7;
1382 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1383 uint32_t opc = opcode & (1 << 9);
1384 uint32_t reg_imm = opcode & (1 << 10);
1389 instruction->type = ARM_SUB;
1394 instruction->type = ARM_ADD;
1398 instruction->info.data_proc.Rd = Rd;
1399 instruction->info.data_proc.Rn = Rn;
1400 instruction->info.data_proc.S = 1;
1404 instruction->info.data_proc.variant = 0; /*immediate*/
1405 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1406 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #%d",
1407 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1411 instruction->info.data_proc.variant = 1; /*immediate shift*/
1412 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1413 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, r%i",
1414 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1420 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1422 uint8_t Rd = (opcode >> 0) & 0x7;
1423 uint8_t Rm = (opcode >> 3) & 0x7;
1424 uint8_t imm = (opcode >> 6) & 0x1f;
1425 uint8_t opc = (opcode >> 11) & 0x3;
1426 char *mnemonic = NULL;
1431 instruction->type = ARM_MOV;
1433 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1436 instruction->type = ARM_MOV;
1438 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1441 instruction->type = ARM_MOV;
1443 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1447 if ((imm == 0) && (opc != 0))
1450 instruction->info.data_proc.Rd = Rd;
1451 instruction->info.data_proc.Rn = -1;
1452 instruction->info.data_proc.S = 1;
1454 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1455 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1456 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1458 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #0x%02x" ,
1459 address, opcode, mnemonic, Rd, Rm, imm);
1464 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1466 uint8_t imm = opcode & 0xff;
1467 uint8_t Rd = (opcode >> 8) & 0x7;
1468 uint32_t opc = (opcode >> 11) & 0x3;
1469 char *mnemonic = NULL;
1471 instruction->info.data_proc.Rd = Rd;
1472 instruction->info.data_proc.Rn = Rd;
1473 instruction->info.data_proc.S = 1;
1474 instruction->info.data_proc.variant = 0; /*immediate*/
1475 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1480 instruction->type = ARM_MOV;
1482 instruction->info.data_proc.Rn = -1;
1485 instruction->type = ARM_CMP;
1487 instruction->info.data_proc.Rd = -1;
1490 instruction->type = ARM_ADD;
1494 instruction->type = ARM_SUB;
1499 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, #0x%02x" ,
1500 address, opcode, mnemonic, Rd, imm);
1505 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1507 uint8_t high_reg, op, Rm, Rd,H1,H2;
1508 char *mnemonic = NULL;
1510 high_reg = (opcode & 0x0400) >> 10;
1511 op = (opcode & 0x03C0) >> 6;
1513 Rd = (opcode & 0x0007);
1514 Rm = (opcode & 0x0038) >> 3;
1515 H1 = (opcode & 0x0080) >> 7;
1516 H2 = (opcode & 0x0040) >> 6;
1518 instruction->info.data_proc.Rd = Rd;
1519 instruction->info.data_proc.Rn = Rd;
1520 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1521 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1522 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1533 instruction->type = ARM_ADD;
1537 instruction->type = ARM_CMP;
1541 instruction->type = ARM_MOV;
1545 if ((opcode & 0x7) == 0x0)
1547 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1550 instruction->type = ARM_BLX;
1551 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBLX r%i", address, opcode, Rm);
1555 instruction->type = ARM_BX;
1556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBX r%i", address, opcode, Rm);
1561 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1562 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1573 instruction->type = ARM_AND;
1577 instruction->type = ARM_EOR;
1581 instruction->type = ARM_MOV;
1583 instruction->info.data_proc.variant = 2 /*register shift*/;
1584 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1585 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1586 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1589 instruction->type = ARM_MOV;
1591 instruction->info.data_proc.variant = 2 /*register shift*/;
1592 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1593 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1594 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1597 instruction->type = ARM_MOV;
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
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_ADC;
1609 instruction->type = ARM_SBC;
1613 instruction->type = ARM_MOV;
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
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_TST;
1625 instruction->type = ARM_RSB;
1627 instruction->info.data_proc.variant = 0 /*immediate*/;
1628 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1629 instruction->info.data_proc.Rn = Rm;
1632 instruction->type = ARM_CMP;
1636 instruction->type = ARM_CMN;
1640 instruction->type = ARM_ORR;
1644 instruction->type = ARM_MUL;
1648 instruction->type = ARM_BIC;
1652 instruction->type = ARM_MVN;
1658 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i",
1659 address, opcode, mnemonic, Rd, Rm);
1664 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1667 uint8_t Rd = (opcode >> 8) & 0x7;
1669 instruction->type = ARM_LDR;
1670 immediate = opcode & 0x000000ff;
1672 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tLDR r%i, [PC, #0x%" PRIx32 "]", address, opcode, Rd, immediate*4);
1674 instruction->info.load_store.Rd = Rd;
1675 instruction->info.load_store.Rn = 15 /*PC*/;
1676 instruction->info.load_store.index_mode = 0; /*offset*/
1677 instruction->info.load_store.offset_mode = 0; /*immediate*/
1678 instruction->info.load_store.offset.offset = immediate*4;
1683 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1685 uint8_t Rd = (opcode >> 0) & 0x7;
1686 uint8_t Rn = (opcode >> 3) & 0x7;
1687 uint8_t Rm = (opcode >> 6) & 0x7;
1688 uint8_t opc = (opcode >> 9) & 0x7;
1689 char *mnemonic = NULL;
1694 instruction->type = ARM_STR;
1698 instruction->type = ARM_STRH;
1702 instruction->type = ARM_STRB;
1706 instruction->type = ARM_LDRSB;
1710 instruction->type = ARM_LDR;
1714 instruction->type = ARM_LDRH;
1718 instruction->type = ARM_LDRB;
1722 instruction->type = ARM_LDRSH;
1727 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, [r%i, r%i]", address, opcode, mnemonic, Rd, Rn, Rm);
1729 instruction->info.load_store.Rd = Rd;
1730 instruction->info.load_store.Rn = Rn;
1731 instruction->info.load_store.index_mode = 0; /*offset*/
1732 instruction->info.load_store.offset_mode = 1; /*register*/
1733 instruction->info.load_store.offset.reg.Rm = Rm;
1738 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1740 uint32_t offset = (opcode >> 6) & 0x1f;
1741 uint8_t Rd = (opcode >> 0) & 0x7;
1742 uint8_t Rn = (opcode >> 3) & 0x7;
1743 uint32_t L = opcode & (1 << 11);
1744 uint32_t B = opcode & (1 << 12);
1751 instruction->type = ARM_LDR;
1756 instruction->type = ARM_STR;
1760 if ((opcode&0xF000) == 0x8000)
1771 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s%c r%i, [r%i, #0x%" PRIx32 "]", address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1773 instruction->info.load_store.Rd = Rd;
1774 instruction->info.load_store.Rn = Rn;
1775 instruction->info.load_store.index_mode = 0; /*offset*/
1776 instruction->info.load_store.offset_mode = 0; /*immediate*/
1777 instruction->info.load_store.offset.offset = offset << shift;
1782 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1784 uint32_t offset = opcode & 0xff;
1785 uint8_t Rd = (opcode >> 8) & 0x7;
1786 uint32_t L = opcode & (1 << 11);
1791 instruction->type = ARM_LDR;
1796 instruction->type = ARM_STR;
1800 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, [SP, #0x%" PRIx32 "]", address, opcode, mnemonic, Rd, offset*4);
1802 instruction->info.load_store.Rd = Rd;
1803 instruction->info.load_store.Rn = 13 /*SP*/;
1804 instruction->info.load_store.index_mode = 0; /*offset*/
1805 instruction->info.load_store.offset_mode = 0; /*immediate*/
1806 instruction->info.load_store.offset.offset = offset*4;
1811 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1813 uint32_t imm = opcode & 0xff;
1814 uint8_t Rd = (opcode >> 8) & 0x7;
1816 uint32_t SP = opcode & (1 << 11);
1819 instruction->type = ARM_ADD;
1832 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tADD r%i, %s, #0x%" PRIx32 "", address, opcode, Rd,reg_name, imm*4);
1834 instruction->info.data_proc.variant = 0 /* immediate */;
1835 instruction->info.data_proc.Rd = Rd;
1836 instruction->info.data_proc.Rn = Rn;
1837 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1842 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1844 uint32_t imm = opcode & 0x7f;
1845 uint8_t opc = opcode & (1 << 7);
1851 instruction->type = ARM_SUB;
1856 instruction->type = ARM_ADD;
1860 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s SP, #0x%" PRIx32 "", address, opcode, mnemonic, imm*4);
1862 instruction->info.data_proc.variant = 0 /* immediate */;
1863 instruction->info.data_proc.Rd = 13 /*SP*/;
1864 instruction->info.data_proc.Rn = 13 /*SP*/;
1865 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1870 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1872 uint32_t imm = opcode & 0xff;
1874 instruction->type = ARM_BKPT;
1876 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBKPT 0x%02" PRIx32 "", address, opcode, imm);
1881 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1883 uint32_t reg_list = opcode & 0xff;
1884 uint32_t L = opcode & (1 << 11);
1885 uint32_t R = opcode & (1 << 8);
1886 uint8_t Rn = (opcode >> 8) & 7;
1887 uint8_t addr_mode = 0 /* IA */;
1891 char ptr_name[7] = "";
1894 if ((opcode & 0xf000) == 0xc000)
1895 { /* generic load/store multiple */
1898 instruction->type = ARM_LDM;
1903 instruction->type = ARM_STM;
1906 snprintf(ptr_name,7,"r%i!, ",Rn);
1913 instruction->type = ARM_LDM;
1916 reg_list |= (1 << 15) /*PC*/;
1920 instruction->type = ARM_STM;
1922 addr_mode = 3; /*DB*/
1924 reg_list |= (1 << 14) /*LR*/;
1928 reg_names_p = reg_names;
1929 for (i = 0; i <= 15; i++)
1931 if (reg_list & (1 << i))
1932 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1934 if (reg_names_p > reg_names)
1935 reg_names_p[-2] = '\0';
1936 else /* invalid op : no registers */
1937 reg_names[0] = '\0';
1939 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s %s{%s}", address, opcode, mnemonic, ptr_name,reg_names);
1941 instruction->info.load_store_multiple.register_list = reg_list;
1942 instruction->info.load_store_multiple.Rn = Rn;
1943 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1948 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1950 uint32_t offset = opcode & 0xff;
1951 uint8_t cond = (opcode >> 8) & 0xf;
1952 uint32_t target_address;
1956 instruction->type = ARM_SWI;
1957 snprintf(instruction->text, 128,
1958 "0x%8.8" PRIx32 "\t0x%4.4x\tSVC 0x%02" PRIx32,
1959 address, opcode, offset);
1962 else if (cond == 0xe)
1964 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1965 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1969 /* sign extend 8-bit offset */
1970 if (offset & 0x00000080)
1971 offset = 0xffffff00 | offset;
1973 target_address = address + 4 + (offset << 1);
1975 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tB%s 0x%8.8" PRIx32 , address, opcode,
1976 arm_condition_strings[cond], target_address);
1978 instruction->type = ARM_B;
1979 instruction->info.b_bl_bx_blx.reg_operand = -1;
1980 instruction->info.b_bl_bx_blx.target_address = target_address;
1985 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
1986 arm_instruction_t *instruction)
1990 /* added in Thumb2 */
1991 offset = (opcode >> 3) & 0x1f;
1992 offset |= (opcode & 0x0200) >> 4;
1994 snprintf(instruction->text, 128,
1995 "0x%8.8" PRIx32 "\t0x%4.4x\tCB%sZ r%d, %#8.8" PRIx32,
1997 (opcode & 0x0800) ? "N" : "",
1998 opcode & 0x7, address + 4 + (offset << 1));
2003 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2004 arm_instruction_t *instruction)
2006 /* added in ARMv6 */
2007 snprintf(instruction->text, 128,
2008 "0x%8.8" PRIx32 "\t0x%4.4x\t%cXT%c r%d, r%d",
2010 (opcode & 0x0080) ? 'U' : 'S',
2011 (opcode & 0x0040) ? 'B' : 'H',
2012 opcode & 0x7, (opcode >> 3) & 0x7);
2017 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2018 arm_instruction_t *instruction)
2020 /* added in ARMv6 */
2021 if ((opcode & 0x0ff0) == 0x0650)
2022 snprintf(instruction->text, 128,
2023 "0x%8.8" PRIx32 "\t0x%4.4x\tSETEND %s",
2025 (opcode & 0x80) ? "BE" : "LE");
2026 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2027 snprintf(instruction->text, 128,
2028 "0x%8.8" PRIx32 "\t0x%4.4x\tCPSI%c %s%s%s",
2030 (opcode & 0x0010) ? 'D' : 'E',
2031 (opcode & 0x0004) ? "A" : "",
2032 (opcode & 0x0002) ? "I" : "",
2033 (opcode & 0x0001) ? "F" : "");
2038 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2039 arm_instruction_t *instruction)
2043 /* added in ARMv6 */
2044 switch (opcode & 0x00c0) {
2055 snprintf(instruction->text, 128,
2056 "0x%8.8" PRIx32 "\t0x%4.4x\tREV%s r%d, r%d",
2057 address, opcode, suffix,
2058 opcode & 0x7, (opcode >> 3) & 0x7);
2063 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2064 arm_instruction_t *instruction)
2068 switch ((opcode >> 4) & 0x0f) {
2085 hint = "HINT (UNRECOGNIZED)";
2089 snprintf(instruction->text, 128,
2090 "0x%8.8" PRIx32 "\t0x%4.4x\t%s",
2091 address, opcode, hint);
2096 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2097 arm_instruction_t *instruction)
2099 unsigned cond = (opcode >> 4) & 0x0f;
2100 char *x = "", *y = "", *z = "";
2103 z = (opcode & 0x02) ? "T" : "E";
2105 y = (opcode & 0x04) ? "T" : "E";
2107 x = (opcode & 0x08) ? "T" : "E";
2109 snprintf(instruction->text, 128,
2110 "0x%8.8" PRIx32 "\t0x%4.4x\tIT%s%s%s %s",
2112 x, y, z, arm_condition_strings[cond]);
2114 /* NOTE: strictly speaking, the next 1-4 instructions should
2115 * now be displayed with the relevant conditional suffix...
2121 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2123 /* clear fields, to avoid confusion */
2124 memset(instruction, 0, sizeof(arm_instruction_t));
2125 instruction->opcode = opcode;
2126 instruction->instruction_size = 2;
2128 if ((opcode & 0xe000) == 0x0000)
2130 /* add/substract register or immediate */
2131 if ((opcode & 0x1800) == 0x1800)
2132 return evaluate_add_sub_thumb(opcode, address, instruction);
2133 /* shift by immediate */
2135 return evaluate_shift_imm_thumb(opcode, address, instruction);
2138 /* Add/substract/compare/move immediate */
2139 if ((opcode & 0xe000) == 0x2000)
2141 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2144 /* Data processing instructions */
2145 if ((opcode & 0xf800) == 0x4000)
2147 return evaluate_data_proc_thumb(opcode, address, instruction);
2150 /* Load from literal pool */
2151 if ((opcode & 0xf800) == 0x4800)
2153 return evaluate_load_literal_thumb(opcode, address, instruction);
2156 /* Load/Store register offset */
2157 if ((opcode & 0xf000) == 0x5000)
2159 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2162 /* Load/Store immediate offset */
2163 if (((opcode & 0xe000) == 0x6000)
2164 ||((opcode & 0xf000) == 0x8000))
2166 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2169 /* Load/Store from/to stack */
2170 if ((opcode & 0xf000) == 0x9000)
2172 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2176 if ((opcode & 0xf000) == 0xa000)
2178 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2182 if ((opcode & 0xf000) == 0xb000)
2184 switch ((opcode >> 8) & 0x0f) {
2186 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2191 return evaluate_cb_thumb(opcode, address, instruction);
2193 return evaluate_extend_thumb(opcode, address, instruction);
2198 return evaluate_load_store_multiple_thumb(opcode, address,
2201 return evaluate_cps_thumb(opcode, address, instruction);
2203 if ((opcode & 0x00c0) == 0x0080)
2205 return evaluate_byterev_thumb(opcode, address, instruction);
2207 return evaluate_breakpoint_thumb(opcode, address, instruction);
2209 if (opcode & 0x000f)
2210 return evaluate_ifthen_thumb(opcode, address,
2213 return evaluate_hint_thumb(opcode, address,
2217 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2218 snprintf(instruction->text, 128,
2219 "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION",
2224 /* Load/Store multiple */
2225 if ((opcode & 0xf000) == 0xc000)
2227 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2230 /* Conditional branch + SWI */
2231 if ((opcode & 0xf000) == 0xd000)
2233 return evaluate_cond_branch_thumb(opcode, address, instruction);
2236 if ((opcode & 0xe000) == 0xe000)
2238 /* Undefined instructions */
2239 if ((opcode & 0xf801) == 0xe801)
2241 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2242 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
2246 { /* Branch to offset */
2247 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2251 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2256 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2257 * always set. That means eventual arm_simulate_step() support for Thumb2
2258 * will need work in this area.
2260 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2266 /* clear low bit ... it's set on function pointers */
2269 /* clear fields, to avoid confusion */
2270 memset(instruction, 0, sizeof(arm_instruction_t));
2272 /* read first halfword, see if this is the only one */
2273 retval = target_read_u16(target, address, &op);
2274 if (retval != ERROR_OK)
2277 switch (op & 0xf800) {
2281 /* 32-bit instructions */
2282 instruction->instruction_size = 4;
2284 retval = target_read_u16(target, address + 2, &op);
2285 if (retval != ERROR_OK)
2288 instruction->opcode = opcode;
2291 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2292 return thumb_evaluate_opcode(op, address, instruction);
2295 /* FIXME decode the 32-bit instructions */
2297 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2299 snprintf(instruction->text, 128,
2300 "0x%8.8" PRIx32 "\t0x%8.8x\t... 32-bit Thumb2 ...",
2305 int arm_access_size(arm_instruction_t *instruction)
2307 if ((instruction->type == ARM_LDRB)
2308 || (instruction->type == ARM_LDRBT)
2309 || (instruction->type == ARM_LDRSB)
2310 || (instruction->type == ARM_STRB)
2311 || (instruction->type == ARM_STRBT))
2315 else if ((instruction->type == ARM_LDRH)
2316 || (instruction->type == ARM_LDRSH)
2317 || (instruction->type == ARM_STRH))
2321 else if ((instruction->type == ARM_LDR)
2322 || (instruction->type == ARM_LDRT)
2323 || (instruction->type == ARM_STR)
2324 || (instruction->type == ARM_STRT))
2328 else if ((instruction->type == ARM_LDRD)
2329 || (instruction->type == ARM_STRD))
2335 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);