1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include "arm_disassembler.h"
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings[] =
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value, int places)
39 return (value >> places) | (value << (32 - places));
42 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
45 if ((opcode & 0x0d70f0000) == 0x0550f000)
47 instruction->type = ARM_PLD;
49 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
55 instruction->type = ARM_UNDEFINED_INSTRUCTION;
59 LOG_ERROR("should never reach this point");
63 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
65 instruction->type = ARM_SWI;
67 snprintf(instruction->text, 128,
68 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
69 address, opcode, (opcode & 0xffffff));
74 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
78 uint32_t target_address;
80 instruction->type = ARM_BLX;
81 immediate = opcode & 0x00ffffff;
83 /* sign extend 24-bit immediate */
84 if (immediate & 0x00800000)
85 offset = 0xff000000 | immediate;
89 /* shift two bits left */
92 /* odd/event halfword */
93 if (opcode & 0x01000000)
96 target_address = address + 8 + offset;
98 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
100 instruction->info.b_bl_bx_blx.reg_operand = -1;
101 instruction->info.b_bl_bx_blx.target_address = target_address;
106 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
111 uint32_t target_address;
113 immediate = opcode & 0x00ffffff;
114 L = (opcode & 0x01000000) >> 24;
116 /* sign extend 24-bit immediate */
117 if (immediate & 0x00800000)
118 offset = 0xff000000 | immediate;
122 /* shift two bits left */
125 target_address = address + 8 + offset;
128 instruction->type = ARM_BL;
130 instruction->type = ARM_B;
132 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
133 (L) ? "L" : "", COND(opcode), target_address);
135 instruction->info.b_bl_bx_blx.reg_operand = -1;
136 instruction->info.b_bl_bx_blx.target_address = target_address;
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
145 uint8_t cp_num = (opcode & 0xf00) >> 8;
148 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
150 uint8_t cp_opcode, Rd, Rn, CRm;
153 cp_opcode = (opcode & 0xf0) >> 4;
154 Rd = (opcode & 0xf000) >> 12;
155 Rn = (opcode & 0xf0000) >> 16;
156 CRm = (opcode & 0xf);
159 if ((opcode & 0x0ff00000) == 0x0c400000)
161 instruction->type = ARM_MCRR;
166 if ((opcode & 0x0ff00000) == 0x0c500000)
168 instruction->type = ARM_MRRC;
172 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
173 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
175 else /* LDC or STC */
177 uint8_t CRd, Rn, offset;
180 char addressing_mode[32];
182 CRd = (opcode & 0xf000) >> 12;
183 Rn = (opcode & 0xf0000) >> 16;
184 offset = (opcode & 0xff);
187 if (opcode & 0x00100000)
189 instruction->type = ARM_LDC;
194 instruction->type = ARM_STC;
198 U = (opcode & 0x00800000) >> 23;
199 N = (opcode & 0x00400000) >> 22;
201 /* addressing modes */
202 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
204 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
206 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
208 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
212 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
214 cp_num, CRd, addressing_mode);
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
227 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
229 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
230 cp_num = (opcode & 0xf00) >> 8;
231 CRd_Rd = (opcode & 0xf000) >> 12;
232 CRn = (opcode & 0xf0000) >> 16;
233 CRm = (opcode & 0xf);
234 opcode_2 = (opcode & 0xe0) >> 5;
237 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
239 if (opcode & 0x00100000) /* bit 20 set -> MRC */
241 instruction->type = ARM_MRC;
244 else /* bit 20 not set -> MCR */
246 instruction->type = ARM_MCR;
250 opcode_1 = (opcode & 0x00e00000) >> 21;
252 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
253 address, opcode, mnemonic, cond,
254 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
256 else /* bit 4 not set -> CDP */
258 instruction->type = ARM_CDP;
261 opcode_1 = (opcode & 0x00f00000) >> 20;
263 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
264 address, opcode, mnemonic, cond,
265 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
274 uint8_t I, P, U, B, W, L;
276 char *operation; /* "LDR" or "STR" */
277 char *suffix; /* "", "B", "T", "BT" */
281 I = (opcode & 0x02000000) >> 25;
282 P = (opcode & 0x01000000) >> 24;
283 U = (opcode & 0x00800000) >> 23;
284 B = (opcode & 0x00400000) >> 22;
285 W = (opcode & 0x00200000) >> 21;
286 L = (opcode & 0x00100000) >> 20;
288 /* target register */
289 Rd = (opcode & 0xf000) >> 12;
292 Rn = (opcode & 0xf0000) >> 16;
294 instruction->info.load_store.Rd = Rd;
295 instruction->info.load_store.Rn = Rn;
296 instruction->info.load_store.U = U;
298 /* determine operation */
304 /* determine instruction type and suffix */
307 if ((P == 0) && (W == 1))
310 instruction->type = ARM_LDRBT;
312 instruction->type = ARM_STRBT;
318 instruction->type = ARM_LDRB;
320 instruction->type = ARM_STRB;
326 if ((P == 0) && (W == 1))
329 instruction->type = ARM_LDRT;
331 instruction->type = ARM_STRT;
337 instruction->type = ARM_LDR;
339 instruction->type = ARM_STR;
344 if (!I) /* #+-<offset_12> */
346 uint32_t offset_12 = (opcode & 0xfff);
348 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
350 snprintf(offset, 32, "%s", "");
352 instruction->info.load_store.offset_mode = 0;
353 instruction->info.load_store.offset.offset = offset_12;
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
357 uint8_t shift_imm, shift;
360 shift_imm = (opcode & 0xf80) >> 7;
361 shift = (opcode & 0x60) >> 5;
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift == 0x1) && (shift_imm == 0x0))
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift == 0x2) && (shift_imm == 0x0))
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift == 0x3) && (shift_imm == 0x0))
376 instruction->info.load_store.offset_mode = 1;
377 instruction->info.load_store.offset.reg.Rm = Rm;
378 instruction->info.load_store.offset.reg.shift = shift;
379 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
381 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
383 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
390 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
393 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
396 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
399 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
402 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
410 if (W == 0) /* offset */
412 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
413 address, opcode, operation, COND(opcode), suffix,
416 instruction->info.load_store.index_mode = 0;
418 else /* pre-indexed */
420 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
421 address, opcode, operation, COND(opcode), suffix,
424 instruction->info.load_store.index_mode = 1;
427 else /* post-indexed */
429 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
430 address, opcode, operation, COND(opcode), suffix,
433 instruction->info.load_store.index_mode = 2;
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
442 uint8_t P, U, I, W, L, S, H;
444 char *operation; /* "LDR" or "STR" */
445 char *suffix; /* "H", "SB", "SH", "D" */
449 P = (opcode & 0x01000000) >> 24;
450 U = (opcode & 0x00800000) >> 23;
451 I = (opcode & 0x00400000) >> 22;
452 W = (opcode & 0x00200000) >> 21;
453 L = (opcode & 0x00100000) >> 20;
454 S = (opcode & 0x00000040) >> 6;
455 H = (opcode & 0x00000020) >> 5;
457 /* target register */
458 Rd = (opcode & 0xf000) >> 12;
461 Rn = (opcode & 0xf0000) >> 16;
463 instruction->info.load_store.Rd = Rd;
464 instruction->info.load_store.Rn = Rn;
465 instruction->info.load_store.U = U;
467 /* determine instruction type and suffix */
475 instruction->type = ARM_LDRSH;
481 instruction->type = ARM_LDRSB;
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
491 instruction->type = ARM_STRD;
496 instruction->type = ARM_LDRD;
506 instruction->type = ARM_LDRH;
511 instruction->type = ARM_STRH;
515 if (I) /* Immediate offset/index (#+-<offset_8>)*/
517 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
518 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
520 instruction->info.load_store.offset_mode = 0;
521 instruction->info.load_store.offset.offset = offset_8;
523 else /* Register offset/index (+-<Rm>) */
527 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
529 instruction->info.load_store.offset_mode = 1;
530 instruction->info.load_store.offset.reg.Rm = Rm;
531 instruction->info.load_store.offset.reg.shift = 0x0;
532 instruction->info.load_store.offset.reg.shift_imm = 0x0;
537 if (W == 0) /* offset */
539 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
540 address, opcode, operation, COND(opcode), suffix,
543 instruction->info.load_store.index_mode = 0;
545 else /* pre-indexed */
547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
548 address, opcode, operation, COND(opcode), suffix,
551 instruction->info.load_store.index_mode = 1;
554 else /* post-indexed */
556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
557 address, opcode, operation, COND(opcode), suffix,
560 instruction->info.load_store.index_mode = 2;
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
569 uint8_t P, U, S, W, L, Rn;
570 uint32_t register_list;
571 char *addressing_mode;
578 P = (opcode & 0x01000000) >> 24;
579 U = (opcode & 0x00800000) >> 23;
580 S = (opcode & 0x00400000) >> 22;
581 W = (opcode & 0x00200000) >> 21;
582 L = (opcode & 0x00100000) >> 20;
583 register_list = (opcode & 0xffff);
584 Rn = (opcode & 0xf0000) >> 16;
586 instruction->info.load_store_multiple.Rn = Rn;
587 instruction->info.load_store_multiple.register_list = register_list;
588 instruction->info.load_store_multiple.S = S;
589 instruction->info.load_store_multiple.W = W;
593 instruction->type = ARM_LDM;
598 instruction->type = ARM_STM;
606 instruction->info.load_store_multiple.addressing_mode = 1;
607 addressing_mode = "IB";
611 instruction->info.load_store_multiple.addressing_mode = 3;
612 addressing_mode = "DB";
619 instruction->info.load_store_multiple.addressing_mode = 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode = "";
625 instruction->info.load_store_multiple.addressing_mode = 2;
626 addressing_mode = "DA";
630 reg_list_p = reg_list;
631 for (i = 0; i <= 15; i++)
633 if ((register_list >> i) & 1)
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
642 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
647 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
648 address, opcode, mnemonic, COND(opcode), addressing_mode,
649 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode & 0x000000f0) == 0x00000090)
660 /* Multiply (accumulate) */
661 if ((opcode & 0x0f800000) == 0x00000000)
663 uint8_t Rm, Rs, Rn, Rd, S;
665 Rs = (opcode & 0xf00) >> 8;
666 Rn = (opcode & 0xf000) >> 12;
667 Rd = (opcode & 0xf0000) >> 16;
668 S = (opcode & 0x00100000) >> 20;
670 /* examine A bit (accumulate) */
671 if (opcode & 0x00200000)
673 instruction->type = ARM_MLA;
674 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
675 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
679 instruction->type = ARM_MUL;
680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
681 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
687 /* Multiply (accumulate) long */
688 if ((opcode & 0x0f800000) == 0x00800000)
690 char* mnemonic = NULL;
691 uint8_t Rm, Rs, RdHi, RdLow, S;
693 Rs = (opcode & 0xf00) >> 8;
694 RdHi = (opcode & 0xf000) >> 12;
695 RdLow = (opcode & 0xf0000) >> 16;
696 S = (opcode & 0x00100000) >> 20;
698 switch ((opcode & 0x00600000) >> 21)
701 instruction->type = ARM_UMULL;
705 instruction->type = ARM_UMLAL;
709 instruction->type = ARM_SMULL;
713 instruction->type = ARM_SMLAL;
718 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
719 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
720 RdLow, RdHi, Rm, Rs);
726 if ((opcode & 0x0f800000) == 0x01000000)
730 Rd = (opcode & 0xf000) >> 12;
731 Rn = (opcode & 0xf0000) >> 16;
734 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
736 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
737 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
743 return evaluate_misc_load_store(opcode, address, instruction);
746 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
748 int R = (opcode & 0x00400000) >> 22;
749 char *PSR = (R) ? "SPSR" : "CPSR";
751 /* Move register to status register (MSR) */
752 if (opcode & 0x00200000)
754 instruction->type = ARM_MSR;
756 /* immediate variant */
757 if (opcode & 0x02000000)
759 uint8_t immediate = (opcode & 0xff);
760 uint8_t rotate = (opcode & 0xf00);
762 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
763 address, opcode, COND(opcode), PSR,
764 (opcode & 0x10000) ? "c" : "",
765 (opcode & 0x20000) ? "x" : "",
766 (opcode & 0x40000) ? "s" : "",
767 (opcode & 0x80000) ? "f" : "",
768 ror(immediate, (rotate * 2))
771 else /* register variant */
773 uint8_t Rm = opcode & 0xf;
774 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
775 address, opcode, COND(opcode), PSR,
776 (opcode & 0x10000) ? "c" : "",
777 (opcode & 0x20000) ? "x" : "",
778 (opcode & 0x40000) ? "s" : "",
779 (opcode & 0x80000) ? "f" : "",
785 else /* Move status register to register (MRS) */
789 instruction->type = ARM_MRS;
790 Rd = (opcode & 0x0000f000) >> 12;
792 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
793 address, opcode, COND(opcode), Rd, PSR);
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
803 if ((opcode & 0x000000f0) == 0x00000000)
805 evaluate_mrs_msr(opcode, address, instruction);
809 if ((opcode & 0x006000f0) == 0x00200010)
812 instruction->type = ARM_BX;
815 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
816 address, opcode, COND(opcode), Rm);
818 instruction->info.b_bl_bx_blx.reg_operand = Rm;
819 instruction->info.b_bl_bx_blx.target_address = -1;
823 if ((opcode & 0x006000f0) == 0x00600010)
826 instruction->type = ARM_CLZ;
828 Rd = (opcode & 0xf000) >> 12;
830 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
831 address, opcode, COND(opcode), Rd, Rm);
835 if ((opcode & 0x006000f0) == 0x00200030)
838 instruction->type = ARM_BLX;
841 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
842 address, opcode, COND(opcode), Rm);
844 instruction->info.b_bl_bx_blx.reg_operand = Rm;
845 instruction->info.b_bl_bx_blx.target_address = -1;
848 /* Enhanced DSP add/subtracts */
849 if ((opcode & 0x0000000f0) == 0x00000050)
852 char *mnemonic = NULL;
854 Rd = (opcode & 0xf000) >> 12;
855 Rn = (opcode & 0xf0000) >> 16;
857 switch ((opcode & 0x00600000) >> 21)
860 instruction->type = ARM_QADD;
864 instruction->type = ARM_QSUB;
868 instruction->type = ARM_QDADD;
872 instruction->type = ARM_QDSUB;
877 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
878 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
881 /* Software breakpoints */
882 if ((opcode & 0x0000000f0) == 0x00000070)
885 instruction->type = ARM_BKPT;
886 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
888 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
889 address, opcode, immediate);
892 /* Enhanced DSP multiplies */
893 if ((opcode & 0x000000090) == 0x00000080)
895 int x = (opcode & 0x20) >> 5;
896 int y = (opcode & 0x40) >> 6;
899 if ((opcode & 0x00600000) == 0x00000000)
901 uint8_t Rd, Rm, Rs, Rn;
902 instruction->type = ARM_SMLAxy;
903 Rd = (opcode & 0xf0000) >> 16;
905 Rs = (opcode & 0xf00) >> 8;
906 Rn = (opcode & 0xf000) >> 12;
908 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
914 if ((opcode & 0x00600000) == 0x00400000)
916 uint8_t RdLow, RdHi, Rm, Rs;
917 instruction->type = ARM_SMLAxy;
918 RdHi = (opcode & 0xf0000) >> 16;
919 RdLow = (opcode & 0xf000) >> 12;
921 Rs = (opcode & 0xf00) >> 8;
923 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
925 RdLow, RdHi, Rm, Rs);
929 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
931 uint8_t Rd, Rm, Rs, Rn;
932 instruction->type = ARM_SMLAWy;
933 Rd = (opcode & 0xf0000) >> 16;
935 Rs = (opcode & 0xf00) >> 8;
936 Rn = (opcode & 0xf000) >> 12;
938 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address, opcode, (y) ? "T" : "B", COND(opcode),
944 if ((opcode & 0x00600000) == 0x00300000)
947 instruction->type = ARM_SMULxy;
948 Rd = (opcode & 0xf0000) >> 16;
950 Rs = (opcode & 0xf00) >> 8;
952 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
953 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
958 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
961 instruction->type = ARM_SMULWy;
962 Rd = (opcode & 0xf0000) >> 16;
964 Rs = (opcode & 0xf00) >> 8;
966 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
967 address, opcode, (y) ? "T" : "B", COND(opcode),
975 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
977 uint8_t I, op, S, Rn, Rd;
978 char *mnemonic = NULL;
979 char shifter_operand[32];
981 I = (opcode & 0x02000000) >> 25;
982 op = (opcode & 0x01e00000) >> 21;
983 S = (opcode & 0x00100000) >> 20;
985 Rd = (opcode & 0xf000) >> 12;
986 Rn = (opcode & 0xf0000) >> 16;
988 instruction->info.data_proc.Rd = Rd;
989 instruction->info.data_proc.Rn = Rn;
990 instruction->info.data_proc.S = S;
995 instruction->type = ARM_AND;
999 instruction->type = ARM_EOR;
1003 instruction->type = ARM_SUB;
1007 instruction->type = ARM_RSB;
1011 instruction->type = ARM_ADD;
1015 instruction->type = ARM_ADC;
1019 instruction->type = ARM_SBC;
1023 instruction->type = ARM_RSC;
1027 instruction->type = ARM_TST;
1031 instruction->type = ARM_TEQ;
1035 instruction->type = ARM_CMP;
1039 instruction->type = ARM_CMN;
1043 instruction->type = ARM_ORR;
1047 instruction->type = ARM_MOV;
1051 instruction->type = ARM_BIC;
1055 instruction->type = ARM_MVN;
1060 if (I) /* immediate shifter operand (#<immediate>)*/
1062 uint8_t immed_8 = opcode & 0xff;
1063 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1066 immediate = ror(immed_8, rotate_imm * 2);
1068 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1070 instruction->info.data_proc.variant = 0;
1071 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1073 else /* register-based shifter operand */
1076 shift = (opcode & 0x60) >> 5;
1077 Rm = (opcode & 0xf);
1079 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1082 shift_imm = (opcode & 0xf80) >> 7;
1084 instruction->info.data_proc.variant = 1;
1085 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1086 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x1) && (shift_imm == 0x0))
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift == 0x2) && (shift_imm == 0x0))
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift == 0x3) && (shift_imm == 0x0))
1101 if ((shift_imm == 0x0) && (shift == 0x0))
1103 snprintf(shifter_operand, 32, "r%i", Rm);
1107 if (shift == 0x0) /* LSL */
1109 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1111 else if (shift == 0x1) /* LSR */
1113 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1115 else if (shift == 0x2) /* ASR */
1117 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1119 else if (shift == 0x3) /* ROR */
1121 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1123 else if (shift == 0x4) /* RRX */
1125 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1131 uint8_t Rs = (opcode & 0xf00) >> 8;
1133 instruction->info.data_proc.variant = 2;
1134 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1135 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1136 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1138 if (shift == 0x0) /* LSL */
1140 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1142 else if (shift == 0x1) /* LSR */
1144 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1146 else if (shift == 0x2) /* ASR */
1148 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1150 else if (shift == 0x3) /* ROR */
1152 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1157 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1160 address, opcode, mnemonic, COND(opcode),
1161 (S) ? "S" : "", Rd, Rn, shifter_operand);
1163 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1165 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1169 address, opcode, mnemonic, COND(opcode),
1170 (S) ? "S" : "", Rd, shifter_operand);
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1174 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1175 address, opcode, mnemonic, COND(opcode),
1176 Rn, shifter_operand);
1182 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1184 /* clear fields, to avoid confusion */
1185 memset(instruction, 0, sizeof(arm_instruction_t));
1186 instruction->opcode = opcode;
1187 instruction->instruction_size = 4;
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode & 0xf0000000) == 0xf0000000)
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode & 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode, address, instruction);
1196 /* Undefined instruction */
1197 if ((opcode & 0x0e000000) == 0x08000000)
1199 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1200 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode & 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode, address, instruction);
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode & 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1213 /* Coprocessor data processing */
1214 if ((opcode & 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1217 /* Coprocessor register transfers */
1218 if ((opcode & 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1221 /* Undefined instruction */
1222 if ((opcode & 0x0f000000) == 0x0f000000)
1224 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1225 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode & 0x0e000000) == 0x00000000)
1233 /* Multiplies, extra load/stores */
1234 if ((opcode & 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1237 /* Miscellaneous instructions */
1238 if ((opcode & 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode, address, instruction);
1241 return evaluate_data_proc(opcode, address, instruction);
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode & 0x0e000000) == 0x02000000)
1247 /* Undefined instruction */
1248 if ((opcode & 0x0fb00000) == 0x03000000)
1250 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1251 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1255 /* Move immediate to status register */
1256 if ((opcode & 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode, address, instruction);
1259 return evaluate_data_proc(opcode, address, instruction);
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode & 0x0e000000) == 0x04000000)
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode, address, instruction);
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode & 0x0e000000) == 0x06000000)
1273 /* Undefined instruction */
1274 if ((opcode & 0x00000010) == 0x00000010)
1276 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1277 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode, address, instruction);
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode & 0x0e000000) == 0x08000000)
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode, address, instruction);
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode & 0x0e000000) == 0x0a000000)
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode, address, instruction);
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode & 0x0e000000) == 0x0a000000)
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode & 0x0e000000) == 0x0e000000)
1310 /* Software interrupt */
1311 if ((opcode & 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode, address, instruction);
1314 /* Coprocessor data processing */
1315 if ((opcode & 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1318 /* Coprocessor register transfers */
1319 if ((opcode & 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1323 LOG_ERROR("should never reach this point");
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1329 uint32_t offset = opcode & 0x7ff;
1330 uint32_t opc = (opcode >> 11) & 0x3;
1331 uint32_t target_address;
1332 char *mnemonic = NULL;
1334 /* sign extend 11-bit offset */
1335 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1336 offset = 0xfffff800 | offset;
1338 target_address = address + 4 + (offset << 1);
1342 /* unconditional branch */
1344 instruction->type = ARM_B;
1349 instruction->type = ARM_BLX;
1354 instruction->type = ARM_UNKNOWN_INSTUCTION;
1355 mnemonic = "prefix";
1356 target_address = offset << 12;
1360 instruction->type = ARM_BL;
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1370 snprintf(instruction->text, 128,
1371 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1372 address, opcode, mnemonic, target_address);
1374 instruction->info.b_bl_bx_blx.reg_operand = -1;
1375 instruction->info.b_bl_bx_blx.target_address = target_address;
1380 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1382 uint8_t Rd = (opcode >> 0) & 0x7;
1383 uint8_t Rn = (opcode >> 3) & 0x7;
1384 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1385 uint32_t opc = opcode & (1 << 9);
1386 uint32_t reg_imm = opcode & (1 << 10);
1391 instruction->type = ARM_SUB;
1396 instruction->type = ARM_ADD;
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = 1;
1406 instruction->info.data_proc.variant = 0; /*immediate*/
1407 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1408 snprintf(instruction->text, 128,
1409 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1414 instruction->info.data_proc.variant = 1; /*immediate shift*/
1415 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1416 snprintf(instruction->text, 128,
1417 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1424 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1426 uint8_t Rd = (opcode >> 0) & 0x7;
1427 uint8_t Rm = (opcode >> 3) & 0x7;
1428 uint8_t imm = (opcode >> 6) & 0x1f;
1429 uint8_t opc = (opcode >> 11) & 0x3;
1430 char *mnemonic = NULL;
1435 instruction->type = ARM_MOV;
1437 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1440 instruction->type = ARM_MOV;
1442 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1445 instruction->type = ARM_MOV;
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1451 if ((imm == 0) && (opc != 0))
1454 instruction->info.data_proc.Rd = Rd;
1455 instruction->info.data_proc.Rn = -1;
1456 instruction->info.data_proc.S = 1;
1458 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1459 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1460 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1462 snprintf(instruction->text, 128,
1463 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address, opcode, mnemonic, Rd, Rm, imm);
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1471 uint8_t imm = opcode & 0xff;
1472 uint8_t Rd = (opcode >> 8) & 0x7;
1473 uint32_t opc = (opcode >> 11) & 0x3;
1474 char *mnemonic = NULL;
1476 instruction->info.data_proc.Rd = Rd;
1477 instruction->info.data_proc.Rn = Rd;
1478 instruction->info.data_proc.S = 1;
1479 instruction->info.data_proc.variant = 0; /*immediate*/
1480 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1485 instruction->type = ARM_MOV;
1487 instruction->info.data_proc.Rn = -1;
1490 instruction->type = ARM_CMP;
1492 instruction->info.data_proc.Rd = -1;
1495 instruction->type = ARM_ADD;
1499 instruction->type = ARM_SUB;
1504 snprintf(instruction->text, 128,
1505 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address, opcode, mnemonic, Rd, imm);
1511 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1513 uint8_t high_reg, op, Rm, Rd,H1,H2;
1514 char *mnemonic = NULL;
1516 high_reg = (opcode & 0x0400) >> 10;
1517 op = (opcode & 0x03C0) >> 6;
1519 Rd = (opcode & 0x0007);
1520 Rm = (opcode & 0x0038) >> 3;
1521 H1 = (opcode & 0x0080) >> 7;
1522 H2 = (opcode & 0x0040) >> 6;
1524 instruction->info.data_proc.Rd = Rd;
1525 instruction->info.data_proc.Rn = Rd;
1526 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1527 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1528 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1539 instruction->type = ARM_ADD;
1543 instruction->type = ARM_CMP;
1547 instruction->type = ARM_MOV;
1551 if ((opcode & 0x7) == 0x0)
1553 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1556 instruction->type = ARM_BLX;
1557 snprintf(instruction->text, 128,
1559 " 0x%4.4x \tBLX\tr%i",
1560 address, opcode, Rm);
1564 instruction->type = ARM_BX;
1565 snprintf(instruction->text, 128,
1567 " 0x%4.4x \tBX\tr%i",
1568 address, opcode, Rm);
1573 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1574 snprintf(instruction->text, 128,
1577 "UNDEFINED INSTRUCTION",
1589 instruction->type = ARM_AND;
1593 instruction->type = ARM_EOR;
1597 instruction->type = ARM_MOV;
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1601 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1602 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1605 instruction->type = ARM_MOV;
1607 instruction->info.data_proc.variant = 2 /*register shift*/;
1608 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1609 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1610 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1613 instruction->type = ARM_MOV;
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1617 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1618 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1621 instruction->type = ARM_ADC;
1625 instruction->type = ARM_SBC;
1629 instruction->type = ARM_MOV;
1631 instruction->info.data_proc.variant = 2 /*register shift*/;
1632 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1633 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1634 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1637 instruction->type = ARM_TST;
1641 instruction->type = ARM_RSB;
1643 instruction->info.data_proc.variant = 0 /*immediate*/;
1644 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1645 instruction->info.data_proc.Rn = Rm;
1648 instruction->type = ARM_CMP;
1652 instruction->type = ARM_CMN;
1656 instruction->type = ARM_ORR;
1660 instruction->type = ARM_MUL;
1664 instruction->type = ARM_BIC;
1668 instruction->type = ARM_MVN;
1674 snprintf(instruction->text, 128,
1675 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1676 address, opcode, mnemonic, Rd, Rm);
1681 /* PC-relative data addressing is word-aligned even with Thumb */
1682 static inline uint32_t thumb_alignpc4(uint32_t addr)
1684 return (addr + 4) & ~3;
1687 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1690 uint8_t Rd = (opcode >> 8) & 0x7;
1692 instruction->type = ARM_LDR;
1693 immediate = opcode & 0x000000ff;
1696 instruction->info.load_store.Rd = Rd;
1697 instruction->info.load_store.Rn = 15 /*PC*/;
1698 instruction->info.load_store.index_mode = 0; /*offset*/
1699 instruction->info.load_store.offset_mode = 0; /*immediate*/
1700 instruction->info.load_store.offset.offset = immediate;
1702 snprintf(instruction->text, 128,
1703 "0x%8.8" PRIx32 " 0x%4.4x \t"
1704 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8x",
1705 address, opcode, Rd, immediate,
1706 thumb_alignpc4(address) + immediate);
1711 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1713 uint8_t Rd = (opcode >> 0) & 0x7;
1714 uint8_t Rn = (opcode >> 3) & 0x7;
1715 uint8_t Rm = (opcode >> 6) & 0x7;
1716 uint8_t opc = (opcode >> 9) & 0x7;
1717 char *mnemonic = NULL;
1722 instruction->type = ARM_STR;
1726 instruction->type = ARM_STRH;
1730 instruction->type = ARM_STRB;
1734 instruction->type = ARM_LDRSB;
1738 instruction->type = ARM_LDR;
1742 instruction->type = ARM_LDRH;
1746 instruction->type = ARM_LDRB;
1750 instruction->type = ARM_LDRSH;
1755 snprintf(instruction->text, 128,
1756 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1757 address, opcode, mnemonic, Rd, Rn, Rm);
1759 instruction->info.load_store.Rd = Rd;
1760 instruction->info.load_store.Rn = Rn;
1761 instruction->info.load_store.index_mode = 0; /*offset*/
1762 instruction->info.load_store.offset_mode = 1; /*register*/
1763 instruction->info.load_store.offset.reg.Rm = Rm;
1768 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1770 uint32_t offset = (opcode >> 6) & 0x1f;
1771 uint8_t Rd = (opcode >> 0) & 0x7;
1772 uint8_t Rn = (opcode >> 3) & 0x7;
1773 uint32_t L = opcode & (1 << 11);
1774 uint32_t B = opcode & (1 << 12);
1781 instruction->type = ARM_LDR;
1786 instruction->type = ARM_STR;
1790 if ((opcode&0xF000) == 0x8000)
1801 snprintf(instruction->text, 128,
1802 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1803 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1805 instruction->info.load_store.Rd = Rd;
1806 instruction->info.load_store.Rn = Rn;
1807 instruction->info.load_store.index_mode = 0; /*offset*/
1808 instruction->info.load_store.offset_mode = 0; /*immediate*/
1809 instruction->info.load_store.offset.offset = offset << shift;
1814 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1816 uint32_t offset = opcode & 0xff;
1817 uint8_t Rd = (opcode >> 8) & 0x7;
1818 uint32_t L = opcode & (1 << 11);
1823 instruction->type = ARM_LDR;
1828 instruction->type = ARM_STR;
1832 snprintf(instruction->text, 128,
1833 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1834 address, opcode, mnemonic, Rd, offset*4);
1836 instruction->info.load_store.Rd = Rd;
1837 instruction->info.load_store.Rn = 13 /*SP*/;
1838 instruction->info.load_store.index_mode = 0; /*offset*/
1839 instruction->info.load_store.offset_mode = 0; /*immediate*/
1840 instruction->info.load_store.offset.offset = offset*4;
1845 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1847 uint32_t imm = opcode & 0xff;
1848 uint8_t Rd = (opcode >> 8) & 0x7;
1850 uint32_t SP = opcode & (1 << 11);
1853 instruction->type = ARM_ADD;
1866 snprintf(instruction->text, 128,
1867 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1868 address, opcode, Rd, reg_name, imm * 4);
1870 instruction->info.data_proc.variant = 0 /* immediate */;
1871 instruction->info.data_proc.Rd = Rd;
1872 instruction->info.data_proc.Rn = Rn;
1873 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1878 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1880 uint32_t imm = opcode & 0x7f;
1881 uint8_t opc = opcode & (1 << 7);
1887 instruction->type = ARM_SUB;
1892 instruction->type = ARM_ADD;
1896 snprintf(instruction->text, 128,
1897 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1898 address, opcode, mnemonic, imm*4);
1900 instruction->info.data_proc.variant = 0 /* immediate */;
1901 instruction->info.data_proc.Rd = 13 /*SP*/;
1902 instruction->info.data_proc.Rn = 13 /*SP*/;
1903 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1908 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1910 uint32_t imm = opcode & 0xff;
1912 instruction->type = ARM_BKPT;
1914 snprintf(instruction->text, 128,
1915 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1916 address, opcode, imm);
1921 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1923 uint32_t reg_list = opcode & 0xff;
1924 uint32_t L = opcode & (1 << 11);
1925 uint32_t R = opcode & (1 << 8);
1926 uint8_t Rn = (opcode >> 8) & 7;
1927 uint8_t addr_mode = 0 /* IA */;
1931 char ptr_name[7] = "";
1934 if ((opcode & 0xf000) == 0xc000)
1935 { /* generic load/store multiple */
1938 instruction->type = ARM_LDM;
1943 instruction->type = ARM_STM;
1946 snprintf(ptr_name,7,"r%i!, ",Rn);
1953 instruction->type = ARM_LDM;
1956 reg_list |= (1 << 15) /*PC*/;
1960 instruction->type = ARM_STM;
1962 addr_mode = 3; /*DB*/
1964 reg_list |= (1 << 14) /*LR*/;
1968 reg_names_p = reg_names;
1969 for (i = 0; i <= 15; i++)
1971 if (reg_list & (1 << i))
1972 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1974 if (reg_names_p > reg_names)
1975 reg_names_p[-2] = '\0';
1976 else /* invalid op : no registers */
1977 reg_names[0] = '\0';
1979 snprintf(instruction->text, 128,
1980 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1981 address, opcode, mnemonic, ptr_name, reg_names);
1983 instruction->info.load_store_multiple.register_list = reg_list;
1984 instruction->info.load_store_multiple.Rn = Rn;
1985 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1990 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1992 uint32_t offset = opcode & 0xff;
1993 uint8_t cond = (opcode >> 8) & 0xf;
1994 uint32_t target_address;
1998 instruction->type = ARM_SWI;
1999 snprintf(instruction->text, 128,
2000 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2001 address, opcode, offset);
2004 else if (cond == 0xe)
2006 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2007 snprintf(instruction->text, 128,
2008 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2013 /* sign extend 8-bit offset */
2014 if (offset & 0x00000080)
2015 offset = 0xffffff00 | offset;
2017 target_address = address + 4 + (offset << 1);
2019 snprintf(instruction->text, 128,
2020 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2022 arm_condition_strings[cond], target_address);
2024 instruction->type = ARM_B;
2025 instruction->info.b_bl_bx_blx.reg_operand = -1;
2026 instruction->info.b_bl_bx_blx.target_address = target_address;
2031 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2032 arm_instruction_t *instruction)
2036 /* added in Thumb2 */
2037 offset = (opcode >> 3) & 0x1f;
2038 offset |= (opcode & 0x0200) >> 4;
2040 snprintf(instruction->text, 128,
2041 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2043 (opcode & 0x0800) ? "N" : "",
2044 opcode & 0x7, address + 4 + (offset << 1));
2049 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2050 arm_instruction_t *instruction)
2052 /* added in ARMv6 */
2053 snprintf(instruction->text, 128,
2054 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2056 (opcode & 0x0080) ? 'U' : 'S',
2057 (opcode & 0x0040) ? 'B' : 'H',
2058 opcode & 0x7, (opcode >> 3) & 0x7);
2063 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2064 arm_instruction_t *instruction)
2066 /* added in ARMv6 */
2067 if ((opcode & 0x0ff0) == 0x0650)
2068 snprintf(instruction->text, 128,
2069 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2071 (opcode & 0x80) ? "BE" : "LE");
2072 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2073 snprintf(instruction->text, 128,
2074 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2076 (opcode & 0x0010) ? 'D' : 'E',
2077 (opcode & 0x0004) ? "A" : "",
2078 (opcode & 0x0002) ? "I" : "",
2079 (opcode & 0x0001) ? "F" : "");
2084 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2085 arm_instruction_t *instruction)
2089 /* added in ARMv6 */
2090 switch (opcode & 0x00c0) {
2101 snprintf(instruction->text, 128,
2102 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2103 address, opcode, suffix,
2104 opcode & 0x7, (opcode >> 3) & 0x7);
2109 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2110 arm_instruction_t *instruction)
2114 switch ((opcode >> 4) & 0x0f) {
2131 hint = "HINT (UNRECOGNIZED)";
2135 snprintf(instruction->text, 128,
2136 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2137 address, opcode, hint);
2142 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2143 arm_instruction_t *instruction)
2145 unsigned cond = (opcode >> 4) & 0x0f;
2146 char *x = "", *y = "", *z = "";
2149 z = (opcode & 0x02) ? "T" : "E";
2151 y = (opcode & 0x04) ? "T" : "E";
2153 x = (opcode & 0x08) ? "T" : "E";
2155 snprintf(instruction->text, 128,
2156 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2158 x, y, z, arm_condition_strings[cond]);
2160 /* NOTE: strictly speaking, the next 1-4 instructions should
2161 * now be displayed with the relevant conditional suffix...
2167 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2169 /* clear fields, to avoid confusion */
2170 memset(instruction, 0, sizeof(arm_instruction_t));
2171 instruction->opcode = opcode;
2172 instruction->instruction_size = 2;
2174 if ((opcode & 0xe000) == 0x0000)
2176 /* add/substract register or immediate */
2177 if ((opcode & 0x1800) == 0x1800)
2178 return evaluate_add_sub_thumb(opcode, address, instruction);
2179 /* shift by immediate */
2181 return evaluate_shift_imm_thumb(opcode, address, instruction);
2184 /* Add/substract/compare/move immediate */
2185 if ((opcode & 0xe000) == 0x2000)
2187 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2190 /* Data processing instructions */
2191 if ((opcode & 0xf800) == 0x4000)
2193 return evaluate_data_proc_thumb(opcode, address, instruction);
2196 /* Load from literal pool */
2197 if ((opcode & 0xf800) == 0x4800)
2199 return evaluate_load_literal_thumb(opcode, address, instruction);
2202 /* Load/Store register offset */
2203 if ((opcode & 0xf000) == 0x5000)
2205 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2208 /* Load/Store immediate offset */
2209 if (((opcode & 0xe000) == 0x6000)
2210 ||((opcode & 0xf000) == 0x8000))
2212 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2215 /* Load/Store from/to stack */
2216 if ((opcode & 0xf000) == 0x9000)
2218 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2222 if ((opcode & 0xf000) == 0xa000)
2224 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2228 if ((opcode & 0xf000) == 0xb000)
2230 switch ((opcode >> 8) & 0x0f) {
2232 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2237 return evaluate_cb_thumb(opcode, address, instruction);
2239 return evaluate_extend_thumb(opcode, address, instruction);
2244 return evaluate_load_store_multiple_thumb(opcode, address,
2247 return evaluate_cps_thumb(opcode, address, instruction);
2249 if ((opcode & 0x00c0) == 0x0080)
2251 return evaluate_byterev_thumb(opcode, address, instruction);
2253 return evaluate_breakpoint_thumb(opcode, address, instruction);
2255 if (opcode & 0x000f)
2256 return evaluate_ifthen_thumb(opcode, address,
2259 return evaluate_hint_thumb(opcode, address,
2263 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2264 snprintf(instruction->text, 128,
2265 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2270 /* Load/Store multiple */
2271 if ((opcode & 0xf000) == 0xc000)
2273 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2276 /* Conditional branch + SWI */
2277 if ((opcode & 0xf000) == 0xd000)
2279 return evaluate_cond_branch_thumb(opcode, address, instruction);
2282 if ((opcode & 0xe000) == 0xe000)
2284 /* Undefined instructions */
2285 if ((opcode & 0xf801) == 0xe801)
2287 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2288 snprintf(instruction->text, 128,
2289 "0x%8.8" PRIx32 " 0x%8.8x\t"
2290 "UNDEFINED INSTRUCTION",
2295 { /* Branch to offset */
2296 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2300 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2304 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2305 arm_instruction_t *instruction, char *cp)
2308 unsigned b21 = 1 << 21;
2309 unsigned b22 = 1 << 22;
2311 /* instead of combining two smaller 16-bit branch instructions,
2312 * Thumb2 uses only one larger 32-bit instruction.
2314 offset = opcode & 0x7ff;
2315 offset |= (opcode & 0x03ff0000) >> 5;
2316 if (opcode & (1 << 26)) {
2317 offset |= 0xff << 23;
2318 if ((opcode & (1 << 11)) == 0)
2320 if ((opcode & (1 << 13)) == 0)
2323 if (opcode & (1 << 11))
2325 if (opcode & (1 << 13))
2333 address += offset << 1;
2335 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2336 instruction->info.b_bl_bx_blx.reg_operand = -1;
2337 instruction->info.b_bl_bx_blx.target_address = address;
2338 sprintf(cp, "%s\t%#8.8" PRIx32,
2339 (opcode & (1 << 14)) ? "BL" : "B.W",
2345 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2346 arm_instruction_t *instruction, char *cp)
2349 unsigned b17 = 1 << 17;
2350 unsigned b18 = 1 << 18;
2351 unsigned cond = (opcode >> 22) & 0x0f;
2353 offset = opcode & 0x7ff;
2354 offset |= (opcode & 0x003f0000) >> 5;
2355 if (opcode & (1 << 26)) {
2356 offset |= 0xffff << 19;
2357 if ((opcode & (1 << 11)) == 0)
2359 if ((opcode & (1 << 13)) == 0)
2362 if (opcode & (1 << 11))
2364 if (opcode & (1 << 13))
2371 address += offset << 1;
2373 instruction->type = ARM_B;
2374 instruction->info.b_bl_bx_blx.reg_operand = -1;
2375 instruction->info.b_bl_bx_blx.target_address = address;
2376 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2377 arm_condition_strings[cond],
2383 static const char *special_name(int number)
2385 char *special = "(RESERVED)";
2416 special = "primask";
2419 special = "basepri";
2422 special = "basepri_max";
2425 special = "faultmask";
2428 special = "control";
2434 static int t2ev_hint(uint32_t opcode, uint32_t address,
2435 arm_instruction_t *instruction, char *cp)
2437 const char *mnemonic;
2439 if (opcode & 0x0700) {
2440 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2441 strcpy(cp, "UNDEFINED");
2445 if (opcode & 0x00f0) {
2446 sprintf(cp, "DBG\t#%d", opcode & 0xf);
2450 switch (opcode & 0x0f) {
2455 mnemonic = "YIELD.W";
2467 mnemonic = "HINT.W (UNRECOGNIZED)";
2470 strcpy(cp, mnemonic);
2474 static int t2ev_misc(uint32_t opcode, uint32_t address,
2475 arm_instruction_t *instruction, char *cp)
2477 const char *mnemonic;
2479 switch ((opcode >> 4) & 0x0f) {
2493 return ERROR_INVALID_ARGUMENTS;
2495 strcpy(cp, mnemonic);
2499 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2500 arm_instruction_t *instruction, char *cp)
2502 /* permanently undefined */
2503 if ((opcode & 0x07f07000) == 0x07f02000) {
2504 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2505 strcpy(cp, "UNDEFINED");
2509 switch ((opcode >> 12) & 0x5) {
2512 return t2ev_b_bl(opcode, address, instruction, cp);
2516 if (((opcode >> 23) & 0x07) == 0x07)
2517 return t2ev_cond_b(opcode, address, instruction, cp);
2518 if (opcode & (1 << 26))
2523 switch ((opcode >> 20) & 0x7f) {
2526 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2527 (opcode >> 16) & 0x0f);
2530 return t2ev_hint(opcode, address, instruction, cp);
2532 return t2ev_misc(opcode, address, instruction, cp);
2535 sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
2536 special_name(opcode & 0xff));
2541 return ERROR_INVALID_ARGUMENTS;
2544 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2545 arm_instruction_t *instruction, char *cp)
2547 char *mnemonic = NULL;
2548 int rn = (opcode >> 16) & 0xf;
2549 int rd = (opcode >> 8) & 0xf;
2550 unsigned immed = opcode & 0xff;
2555 /* ARMv7-M: A5.3.2 Modified immediate constants */
2556 func = (opcode >> 11) & 0x0e;
2559 if (opcode & (1 << 26))
2562 /* "Modified" immediates */
2563 switch (func >> 1) {
2570 immed += immed << 16;
2573 immed += immed << 8;
2574 immed += immed << 16;
2578 immed = ror(immed, func);
2581 if (opcode & (1 << 20))
2584 switch ((opcode >> 21) & 0xf) {
2587 instruction->type = ARM_TST;
2593 instruction->type = ARM_AND;
2598 instruction->type = ARM_BIC;
2603 instruction->type = ARM_MOV;
2607 instruction->type = ARM_ORR;
2613 instruction->type = ARM_MVN;
2617 // instruction->type = ARM_ORN;
2623 instruction->type = ARM_TEQ;
2629 instruction->type = ARM_EOR;
2635 instruction->type = ARM_CMN;
2641 instruction->type = ARM_ADD;
2646 instruction->type = ARM_ADC;
2650 instruction->type = ARM_SBC;
2655 instruction->type = ARM_CMP;
2661 instruction->type = ARM_SUB;
2666 instruction->type = ARM_RSB;
2670 return ERROR_INVALID_ARGUMENTS;
2674 sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
2675 mnemonic, rd, immed, immed);
2677 sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
2678 mnemonic, suffix, rd, rn, immed, immed);
2683 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2684 arm_instruction_t *instruction, char *cp)
2686 char *mnemonic = NULL;
2687 int rn = (opcode >> 16) & 0xf;
2688 int rd = (opcode >> 8) & 0xf;
2691 bool is_signed = false;
2693 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2694 if (opcode & (1 << 27))
2697 switch ((opcode >> 20) & 0x1f) {
2714 /* move constant to top 16 bits of register */
2715 immed |= (opcode >> 4) & 0xf000;
2716 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2723 /* signed/unsigned saturated add */
2724 immed = (opcode >> 6) & 0x03;
2725 immed |= (opcode >> 10) & 0x1c;
2726 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2727 is_signed ? "S" : "U",
2728 rd, (opcode & 0x1f) + 1, rn,
2729 (opcode & (1 << 21)) ? "ASR" : "LSL",
2730 immed ? immed : 32);
2736 /* signed/unsigned bitfield extract */
2737 immed = (opcode >> 6) & 0x03;
2738 immed |= (opcode >> 10) & 0x1c;
2739 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2740 is_signed ? "S" : "U",
2742 (opcode & 0x1f) + 1);
2745 immed = (opcode >> 6) & 0x03;
2746 immed |= (opcode >> 10) & 0x1c;
2747 if (rn == 0xf) /* bitfield clear */
2748 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2750 (opcode & 0x1f) + 1 - immed);
2751 else /* bitfield insert */
2752 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2754 (opcode & 0x1f) + 1 - immed);
2757 return ERROR_INVALID_ARGUMENTS;
2760 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2761 rd, rn, immed, immed);
2765 address = thumb_alignpc4(address);
2770 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2771 * not hiding the pc-relative stuff will sometimes be useful.
2773 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2778 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2779 * always set. That means eventual arm_simulate_step() support for Thumb2
2780 * will need work in this area.
2782 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2789 /* clear low bit ... it's set on function pointers */
2792 /* clear fields, to avoid confusion */
2793 memset(instruction, 0, sizeof(arm_instruction_t));
2795 /* read first halfword, see if this is the only one */
2796 retval = target_read_u16(target, address, &op);
2797 if (retval != ERROR_OK)
2800 switch (op & 0xf800) {
2804 /* 32-bit instructions */
2805 instruction->instruction_size = 4;
2807 retval = target_read_u16(target, address + 2, &op);
2808 if (retval != ERROR_OK)
2811 instruction->opcode = opcode;
2814 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2815 return thumb_evaluate_opcode(op, address, instruction);
2818 snprintf(instruction->text, 128,
2819 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
2821 cp = strchr(instruction->text, 0);
2822 retval = ERROR_FAIL;
2824 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
2825 if ((opcode & 0x1a008000) == 0x10000000)
2826 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
2828 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
2829 else if ((opcode & 0x1a008000) == 0x12000000)
2830 retval = t2ev_data_immed(opcode, address, instruction, cp);
2832 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
2833 else if ((opcode & 0x18008000) == 0x10008000)
2834 retval = t2ev_b_misc(opcode, address, instruction, cp);
2836 /* FIXME decode more 32-bit instructions */
2838 if (retval == ERROR_OK)
2841 if (retval == ERROR_INVALID_ARGUMENTS) {
2842 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2843 strcpy(cp, "UNDEFINED OPCODE");
2847 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2849 strcpy(cp, "(32-bit Thumb2 ...)");
2853 int arm_access_size(arm_instruction_t *instruction)
2855 if ((instruction->type == ARM_LDRB)
2856 || (instruction->type == ARM_LDRBT)
2857 || (instruction->type == ARM_LDRSB)
2858 || (instruction->type == ARM_STRB)
2859 || (instruction->type == ARM_STRBT))
2863 else if ((instruction->type == ARM_LDRH)
2864 || (instruction->type == ARM_LDRSH)
2865 || (instruction->type == ARM_STRH))
2869 else if ((instruction->type == ARM_LDR)
2870 || (instruction->type == ARM_LDRT)
2871 || (instruction->type == ARM_STR)
2872 || (instruction->type == ARM_STRT))
2876 else if ((instruction->type == ARM_LDRD)
2877 || (instruction->type == ARM_STRD))
2883 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);