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 ***************************************************************************/
24 #include "arm_disassembler.h"
28 /* textual represenation of the condition field */
29 /* ALways (default) is ommitted (empty string) */
30 char *arm_condition_strings[] =
32 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
35 /* make up for C's missing ROR */
36 uint32_t ror(uint32_t value, int places)
38 return (value >> places) | (value << (32 - places));
41 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
44 if ((opcode & 0x0d70f0000) == 0x0550f000)
46 instruction->type = ARM_PLD;
48 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
54 instruction->type = ARM_UNDEFINED_INSTRUCTION;
58 LOG_ERROR("should never reach this point");
62 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
64 instruction->type = ARM_SWI;
66 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI 0x%6.6" PRIx32 "", address, opcode, (opcode & 0xffffff));
71 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
75 uint32_t target_address;
77 instruction->type = ARM_BLX;
78 immediate = opcode & 0x00ffffff;
80 /* sign extend 24-bit immediate */
81 if (immediate & 0x00800000)
82 offset = 0xff000000 | immediate;
86 /* shift two bits left */
89 /* odd/event halfword */
90 if (opcode & 0x01000000)
93 target_address = address + 8 + offset;
95 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
97 instruction->info.b_bl_bx_blx.reg_operand = -1;
98 instruction->info.b_bl_bx_blx.target_address = target_address;
103 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
108 uint32_t target_address;
110 immediate = opcode & 0x00ffffff;
111 L = (opcode & 0x01000000) >> 24;
113 /* sign extend 24-bit immediate */
114 if (immediate & 0x00800000)
115 offset = 0xff000000 | immediate;
119 /* shift two bits left */
122 target_address = address + 8 + offset;
125 instruction->type = ARM_BL;
127 instruction->type = ARM_B;
129 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
130 (L) ? "L" : "", COND(opcode), target_address);
132 instruction->info.b_bl_bx_blx.reg_operand = -1;
133 instruction->info.b_bl_bx_blx.target_address = target_address;
138 /* Coprocessor load/store and double register transfers */
139 /* both normal and extended instruction space (condition field b1111) */
140 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
142 uint8_t cp_num = (opcode & 0xf00) >> 8;
145 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
147 uint8_t cp_opcode, Rd, Rn, CRm;
150 cp_opcode = (opcode & 0xf0) >> 4;
151 Rd = (opcode & 0xf000) >> 12;
152 Rn = (opcode & 0xf0000) >> 16;
153 CRm = (opcode & 0xf);
156 if ((opcode & 0x0ff00000) == 0x0c400000)
158 instruction->type = ARM_MCRR;
163 if ((opcode & 0x0ff00000) == 0x0c500000)
165 instruction->type = ARM_MRRC;
169 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
170 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
172 else /* LDC or STC */
174 uint8_t CRd, Rn, offset;
177 char addressing_mode[32];
179 CRd = (opcode & 0xf000) >> 12;
180 Rn = (opcode & 0xf0000) >> 16;
181 offset = (opcode & 0xff);
184 if (opcode & 0x00100000)
186 instruction->type = ARM_LDC;
191 instruction->type = ARM_STC;
195 U = (opcode & 0x00800000) >> 23;
196 N = (opcode & 0x00400000) >> 22;
198 /* addressing modes */
199 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
200 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
201 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
202 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
203 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
204 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
205 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
206 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
208 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
209 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
211 cp_num, CRd, addressing_mode);
217 /* Coprocessor data processing instructions */
218 /* Coprocessor register transfer instructions */
219 /* both normal and extended instruction space (condition field b1111) */
220 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
224 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
226 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
227 cp_num = (opcode & 0xf00) >> 8;
228 CRd_Rd = (opcode & 0xf000) >> 12;
229 CRn = (opcode & 0xf0000) >> 16;
230 CRm = (opcode & 0xf);
231 opcode_2 = (opcode & 0xe0) >> 5;
234 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
236 if (opcode & 0x00100000) /* bit 20 set -> MRC */
238 instruction->type = ARM_MRC;
241 else /* bit 20 not set -> MCR */
243 instruction->type = ARM_MCR;
247 opcode_1 = (opcode & 0x00e00000) >> 21;
249 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",
250 address, opcode, mnemonic, cond,
251 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
253 else /* bit 4 not set -> CDP */
255 instruction->type = ARM_CDP;
258 opcode_1 = (opcode & 0x00f00000) >> 20;
260 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",
261 address, opcode, mnemonic, cond,
262 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
268 /* Load/store instructions */
269 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
271 uint8_t I, P, U, B, W, L;
273 char *operation; /* "LDR" or "STR" */
274 char *suffix; /* "", "B", "T", "BT" */
278 I = (opcode & 0x02000000) >> 25;
279 P = (opcode & 0x01000000) >> 24;
280 U = (opcode & 0x00800000) >> 23;
281 B = (opcode & 0x00400000) >> 22;
282 W = (opcode & 0x00200000) >> 21;
283 L = (opcode & 0x00100000) >> 20;
285 /* target register */
286 Rd = (opcode & 0xf000) >> 12;
289 Rn = (opcode & 0xf0000) >> 16;
291 instruction->info.load_store.Rd = Rd;
292 instruction->info.load_store.Rn = Rn;
293 instruction->info.load_store.U = U;
295 /* determine operation */
301 /* determine instruction type and suffix */
304 if ((P == 0) && (W == 1))
307 instruction->type = ARM_LDRBT;
309 instruction->type = ARM_STRBT;
315 instruction->type = ARM_LDRB;
317 instruction->type = ARM_STRB;
323 if ((P == 0) && (W == 1))
326 instruction->type = ARM_LDRT;
328 instruction->type = ARM_STRT;
334 instruction->type = ARM_LDR;
336 instruction->type = ARM_STR;
341 if (!I) /* #+-<offset_12> */
343 uint32_t offset_12 = (opcode & 0xfff);
345 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
347 snprintf(offset, 32, "%s", "");
349 instruction->info.load_store.offset_mode = 0;
350 instruction->info.load_store.offset.offset = offset_12;
352 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
354 uint8_t shift_imm, shift;
357 shift_imm = (opcode & 0xf80) >> 7;
358 shift = (opcode & 0x60) >> 5;
361 /* LSR encodes a shift by 32 bit as 0x0 */
362 if ((shift == 0x1) && (shift_imm == 0x0))
365 /* ASR encodes a shift by 32 bit as 0x0 */
366 if ((shift == 0x2) && (shift_imm == 0x0))
369 /* ROR by 32 bit is actually a RRX */
370 if ((shift == 0x3) && (shift_imm == 0x0))
373 instruction->info.load_store.offset_mode = 1;
374 instruction->info.load_store.offset.reg.Rm = Rm;
375 instruction->info.load_store.offset.reg.shift = shift;
376 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
378 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
380 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
382 else /* +-<Rm>, <Shift>, #<shift_imm> */
387 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
390 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
393 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
396 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
399 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
407 if (W == 0) /* offset */
409 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
410 address, opcode, operation, COND(opcode), suffix,
413 instruction->info.load_store.index_mode = 0;
415 else /* pre-indexed */
417 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
418 address, opcode, operation, COND(opcode), suffix,
421 instruction->info.load_store.index_mode = 1;
424 else /* post-indexed */
426 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
427 address, opcode, operation, COND(opcode), suffix,
430 instruction->info.load_store.index_mode = 2;
436 /* Miscellaneous load/store instructions */
437 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
439 uint8_t P, U, I, W, L, S, H;
441 char *operation; /* "LDR" or "STR" */
442 char *suffix; /* "H", "SB", "SH", "D" */
446 P = (opcode & 0x01000000) >> 24;
447 U = (opcode & 0x00800000) >> 23;
448 I = (opcode & 0x00400000) >> 22;
449 W = (opcode & 0x00200000) >> 21;
450 L = (opcode & 0x00100000) >> 20;
451 S = (opcode & 0x00000040) >> 6;
452 H = (opcode & 0x00000020) >> 5;
454 /* target register */
455 Rd = (opcode & 0xf000) >> 12;
458 Rn = (opcode & 0xf0000) >> 16;
460 instruction->info.load_store.Rd = Rd;
461 instruction->info.load_store.Rn = Rn;
462 instruction->info.load_store.U = U;
464 /* determine instruction type and suffix */
472 instruction->type = ARM_LDRSH;
478 instruction->type = ARM_LDRSB;
482 else /* there are no signed stores, so this is used to encode double-register load/stores */
488 instruction->type = ARM_STRD;
493 instruction->type = ARM_LDRD;
503 instruction->type = ARM_LDRH;
508 instruction->type = ARM_STRH;
512 if (I) /* Immediate offset/index (#+-<offset_8>)*/
514 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
515 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
517 instruction->info.load_store.offset_mode = 0;
518 instruction->info.load_store.offset.offset = offset_8;
520 else /* Register offset/index (+-<Rm>) */
524 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
526 instruction->info.load_store.offset_mode = 1;
527 instruction->info.load_store.offset.reg.Rm = Rm;
528 instruction->info.load_store.offset.reg.shift = 0x0;
529 instruction->info.load_store.offset.reg.shift_imm = 0x0;
534 if (W == 0) /* offset */
536 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
537 address, opcode, operation, COND(opcode), suffix,
540 instruction->info.load_store.index_mode = 0;
542 else /* pre-indexed */
544 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
545 address, opcode, operation, COND(opcode), suffix,
548 instruction->info.load_store.index_mode = 1;
551 else /* post-indexed */
553 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
554 address, opcode, operation, COND(opcode), suffix,
557 instruction->info.load_store.index_mode = 2;
563 /* Load/store multiples instructions */
564 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
566 uint8_t P, U, S, W, L, Rn;
567 uint32_t register_list;
568 char *addressing_mode;
575 P = (opcode & 0x01000000) >> 24;
576 U = (opcode & 0x00800000) >> 23;
577 S = (opcode & 0x00400000) >> 22;
578 W = (opcode & 0x00200000) >> 21;
579 L = (opcode & 0x00100000) >> 20;
580 register_list = (opcode & 0xffff);
581 Rn = (opcode & 0xf0000) >> 16;
583 instruction->info.load_store_multiple.Rn = Rn;
584 instruction->info.load_store_multiple.register_list = register_list;
585 instruction->info.load_store_multiple.S = S;
586 instruction->info.load_store_multiple.W = W;
590 instruction->type = ARM_LDM;
595 instruction->type = ARM_STM;
603 instruction->info.load_store_multiple.addressing_mode = 1;
604 addressing_mode = "IB";
608 instruction->info.load_store_multiple.addressing_mode = 3;
609 addressing_mode = "DB";
616 instruction->info.load_store_multiple.addressing_mode = 0;
617 addressing_mode = "IA";
621 instruction->info.load_store_multiple.addressing_mode = 2;
622 addressing_mode = "DA";
626 reg_list_p = reg_list;
627 for (i = 0; i <= 15; i++)
629 if ((register_list >> i) & 1)
634 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
643 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
644 address, opcode, mnemonic, COND(opcode), addressing_mode,
645 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
650 /* Multiplies, extra load/stores */
651 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
653 /* Multiply (accumulate) (long) and Swap/swap byte */
654 if ((opcode & 0x000000f0) == 0x00000090)
656 /* Multiply (accumulate) */
657 if ((opcode & 0x0f800000) == 0x00000000)
659 uint8_t Rm, Rs, Rn, Rd, S;
661 Rs = (opcode & 0xf00) >> 8;
662 Rn = (opcode & 0xf000) >> 12;
663 Rd = (opcode & 0xf0000) >> 16;
664 S = (opcode & 0x00100000) >> 20;
666 /* examine A bit (accumulate) */
667 if (opcode & 0x00200000)
669 instruction->type = ARM_MLA;
670 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
671 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
675 instruction->type = ARM_MUL;
676 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
677 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
683 /* Multiply (accumulate) long */
684 if ((opcode & 0x0f800000) == 0x00800000)
686 char* mnemonic = NULL;
687 uint8_t Rm, Rs, RdHi, RdLow, S;
689 Rs = (opcode & 0xf00) >> 8;
690 RdHi = (opcode & 0xf000) >> 12;
691 RdLow = (opcode & 0xf0000) >> 16;
692 S = (opcode & 0x00100000) >> 20;
694 switch ((opcode & 0x00600000) >> 21)
697 instruction->type = ARM_UMULL;
701 instruction->type = ARM_UMLAL;
705 instruction->type = ARM_SMULL;
709 instruction->type = ARM_SMLAL;
714 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
715 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
716 RdLow, RdHi, Rm, Rs);
722 if ((opcode & 0x0f800000) == 0x01000000)
726 Rd = (opcode & 0xf000) >> 12;
727 Rn = (opcode & 0xf0000) >> 16;
730 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
732 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
733 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
739 return evaluate_misc_load_store(opcode, address, instruction);
742 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
744 int R = (opcode & 0x00400000) >> 22;
745 char *PSR = (R) ? "SPSR" : "CPSR";
747 /* Move register to status register (MSR) */
748 if (opcode & 0x00200000)
750 instruction->type = ARM_MSR;
752 /* immediate variant */
753 if (opcode & 0x02000000)
755 uint8_t immediate = (opcode & 0xff);
756 uint8_t rotate = (opcode & 0xf00);
758 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
759 address, opcode, COND(opcode), PSR,
760 (opcode & 0x10000) ? "c" : "",
761 (opcode & 0x20000) ? "x" : "",
762 (opcode & 0x40000) ? "s" : "",
763 (opcode & 0x80000) ? "f" : "",
764 ror(immediate, (rotate * 2))
767 else /* register variant */
769 uint8_t Rm = opcode & 0xf;
770 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
771 address, opcode, COND(opcode), PSR,
772 (opcode & 0x10000) ? "c" : "",
773 (opcode & 0x20000) ? "x" : "",
774 (opcode & 0x40000) ? "s" : "",
775 (opcode & 0x80000) ? "f" : "",
781 else /* Move status register to register (MRS) */
785 instruction->type = ARM_MRS;
786 Rd = (opcode & 0x0000f000) >> 12;
788 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
789 address, opcode, COND(opcode), Rd, PSR);
795 /* Miscellaneous instructions */
796 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
799 if ((opcode & 0x000000f0) == 0x00000000)
801 evaluate_mrs_msr(opcode, address, instruction);
805 if ((opcode & 0x006000f0) == 0x00200010)
808 instruction->type = ARM_BX;
811 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
812 address, opcode, COND(opcode), Rm);
814 instruction->info.b_bl_bx_blx.reg_operand = Rm;
815 instruction->info.b_bl_bx_blx.target_address = -1;
819 if ((opcode & 0x006000f0) == 0x00600010)
822 instruction->type = ARM_CLZ;
824 Rd = (opcode & 0xf000) >> 12;
826 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
827 address, opcode, COND(opcode), Rd, Rm);
831 if ((opcode & 0x006000f0) == 0x00200030)
834 instruction->type = ARM_BLX;
837 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
838 address, opcode, COND(opcode), Rm);
840 instruction->info.b_bl_bx_blx.reg_operand = Rm;
841 instruction->info.b_bl_bx_blx.target_address = -1;
844 /* Enhanced DSP add/subtracts */
845 if ((opcode & 0x0000000f0) == 0x00000050)
848 char *mnemonic = NULL;
850 Rd = (opcode & 0xf000) >> 12;
851 Rn = (opcode & 0xf0000) >> 16;
853 switch ((opcode & 0x00600000) >> 21)
856 instruction->type = ARM_QADD;
860 instruction->type = ARM_QSUB;
864 instruction->type = ARM_QDADD;
868 instruction->type = ARM_QDSUB;
873 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
874 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
877 /* Software breakpoints */
878 if ((opcode & 0x0000000f0) == 0x00000070)
881 instruction->type = ARM_BKPT;
882 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
884 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
885 address, opcode, immediate);
888 /* Enhanced DSP multiplies */
889 if ((opcode & 0x000000090) == 0x00000080)
891 int x = (opcode & 0x20) >> 5;
892 int y = (opcode & 0x40) >> 6;
895 if ((opcode & 0x00600000) == 0x00000000)
897 uint8_t Rd, Rm, Rs, Rn;
898 instruction->type = ARM_SMLAxy;
899 Rd = (opcode & 0xf0000) >> 16;
901 Rs = (opcode & 0xf00) >> 8;
902 Rn = (opcode & 0xf000) >> 12;
904 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
905 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
910 if ((opcode & 0x00600000) == 0x00400000)
912 uint8_t RdLow, RdHi, Rm, Rs;
913 instruction->type = ARM_SMLAxy;
914 RdHi = (opcode & 0xf0000) >> 16;
915 RdLow = (opcode & 0xf000) >> 12;
917 Rs = (opcode & 0xf00) >> 8;
919 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
920 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
921 RdLow, RdHi, Rm, Rs);
925 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
927 uint8_t Rd, Rm, Rs, Rn;
928 instruction->type = ARM_SMLAWy;
929 Rd = (opcode & 0xf0000) >> 16;
931 Rs = (opcode & 0xf00) >> 8;
932 Rn = (opcode & 0xf000) >> 12;
934 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
935 address, opcode, (y) ? "T" : "B", COND(opcode),
940 if ((opcode & 0x00600000) == 0x00300000)
943 instruction->type = ARM_SMULxy;
944 Rd = (opcode & 0xf0000) >> 16;
946 Rs = (opcode & 0xf00) >> 8;
948 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
949 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
954 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
957 instruction->type = ARM_SMULWy;
958 Rd = (opcode & 0xf0000) >> 16;
960 Rs = (opcode & 0xf00) >> 8;
962 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
963 address, opcode, (y) ? "T" : "B", COND(opcode),
971 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
973 uint8_t I, op, S, Rn, Rd;
974 char *mnemonic = NULL;
975 char shifter_operand[32];
977 I = (opcode & 0x02000000) >> 25;
978 op = (opcode & 0x01e00000) >> 21;
979 S = (opcode & 0x00100000) >> 20;
981 Rd = (opcode & 0xf000) >> 12;
982 Rn = (opcode & 0xf0000) >> 16;
984 instruction->info.data_proc.Rd = Rd;
985 instruction->info.data_proc.Rn = Rn;
986 instruction->info.data_proc.S = S;
991 instruction->type = ARM_AND;
995 instruction->type = ARM_EOR;
999 instruction->type = ARM_SUB;
1003 instruction->type = ARM_RSB;
1007 instruction->type = ARM_ADD;
1011 instruction->type = ARM_ADC;
1015 instruction->type = ARM_SBC;
1019 instruction->type = ARM_RSC;
1023 instruction->type = ARM_TST;
1027 instruction->type = ARM_TEQ;
1031 instruction->type = ARM_CMP;
1035 instruction->type = ARM_CMN;
1039 instruction->type = ARM_ORR;
1043 instruction->type = ARM_MOV;
1047 instruction->type = ARM_BIC;
1051 instruction->type = ARM_MVN;
1056 if (I) /* immediate shifter operand (#<immediate>)*/
1058 uint8_t immed_8 = opcode & 0xff;
1059 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1062 immediate = ror(immed_8, rotate_imm * 2);
1064 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1066 instruction->info.data_proc.variant = 0;
1067 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1069 else /* register-based shifter operand */
1072 shift = (opcode & 0x60) >> 5;
1073 Rm = (opcode & 0xf);
1075 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1078 shift_imm = (opcode & 0xf80) >> 7;
1080 instruction->info.data_proc.variant = 1;
1081 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1082 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1083 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1085 /* LSR encodes a shift by 32 bit as 0x0 */
1086 if ((shift == 0x1) && (shift_imm == 0x0))
1089 /* ASR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x2) && (shift_imm == 0x0))
1093 /* ROR by 32 bit is actually a RRX */
1094 if ((shift == 0x3) && (shift_imm == 0x0))
1097 if ((shift_imm == 0x0) && (shift == 0x0))
1099 snprintf(shifter_operand, 32, "r%i", Rm);
1103 if (shift == 0x0) /* LSL */
1105 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1107 else if (shift == 0x1) /* LSR */
1109 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1111 else if (shift == 0x2) /* ASR */
1113 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1115 else if (shift == 0x3) /* ROR */
1117 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1119 else if (shift == 0x4) /* RRX */
1121 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1125 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1127 uint8_t Rs = (opcode & 0xf00) >> 8;
1129 instruction->info.data_proc.variant = 2;
1130 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1131 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1132 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1134 if (shift == 0x0) /* LSL */
1136 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1138 else if (shift == 0x1) /* LSR */
1140 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1142 else if (shift == 0x2) /* ASR */
1144 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1146 else if (shift == 0x3) /* ROR */
1148 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1153 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1155 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1156 address, opcode, mnemonic, COND(opcode),
1157 (S) ? "S" : "", Rd, Rn, shifter_operand);
1159 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1161 if (opcode==0xe1a00000) /* print MOV r0,r0 as NOP */
1162 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1164 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1165 address, opcode, mnemonic, COND(opcode),
1166 (S) ? "S" : "", Rd, shifter_operand);
1168 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1170 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1171 address, opcode, mnemonic, COND(opcode),
1172 Rn, shifter_operand);
1178 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1180 /* clear fields, to avoid confusion */
1181 memset(instruction, 0, sizeof(arm_instruction_t));
1182 instruction->opcode = opcode;
1184 /* catch opcodes with condition field [31:28] = b1111 */
1185 if ((opcode & 0xf0000000) == 0xf0000000)
1187 /* Undefined instruction (or ARMv5E cache preload PLD) */
1188 if ((opcode & 0x08000000) == 0x00000000)
1189 return evaluate_pld(opcode, address, instruction);
1191 /* Undefined instruction */
1192 if ((opcode & 0x0e000000) == 0x08000000)
1194 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1195 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1199 /* Branch and branch with link and change to Thumb */
1200 if ((opcode & 0x0e000000) == 0x0a000000)
1201 return evaluate_blx_imm(opcode, address, instruction);
1203 /* Extended coprocessor opcode space (ARMv5 and higher )*/
1204 /* Coprocessor load/store and double register transfers */
1205 if ((opcode & 0x0e000000) == 0x0c000000)
1206 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1208 /* Coprocessor data processing */
1209 if ((opcode & 0x0f000100) == 0x0c000000)
1210 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1212 /* Coprocessor register transfers */
1213 if ((opcode & 0x0f000010) == 0x0c000010)
1214 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1216 /* Undefined instruction */
1217 if ((opcode & 0x0f000000) == 0x0f000000)
1219 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1220 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1225 /* catch opcodes with [27:25] = b000 */
1226 if ((opcode & 0x0e000000) == 0x00000000)
1228 /* Multiplies, extra load/stores */
1229 if ((opcode & 0x00000090) == 0x00000090)
1230 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1232 /* Miscellaneous instructions */
1233 if ((opcode & 0x0f900000) == 0x01000000)
1234 return evaluate_misc_instr(opcode, address, instruction);
1236 return evaluate_data_proc(opcode, address, instruction);
1239 /* catch opcodes with [27:25] = b001 */
1240 if ((opcode & 0x0e000000) == 0x02000000)
1242 /* Undefined instruction */
1243 if ((opcode & 0x0fb00000) == 0x03000000)
1245 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1246 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1250 /* Move immediate to status register */
1251 if ((opcode & 0x0fb00000) == 0x03200000)
1252 return evaluate_mrs_msr(opcode, address, instruction);
1254 return evaluate_data_proc(opcode, address, instruction);
1258 /* catch opcodes with [27:25] = b010 */
1259 if ((opcode & 0x0e000000) == 0x04000000)
1261 /* Load/store immediate offset */
1262 return evaluate_load_store(opcode, address, instruction);
1265 /* catch opcodes with [27:25] = b011 */
1266 if ((opcode & 0x0e000000) == 0x06000000)
1268 /* Undefined instruction */
1269 if ((opcode & 0x00000010) == 0x00000010)
1271 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1272 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1276 /* Load/store register offset */
1277 return evaluate_load_store(opcode, address, instruction);
1281 /* catch opcodes with [27:25] = b100 */
1282 if ((opcode & 0x0e000000) == 0x08000000)
1284 /* Load/store multiple */
1285 return evaluate_ldm_stm(opcode, address, instruction);
1288 /* catch opcodes with [27:25] = b101 */
1289 if ((opcode & 0x0e000000) == 0x0a000000)
1291 /* Branch and branch with link */
1292 return evaluate_b_bl(opcode, address, instruction);
1295 /* catch opcodes with [27:25] = b110 */
1296 if ((opcode & 0x0e000000) == 0x0a000000)
1298 /* Coprocessor load/store and double register transfers */
1299 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1302 /* catch opcodes with [27:25] = b111 */
1303 if ((opcode & 0x0e000000) == 0x0e000000)
1305 /* Software interrupt */
1306 if ((opcode & 0x0f000000) == 0x0f000000)
1307 return evaluate_swi(opcode, address, instruction);
1309 /* Coprocessor data processing */
1310 if ((opcode & 0x0f000010) == 0x0e000000)
1311 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1313 /* Coprocessor register transfers */
1314 if ((opcode & 0x0f000010) == 0x0e000010)
1315 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1318 LOG_ERROR("should never reach this point");
1322 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1324 uint32_t offset = opcode & 0x7ff;
1325 uint32_t opc = (opcode >> 11) & 0x3;
1326 uint32_t target_address;
1327 char *mnemonic = NULL;
1329 /* sign extend 11-bit offset */
1330 if (((opc==0) || (opc==2)) && (offset & 0x00000400))
1331 offset = 0xfffff800 | offset;
1333 target_address = address + 4 + (offset<<1);
1337 /* unconditional branch */
1339 instruction->type = ARM_B;
1344 instruction->type = ARM_BLX;
1349 instruction->type = ARM_UNKNOWN_INSTUCTION;
1350 mnemonic = "prefix";
1351 target_address = offset<<12;
1355 instruction->type = ARM_BL;
1359 /* TODO: deals correctly with dual opcodes BL/BLX ... */
1361 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s 0x%8.8" PRIx32 , address, opcode,mnemonic, target_address);
1363 instruction->info.b_bl_bx_blx.reg_operand = -1;
1364 instruction->info.b_bl_bx_blx.target_address = target_address;
1369 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1371 uint8_t Rd = (opcode >> 0) & 0x7;
1372 uint8_t Rn = (opcode >> 3) & 0x7;
1373 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1374 uint32_t opc = opcode & (1<<9);
1375 uint32_t reg_imm = opcode & (1<<10);
1380 instruction->type = ARM_SUB;
1385 instruction->type = ARM_ADD;
1389 instruction->info.data_proc.Rd = Rd;
1390 instruction->info.data_proc.Rn = Rn;
1391 instruction->info.data_proc.S = 1;
1395 instruction->info.data_proc.variant = 0; /*immediate*/
1396 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1397 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #%d",
1398 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1402 instruction->info.data_proc.variant = 1; /*immediate shift*/
1403 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1404 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, r%i",
1405 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1411 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1413 uint8_t Rd = (opcode >> 0) & 0x7;
1414 uint8_t Rm = (opcode >> 3) & 0x7;
1415 uint8_t imm = (opcode >> 6) & 0x1f;
1416 uint8_t opc = (opcode >> 11) & 0x3;
1417 char *mnemonic = NULL;
1422 instruction->type = ARM_MOV;
1424 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1427 instruction->type = ARM_MOV;
1429 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1432 instruction->type = ARM_MOV;
1434 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1438 if ((imm==0) && (opc != 0))
1441 instruction->info.data_proc.Rd = Rd;
1442 instruction->info.data_proc.Rn = -1;
1443 instruction->info.data_proc.S = 1;
1445 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1446 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1449 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #0x%02x" ,
1450 address, opcode, mnemonic, Rd, Rm, imm);
1455 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1457 uint8_t imm = opcode & 0xff;
1458 uint8_t Rd = (opcode >> 8) & 0x7;
1459 uint32_t opc = (opcode >> 11) & 0x3;
1460 char *mnemonic = NULL;
1462 instruction->info.data_proc.Rd = Rd;
1463 instruction->info.data_proc.Rn = Rd;
1464 instruction->info.data_proc.S = 1;
1465 instruction->info.data_proc.variant = 0; /*immediate*/
1466 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1471 instruction->type = ARM_MOV;
1473 instruction->info.data_proc.Rn = -1;
1476 instruction->type = ARM_CMP;
1478 instruction->info.data_proc.Rd = -1;
1481 instruction->type = ARM_ADD;
1485 instruction->type = ARM_SUB;
1490 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, #0x%02x" ,
1491 address, opcode, mnemonic, Rd, imm);
1496 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1498 uint8_t high_reg, op, Rm, Rd,H1,H2;
1499 char *mnemonic = NULL;
1501 high_reg = (opcode & 0x0400) >> 10;
1502 op = (opcode & 0x03C0) >> 6;
1504 Rd = (opcode & 0x0007);
1505 Rm = (opcode & 0x0038) >> 3;
1506 H1 = (opcode & 0x0080) >> 7;
1507 H2 = (opcode & 0x0040) >> 6;
1509 instruction->info.data_proc.Rd = Rd;
1510 instruction->info.data_proc.Rn = Rd;
1511 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1512 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1513 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1524 instruction->type = ARM_ADD;
1528 instruction->type = ARM_CMP;
1532 instruction->type = ARM_MOV;
1536 if ((opcode & 0x7) == 0x0)
1538 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1541 instruction->type = ARM_BLX;
1542 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBLX r%i", address, opcode, Rm);
1546 instruction->type = ARM_BX;
1547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBX r%i", address, opcode, Rm);
1552 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1553 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1564 instruction->type = ARM_AND;
1568 instruction->type = ARM_EOR;
1572 instruction->type = ARM_MOV;
1574 instruction->info.data_proc.variant = 2 /*register shift*/;
1575 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1576 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1577 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1580 instruction->type = ARM_MOV;
1582 instruction->info.data_proc.variant = 2 /*register shift*/;
1583 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1584 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1585 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1588 instruction->type = ARM_MOV;
1590 instruction->info.data_proc.variant = 2 /*register shift*/;
1591 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1592 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1593 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1596 instruction->type = ARM_ADC;
1600 instruction->type = ARM_SBC;
1604 instruction->type = ARM_MOV;
1606 instruction->info.data_proc.variant = 2 /*register shift*/;
1607 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1608 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1609 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1612 instruction->type = ARM_TST;
1616 instruction->type = ARM_RSB;
1618 instruction->info.data_proc.variant = 0 /*immediate*/;
1619 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1620 instruction->info.data_proc.Rn = Rm;
1623 instruction->type = ARM_CMP;
1627 instruction->type = ARM_CMN;
1631 instruction->type = ARM_ORR;
1635 instruction->type = ARM_MUL;
1639 instruction->type = ARM_BIC;
1643 instruction->type = ARM_MVN;
1649 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i",
1650 address, opcode, mnemonic, Rd, Rm);
1655 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1658 uint8_t Rd = (opcode >> 8) & 0x7;
1660 instruction->type = ARM_LDR;
1661 immediate = opcode & 0x000000ff;
1663 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tLDR r%i, [PC, #0x%" PRIx32 "]", address, opcode, Rd, immediate*4);
1665 instruction->info.load_store.Rd = Rd;
1666 instruction->info.load_store.Rn = 15 /*PC*/;
1667 instruction->info.load_store.index_mode = 0; /*offset*/
1668 instruction->info.load_store.offset_mode = 0; /*immediate*/
1669 instruction->info.load_store.offset.offset = immediate*4;
1674 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1676 uint8_t Rd = (opcode >> 0) & 0x7;
1677 uint8_t Rn = (opcode >> 3) & 0x7;
1678 uint8_t Rm = (opcode >> 6) & 0x7;
1679 uint8_t opc = (opcode >> 9) & 0x7;
1680 char *mnemonic = NULL;
1685 instruction->type = ARM_STR;
1689 instruction->type = ARM_STRH;
1693 instruction->type = ARM_STRB;
1697 instruction->type = ARM_LDRSB;
1701 instruction->type = ARM_LDR;
1705 instruction->type = ARM_LDRH;
1709 instruction->type = ARM_LDRB;
1713 instruction->type = ARM_LDRSH;
1718 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);
1720 instruction->info.load_store.Rd = Rd;
1721 instruction->info.load_store.Rn = Rn;
1722 instruction->info.load_store.index_mode = 0; /*offset*/
1723 instruction->info.load_store.offset_mode = 1; /*register*/
1724 instruction->info.load_store.offset.reg.Rm = Rm;
1729 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1731 uint32_t offset = (opcode >> 6) & 0x1f;
1732 uint8_t Rd = (opcode >> 0) & 0x7;
1733 uint8_t Rn = (opcode >> 3) & 0x7;
1734 uint32_t L = opcode & (1<<11);
1735 uint32_t B = opcode & (1<<12);
1742 instruction->type = ARM_LDR;
1747 instruction->type = ARM_STR;
1751 if ((opcode&0xF000)==0x8000)
1762 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);
1764 instruction->info.load_store.Rd = Rd;
1765 instruction->info.load_store.Rn = Rn;
1766 instruction->info.load_store.index_mode = 0; /*offset*/
1767 instruction->info.load_store.offset_mode = 0; /*immediate*/
1768 instruction->info.load_store.offset.offset = offset<<shift;
1773 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1775 uint32_t offset = opcode & 0xff;
1776 uint8_t Rd = (opcode >> 8) & 0x7;
1777 uint32_t L = opcode & (1<<11);
1782 instruction->type = ARM_LDR;
1787 instruction->type = ARM_STR;
1791 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, [SP, #0x%" PRIx32 "]", address, opcode, mnemonic, Rd, offset*4);
1793 instruction->info.load_store.Rd = Rd;
1794 instruction->info.load_store.Rn = 13 /*SP*/;
1795 instruction->info.load_store.index_mode = 0; /*offset*/
1796 instruction->info.load_store.offset_mode = 0; /*immediate*/
1797 instruction->info.load_store.offset.offset = offset*4;
1802 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1804 uint32_t imm = opcode & 0xff;
1805 uint8_t Rd = (opcode >> 8) & 0x7;
1807 uint32_t SP = opcode & (1<<11);
1810 instruction->type = ARM_ADD;
1823 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tADD r%i, %s, #0x%" PRIx32 "", address, opcode, Rd,reg_name, imm*4);
1825 instruction->info.data_proc.variant = 0 /* immediate */;
1826 instruction->info.data_proc.Rd = Rd;
1827 instruction->info.data_proc.Rn = Rn;
1828 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1833 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1835 uint32_t imm = opcode & 0x7f;
1836 uint8_t opc = opcode & (1<<7);
1842 instruction->type = ARM_SUB;
1847 instruction->type = ARM_ADD;
1851 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s SP, #0x%" PRIx32 "", address, opcode, mnemonic, imm*4);
1853 instruction->info.data_proc.variant = 0 /* immediate */;
1854 instruction->info.data_proc.Rd = 13 /*SP*/;
1855 instruction->info.data_proc.Rn = 13 /*SP*/;
1856 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1861 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1863 uint32_t imm = opcode & 0xff;
1865 instruction->type = ARM_BKPT;
1867 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBKPT 0x%02" PRIx32 "", address, opcode, imm);
1872 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1874 uint32_t reg_list = opcode & 0xff;
1875 uint32_t L = opcode & (1<<11);
1876 uint32_t R = opcode & (1<<8);
1877 uint8_t Rn = (opcode >> 8) & 7;
1878 uint8_t addr_mode = 0 /* IA */;
1882 char ptr_name[7] = "";
1885 if ((opcode & 0xf000) == 0xc000)
1886 { /* generic load/store multiple */
1889 instruction->type = ARM_LDM;
1894 instruction->type = ARM_STM;
1897 snprintf(ptr_name,7,"r%i!, ",Rn);
1904 instruction->type = ARM_LDM;
1907 reg_list |= (1<<15) /*PC*/;
1911 instruction->type = ARM_STM;
1913 addr_mode = 3; /*DB*/
1915 reg_list |= (1<<14) /*LR*/;
1919 reg_names_p = reg_names;
1920 for (i = 0; i <= 15; i++)
1922 if (reg_list & (1<<i))
1923 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1925 if (reg_names_p>reg_names)
1926 reg_names_p[-2] = '\0';
1927 else /* invalid op : no registers */
1928 reg_names[0] = '\0';
1930 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s %s{%s}", address, opcode, mnemonic, ptr_name,reg_names);
1932 instruction->info.load_store_multiple.register_list = reg_list;
1933 instruction->info.load_store_multiple.Rn = Rn;
1934 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1939 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1941 uint32_t offset = opcode & 0xff;
1942 uint8_t cond = (opcode >> 8) & 0xf;
1943 uint32_t target_address;
1947 instruction->type = ARM_SWI;
1948 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tSWI 0x%02" PRIx32 , address, opcode, offset);
1951 else if (cond == 0xe)
1953 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1954 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1958 /* sign extend 8-bit offset */
1959 if (offset & 0x00000080)
1960 offset = 0xffffff00 | offset;
1962 target_address = address + 4 + (offset<<1);
1964 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tB%s 0x%8.8" PRIx32 , address, opcode,
1965 arm_condition_strings[cond], target_address);
1967 instruction->type = ARM_B;
1968 instruction->info.b_bl_bx_blx.reg_operand = -1;
1969 instruction->info.b_bl_bx_blx.target_address = target_address;
1974 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1976 /* clear fields, to avoid confusion */
1977 memset(instruction, 0, sizeof(arm_instruction_t));
1978 instruction->opcode = opcode;
1980 if ((opcode & 0xe000) == 0x0000)
1982 /* add/substract register or immediate */
1983 if ((opcode & 0x1800) == 0x1800)
1984 return evaluate_add_sub_thumb(opcode, address, instruction);
1985 /* shift by immediate */
1987 return evaluate_shift_imm_thumb(opcode, address, instruction);
1990 /* Add/substract/compare/move immediate */
1991 if ((opcode & 0xe000) == 0x2000)
1993 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
1996 /* Data processing instructions */
1997 if ((opcode & 0xf800) == 0x4000)
1999 return evaluate_data_proc_thumb(opcode, address, instruction);
2002 /* Load from literal pool */
2003 if ((opcode & 0xf800) == 0x4800)
2005 return evaluate_load_literal_thumb(opcode, address, instruction);
2008 /* Load/Store register offset */
2009 if ((opcode & 0xf000) == 0x5000)
2011 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2014 /* Load/Store immediate offset */
2015 if (((opcode & 0xe000) == 0x6000)
2016 ||((opcode & 0xf000) == 0x8000))
2018 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2021 /* Load/Store from/to stack */
2022 if ((opcode & 0xf000) == 0x9000)
2024 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2028 if ((opcode & 0xf000) == 0xa000)
2030 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2034 if ((opcode & 0xf000) == 0xb000)
2036 if ((opcode & 0x0f00) == 0x0000)
2037 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2038 else if ((opcode & 0x0f00) == 0x0e00)
2039 return evaluate_breakpoint_thumb(opcode, address, instruction);
2040 else if ((opcode & 0x0600) == 0x0400) /* push pop */
2041 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2044 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2045 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
2050 /* Load/Store multiple */
2051 if ((opcode & 0xf000) == 0xc000)
2053 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2056 /* Conditional branch + SWI */
2057 if ((opcode & 0xf000) == 0xd000)
2059 return evaluate_cond_branch_thumb(opcode, address, instruction);
2062 if ((opcode & 0xe000) == 0xe000)
2064 /* Undefined instructions */
2065 if ((opcode & 0xf801) == 0xe801)
2067 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2068 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
2072 { /* Branch to offset */
2073 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2077 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2081 int arm_access_size(arm_instruction_t *instruction)
2083 if ((instruction->type == ARM_LDRB)
2084 || (instruction->type == ARM_LDRBT)
2085 || (instruction->type == ARM_LDRSB)
2086 || (instruction->type == ARM_STRB)
2087 || (instruction->type == ARM_STRBT))
2091 else if ((instruction->type == ARM_LDRH)
2092 || (instruction->type == ARM_LDRSH)
2093 || (instruction->type == ARM_STRH))
2097 else if ((instruction->type == ARM_LDR)
2098 || (instruction->type == ARM_LDRT)
2099 || (instruction->type == ARM_STR)
2100 || (instruction->type == ARM_STRT))
2104 else if ((instruction->type == ARM_LDRD)
2105 || (instruction->type == ARM_STRD))
2111 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);