1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include "arm_disassembler.h"
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings[] =
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value, int places)
39 return (value >> places) | (value << (32 - places));
42 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
45 if ((opcode & 0x0d70f0000) == 0x0550f000)
47 instruction->type = ARM_PLD;
49 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
55 instruction->type = ARM_UNDEFINED_INSTRUCTION;
59 LOG_ERROR("should never reach this point");
63 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
65 instruction->type = ARM_SWI;
67 snprintf(instruction->text, 128,
68 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
69 address, opcode, (opcode & 0xffffff));
74 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
78 uint32_t target_address;
80 instruction->type = ARM_BLX;
81 immediate = opcode & 0x00ffffff;
83 /* sign extend 24-bit immediate */
84 if (immediate & 0x00800000)
85 offset = 0xff000000 | immediate;
89 /* shift two bits left */
92 /* odd/event halfword */
93 if (opcode & 0x01000000)
96 target_address = address + 8 + offset;
98 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
100 instruction->info.b_bl_bx_blx.reg_operand = -1;
101 instruction->info.b_bl_bx_blx.target_address = target_address;
106 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
111 uint32_t target_address;
113 immediate = opcode & 0x00ffffff;
114 L = (opcode & 0x01000000) >> 24;
116 /* sign extend 24-bit immediate */
117 if (immediate & 0x00800000)
118 offset = 0xff000000 | immediate;
122 /* shift two bits left */
125 target_address = address + 8 + offset;
128 instruction->type = ARM_BL;
130 instruction->type = ARM_B;
132 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
133 (L) ? "L" : "", COND(opcode), target_address);
135 instruction->info.b_bl_bx_blx.reg_operand = -1;
136 instruction->info.b_bl_bx_blx.target_address = target_address;
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
145 uint8_t cp_num = (opcode & 0xf00) >> 8;
148 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
150 uint8_t cp_opcode, Rd, Rn, CRm;
153 cp_opcode = (opcode & 0xf0) >> 4;
154 Rd = (opcode & 0xf000) >> 12;
155 Rn = (opcode & 0xf0000) >> 16;
156 CRm = (opcode & 0xf);
159 if ((opcode & 0x0ff00000) == 0x0c400000)
161 instruction->type = ARM_MCRR;
166 if ((opcode & 0x0ff00000) == 0x0c500000)
168 instruction->type = ARM_MRRC;
172 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
173 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
175 else /* LDC or STC */
177 uint8_t CRd, Rn, offset;
180 char addressing_mode[32];
182 CRd = (opcode & 0xf000) >> 12;
183 Rn = (opcode & 0xf0000) >> 16;
184 offset = (opcode & 0xff);
187 if (opcode & 0x00100000)
189 instruction->type = ARM_LDC;
194 instruction->type = ARM_STC;
198 U = (opcode & 0x00800000) >> 23;
199 N = (opcode & 0x00400000) >> 22;
201 /* addressing modes */
202 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
204 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
206 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
208 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
212 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
214 cp_num, CRd, addressing_mode);
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
227 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
229 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
230 cp_num = (opcode & 0xf00) >> 8;
231 CRd_Rd = (opcode & 0xf000) >> 12;
232 CRn = (opcode & 0xf0000) >> 16;
233 CRm = (opcode & 0xf);
234 opcode_2 = (opcode & 0xe0) >> 5;
237 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
239 if (opcode & 0x00100000) /* bit 20 set -> MRC */
241 instruction->type = ARM_MRC;
244 else /* bit 20 not set -> MCR */
246 instruction->type = ARM_MCR;
250 opcode_1 = (opcode & 0x00e00000) >> 21;
252 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
253 address, opcode, mnemonic, cond,
254 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
256 else /* bit 4 not set -> CDP */
258 instruction->type = ARM_CDP;
261 opcode_1 = (opcode & 0x00f00000) >> 20;
263 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
264 address, opcode, mnemonic, cond,
265 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
274 uint8_t I, P, U, B, W, L;
276 char *operation; /* "LDR" or "STR" */
277 char *suffix; /* "", "B", "T", "BT" */
281 I = (opcode & 0x02000000) >> 25;
282 P = (opcode & 0x01000000) >> 24;
283 U = (opcode & 0x00800000) >> 23;
284 B = (opcode & 0x00400000) >> 22;
285 W = (opcode & 0x00200000) >> 21;
286 L = (opcode & 0x00100000) >> 20;
288 /* target register */
289 Rd = (opcode & 0xf000) >> 12;
292 Rn = (opcode & 0xf0000) >> 16;
294 instruction->info.load_store.Rd = Rd;
295 instruction->info.load_store.Rn = Rn;
296 instruction->info.load_store.U = U;
298 /* determine operation */
304 /* determine instruction type and suffix */
307 if ((P == 0) && (W == 1))
310 instruction->type = ARM_LDRBT;
312 instruction->type = ARM_STRBT;
318 instruction->type = ARM_LDRB;
320 instruction->type = ARM_STRB;
326 if ((P == 0) && (W == 1))
329 instruction->type = ARM_LDRT;
331 instruction->type = ARM_STRT;
337 instruction->type = ARM_LDR;
339 instruction->type = ARM_STR;
344 if (!I) /* #+-<offset_12> */
346 uint32_t offset_12 = (opcode & 0xfff);
348 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
350 snprintf(offset, 32, "%s", "");
352 instruction->info.load_store.offset_mode = 0;
353 instruction->info.load_store.offset.offset = offset_12;
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
357 uint8_t shift_imm, shift;
360 shift_imm = (opcode & 0xf80) >> 7;
361 shift = (opcode & 0x60) >> 5;
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift == 0x1) && (shift_imm == 0x0))
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift == 0x2) && (shift_imm == 0x0))
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift == 0x3) && (shift_imm == 0x0))
376 instruction->info.load_store.offset_mode = 1;
377 instruction->info.load_store.offset.reg.Rm = Rm;
378 instruction->info.load_store.offset.reg.shift = shift;
379 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
381 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
383 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
390 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
393 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
396 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
399 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
402 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
410 if (W == 0) /* offset */
412 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
413 address, opcode, operation, COND(opcode), suffix,
416 instruction->info.load_store.index_mode = 0;
418 else /* pre-indexed */
420 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
421 address, opcode, operation, COND(opcode), suffix,
424 instruction->info.load_store.index_mode = 1;
427 else /* post-indexed */
429 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
430 address, opcode, operation, COND(opcode), suffix,
433 instruction->info.load_store.index_mode = 2;
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
442 uint8_t P, U, I, W, L, S, H;
444 char *operation; /* "LDR" or "STR" */
445 char *suffix; /* "H", "SB", "SH", "D" */
449 P = (opcode & 0x01000000) >> 24;
450 U = (opcode & 0x00800000) >> 23;
451 I = (opcode & 0x00400000) >> 22;
452 W = (opcode & 0x00200000) >> 21;
453 L = (opcode & 0x00100000) >> 20;
454 S = (opcode & 0x00000040) >> 6;
455 H = (opcode & 0x00000020) >> 5;
457 /* target register */
458 Rd = (opcode & 0xf000) >> 12;
461 Rn = (opcode & 0xf0000) >> 16;
463 instruction->info.load_store.Rd = Rd;
464 instruction->info.load_store.Rn = Rn;
465 instruction->info.load_store.U = U;
467 /* determine instruction type and suffix */
475 instruction->type = ARM_LDRSH;
481 instruction->type = ARM_LDRSB;
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
491 instruction->type = ARM_STRD;
496 instruction->type = ARM_LDRD;
506 instruction->type = ARM_LDRH;
511 instruction->type = ARM_STRH;
515 if (I) /* Immediate offset/index (#+-<offset_8>)*/
517 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
518 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
520 instruction->info.load_store.offset_mode = 0;
521 instruction->info.load_store.offset.offset = offset_8;
523 else /* Register offset/index (+-<Rm>) */
527 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
529 instruction->info.load_store.offset_mode = 1;
530 instruction->info.load_store.offset.reg.Rm = Rm;
531 instruction->info.load_store.offset.reg.shift = 0x0;
532 instruction->info.load_store.offset.reg.shift_imm = 0x0;
537 if (W == 0) /* offset */
539 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
540 address, opcode, operation, COND(opcode), suffix,
543 instruction->info.load_store.index_mode = 0;
545 else /* pre-indexed */
547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
548 address, opcode, operation, COND(opcode), suffix,
551 instruction->info.load_store.index_mode = 1;
554 else /* post-indexed */
556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
557 address, opcode, operation, COND(opcode), suffix,
560 instruction->info.load_store.index_mode = 2;
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
569 uint8_t P, U, S, W, L, Rn;
570 uint32_t register_list;
571 char *addressing_mode;
578 P = (opcode & 0x01000000) >> 24;
579 U = (opcode & 0x00800000) >> 23;
580 S = (opcode & 0x00400000) >> 22;
581 W = (opcode & 0x00200000) >> 21;
582 L = (opcode & 0x00100000) >> 20;
583 register_list = (opcode & 0xffff);
584 Rn = (opcode & 0xf0000) >> 16;
586 instruction->info.load_store_multiple.Rn = Rn;
587 instruction->info.load_store_multiple.register_list = register_list;
588 instruction->info.load_store_multiple.S = S;
589 instruction->info.load_store_multiple.W = W;
593 instruction->type = ARM_LDM;
598 instruction->type = ARM_STM;
606 instruction->info.load_store_multiple.addressing_mode = 1;
607 addressing_mode = "IB";
611 instruction->info.load_store_multiple.addressing_mode = 3;
612 addressing_mode = "DB";
619 instruction->info.load_store_multiple.addressing_mode = 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode = "";
625 instruction->info.load_store_multiple.addressing_mode = 2;
626 addressing_mode = "DA";
630 reg_list_p = reg_list;
631 for (i = 0; i <= 15; i++)
633 if ((register_list >> i) & 1)
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
642 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
647 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
648 address, opcode, mnemonic, COND(opcode), addressing_mode,
649 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode & 0x000000f0) == 0x00000090)
660 /* Multiply (accumulate) */
661 if ((opcode & 0x0f800000) == 0x00000000)
663 uint8_t Rm, Rs, Rn, Rd, S;
665 Rs = (opcode & 0xf00) >> 8;
666 Rn = (opcode & 0xf000) >> 12;
667 Rd = (opcode & 0xf0000) >> 16;
668 S = (opcode & 0x00100000) >> 20;
670 /* examine A bit (accumulate) */
671 if (opcode & 0x00200000)
673 instruction->type = ARM_MLA;
674 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
675 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
679 instruction->type = ARM_MUL;
680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
681 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
687 /* Multiply (accumulate) long */
688 if ((opcode & 0x0f800000) == 0x00800000)
690 char* mnemonic = NULL;
691 uint8_t Rm, Rs, RdHi, RdLow, S;
693 Rs = (opcode & 0xf00) >> 8;
694 RdHi = (opcode & 0xf000) >> 12;
695 RdLow = (opcode & 0xf0000) >> 16;
696 S = (opcode & 0x00100000) >> 20;
698 switch ((opcode & 0x00600000) >> 21)
701 instruction->type = ARM_UMULL;
705 instruction->type = ARM_UMLAL;
709 instruction->type = ARM_SMULL;
713 instruction->type = ARM_SMLAL;
718 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
719 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
720 RdLow, RdHi, Rm, Rs);
726 if ((opcode & 0x0f800000) == 0x01000000)
730 Rd = (opcode & 0xf000) >> 12;
731 Rn = (opcode & 0xf0000) >> 16;
734 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
736 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
737 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
743 return evaluate_misc_load_store(opcode, address, instruction);
746 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
748 int R = (opcode & 0x00400000) >> 22;
749 char *PSR = (R) ? "SPSR" : "CPSR";
751 /* Move register to status register (MSR) */
752 if (opcode & 0x00200000)
754 instruction->type = ARM_MSR;
756 /* immediate variant */
757 if (opcode & 0x02000000)
759 uint8_t immediate = (opcode & 0xff);
760 uint8_t rotate = (opcode & 0xf00);
762 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
763 address, opcode, COND(opcode), PSR,
764 (opcode & 0x10000) ? "c" : "",
765 (opcode & 0x20000) ? "x" : "",
766 (opcode & 0x40000) ? "s" : "",
767 (opcode & 0x80000) ? "f" : "",
768 ror(immediate, (rotate * 2))
771 else /* register variant */
773 uint8_t Rm = opcode & 0xf;
774 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
775 address, opcode, COND(opcode), PSR,
776 (opcode & 0x10000) ? "c" : "",
777 (opcode & 0x20000) ? "x" : "",
778 (opcode & 0x40000) ? "s" : "",
779 (opcode & 0x80000) ? "f" : "",
785 else /* Move status register to register (MRS) */
789 instruction->type = ARM_MRS;
790 Rd = (opcode & 0x0000f000) >> 12;
792 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
793 address, opcode, COND(opcode), Rd, PSR);
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
803 if ((opcode & 0x000000f0) == 0x00000000)
805 evaluate_mrs_msr(opcode, address, instruction);
809 if ((opcode & 0x006000f0) == 0x00200010)
812 instruction->type = ARM_BX;
815 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
816 address, opcode, COND(opcode), Rm);
818 instruction->info.b_bl_bx_blx.reg_operand = Rm;
819 instruction->info.b_bl_bx_blx.target_address = -1;
823 if ((opcode & 0x006000f0) == 0x00600010)
826 instruction->type = ARM_CLZ;
828 Rd = (opcode & 0xf000) >> 12;
830 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
831 address, opcode, COND(opcode), Rd, Rm);
835 if ((opcode & 0x006000f0) == 0x00200030)
838 instruction->type = ARM_BLX;
841 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
842 address, opcode, COND(opcode), Rm);
844 instruction->info.b_bl_bx_blx.reg_operand = Rm;
845 instruction->info.b_bl_bx_blx.target_address = -1;
848 /* Enhanced DSP add/subtracts */
849 if ((opcode & 0x0000000f0) == 0x00000050)
852 char *mnemonic = NULL;
854 Rd = (opcode & 0xf000) >> 12;
855 Rn = (opcode & 0xf0000) >> 16;
857 switch ((opcode & 0x00600000) >> 21)
860 instruction->type = ARM_QADD;
864 instruction->type = ARM_QSUB;
868 instruction->type = ARM_QDADD;
872 instruction->type = ARM_QDSUB;
877 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
878 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
881 /* Software breakpoints */
882 if ((opcode & 0x0000000f0) == 0x00000070)
885 instruction->type = ARM_BKPT;
886 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
888 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
889 address, opcode, immediate);
892 /* Enhanced DSP multiplies */
893 if ((opcode & 0x000000090) == 0x00000080)
895 int x = (opcode & 0x20) >> 5;
896 int y = (opcode & 0x40) >> 6;
899 if ((opcode & 0x00600000) == 0x00000000)
901 uint8_t Rd, Rm, Rs, Rn;
902 instruction->type = ARM_SMLAxy;
903 Rd = (opcode & 0xf0000) >> 16;
905 Rs = (opcode & 0xf00) >> 8;
906 Rn = (opcode & 0xf000) >> 12;
908 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
914 if ((opcode & 0x00600000) == 0x00400000)
916 uint8_t RdLow, RdHi, Rm, Rs;
917 instruction->type = ARM_SMLAxy;
918 RdHi = (opcode & 0xf0000) >> 16;
919 RdLow = (opcode & 0xf000) >> 12;
921 Rs = (opcode & 0xf00) >> 8;
923 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
925 RdLow, RdHi, Rm, Rs);
929 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
931 uint8_t Rd, Rm, Rs, Rn;
932 instruction->type = ARM_SMLAWy;
933 Rd = (opcode & 0xf0000) >> 16;
935 Rs = (opcode & 0xf00) >> 8;
936 Rn = (opcode & 0xf000) >> 12;
938 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address, opcode, (y) ? "T" : "B", COND(opcode),
944 if ((opcode & 0x00600000) == 0x00300000)
947 instruction->type = ARM_SMULxy;
948 Rd = (opcode & 0xf0000) >> 16;
950 Rs = (opcode & 0xf00) >> 8;
952 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
953 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
958 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
961 instruction->type = ARM_SMULWy;
962 Rd = (opcode & 0xf0000) >> 16;
964 Rs = (opcode & 0xf00) >> 8;
966 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
967 address, opcode, (y) ? "T" : "B", COND(opcode),
975 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
977 uint8_t I, op, S, Rn, Rd;
978 char *mnemonic = NULL;
979 char shifter_operand[32];
981 I = (opcode & 0x02000000) >> 25;
982 op = (opcode & 0x01e00000) >> 21;
983 S = (opcode & 0x00100000) >> 20;
985 Rd = (opcode & 0xf000) >> 12;
986 Rn = (opcode & 0xf0000) >> 16;
988 instruction->info.data_proc.Rd = Rd;
989 instruction->info.data_proc.Rn = Rn;
990 instruction->info.data_proc.S = S;
995 instruction->type = ARM_AND;
999 instruction->type = ARM_EOR;
1003 instruction->type = ARM_SUB;
1007 instruction->type = ARM_RSB;
1011 instruction->type = ARM_ADD;
1015 instruction->type = ARM_ADC;
1019 instruction->type = ARM_SBC;
1023 instruction->type = ARM_RSC;
1027 instruction->type = ARM_TST;
1031 instruction->type = ARM_TEQ;
1035 instruction->type = ARM_CMP;
1039 instruction->type = ARM_CMN;
1043 instruction->type = ARM_ORR;
1047 instruction->type = ARM_MOV;
1051 instruction->type = ARM_BIC;
1055 instruction->type = ARM_MVN;
1060 if (I) /* immediate shifter operand (#<immediate>)*/
1062 uint8_t immed_8 = opcode & 0xff;
1063 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1066 immediate = ror(immed_8, rotate_imm * 2);
1068 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1070 instruction->info.data_proc.variant = 0;
1071 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1073 else /* register-based shifter operand */
1076 shift = (opcode & 0x60) >> 5;
1077 Rm = (opcode & 0xf);
1079 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1082 shift_imm = (opcode & 0xf80) >> 7;
1084 instruction->info.data_proc.variant = 1;
1085 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1086 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x1) && (shift_imm == 0x0))
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift == 0x2) && (shift_imm == 0x0))
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift == 0x3) && (shift_imm == 0x0))
1101 if ((shift_imm == 0x0) && (shift == 0x0))
1103 snprintf(shifter_operand, 32, "r%i", Rm);
1107 if (shift == 0x0) /* LSL */
1109 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1111 else if (shift == 0x1) /* LSR */
1113 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1115 else if (shift == 0x2) /* ASR */
1117 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1119 else if (shift == 0x3) /* ROR */
1121 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1123 else if (shift == 0x4) /* RRX */
1125 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1131 uint8_t Rs = (opcode & 0xf00) >> 8;
1133 instruction->info.data_proc.variant = 2;
1134 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1135 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1136 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1138 if (shift == 0x0) /* LSL */
1140 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1142 else if (shift == 0x1) /* LSR */
1144 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1146 else if (shift == 0x2) /* ASR */
1148 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1150 else if (shift == 0x3) /* ROR */
1152 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1157 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1160 address, opcode, mnemonic, COND(opcode),
1161 (S) ? "S" : "", Rd, Rn, shifter_operand);
1163 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1165 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1169 address, opcode, mnemonic, COND(opcode),
1170 (S) ? "S" : "", Rd, shifter_operand);
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1174 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1175 address, opcode, mnemonic, COND(opcode),
1176 Rn, shifter_operand);
1182 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1184 /* clear fields, to avoid confusion */
1185 memset(instruction, 0, sizeof(arm_instruction_t));
1186 instruction->opcode = opcode;
1187 instruction->instruction_size = 4;
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode & 0xf0000000) == 0xf0000000)
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode & 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode, address, instruction);
1196 /* Undefined instruction */
1197 if ((opcode & 0x0e000000) == 0x08000000)
1199 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1200 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode & 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode, address, instruction);
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode & 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1213 /* Coprocessor data processing */
1214 if ((opcode & 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1217 /* Coprocessor register transfers */
1218 if ((opcode & 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1221 /* Undefined instruction */
1222 if ((opcode & 0x0f000000) == 0x0f000000)
1224 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1225 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode & 0x0e000000) == 0x00000000)
1233 /* Multiplies, extra load/stores */
1234 if ((opcode & 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1237 /* Miscellaneous instructions */
1238 if ((opcode & 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode, address, instruction);
1241 return evaluate_data_proc(opcode, address, instruction);
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode & 0x0e000000) == 0x02000000)
1247 /* Undefined instruction */
1248 if ((opcode & 0x0fb00000) == 0x03000000)
1250 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1251 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1255 /* Move immediate to status register */
1256 if ((opcode & 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode, address, instruction);
1259 return evaluate_data_proc(opcode, address, instruction);
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode & 0x0e000000) == 0x04000000)
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode, address, instruction);
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode & 0x0e000000) == 0x06000000)
1273 /* Undefined instruction */
1274 if ((opcode & 0x00000010) == 0x00000010)
1276 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1277 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode, address, instruction);
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode & 0x0e000000) == 0x08000000)
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode, address, instruction);
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode & 0x0e000000) == 0x0a000000)
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode, address, instruction);
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode & 0x0e000000) == 0x0a000000)
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode & 0x0e000000) == 0x0e000000)
1310 /* Software interrupt */
1311 if ((opcode & 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode, address, instruction);
1314 /* Coprocessor data processing */
1315 if ((opcode & 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1318 /* Coprocessor register transfers */
1319 if ((opcode & 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1323 LOG_ERROR("should never reach this point");
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1329 uint32_t offset = opcode & 0x7ff;
1330 uint32_t opc = (opcode >> 11) & 0x3;
1331 uint32_t target_address;
1332 char *mnemonic = NULL;
1334 /* sign extend 11-bit offset */
1335 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1336 offset = 0xfffff800 | offset;
1338 target_address = address + 4 + (offset << 1);
1342 /* unconditional branch */
1344 instruction->type = ARM_B;
1349 instruction->type = ARM_BLX;
1354 instruction->type = ARM_UNKNOWN_INSTUCTION;
1355 mnemonic = "prefix";
1356 target_address = offset << 12;
1360 instruction->type = ARM_BL;
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1370 snprintf(instruction->text, 128,
1371 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1372 address, opcode, mnemonic, target_address);
1374 instruction->info.b_bl_bx_blx.reg_operand = -1;
1375 instruction->info.b_bl_bx_blx.target_address = target_address;
1380 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1382 uint8_t Rd = (opcode >> 0) & 0x7;
1383 uint8_t Rn = (opcode >> 3) & 0x7;
1384 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1385 uint32_t opc = opcode & (1 << 9);
1386 uint32_t reg_imm = opcode & (1 << 10);
1391 instruction->type = ARM_SUB;
1396 instruction->type = ARM_ADD;
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = 1;
1406 instruction->info.data_proc.variant = 0; /*immediate*/
1407 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1408 snprintf(instruction->text, 128,
1409 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1414 instruction->info.data_proc.variant = 1; /*immediate shift*/
1415 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1416 snprintf(instruction->text, 128,
1417 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1424 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1426 uint8_t Rd = (opcode >> 0) & 0x7;
1427 uint8_t Rm = (opcode >> 3) & 0x7;
1428 uint8_t imm = (opcode >> 6) & 0x1f;
1429 uint8_t opc = (opcode >> 11) & 0x3;
1430 char *mnemonic = NULL;
1435 instruction->type = ARM_MOV;
1437 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1440 instruction->type = ARM_MOV;
1442 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1445 instruction->type = ARM_MOV;
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1451 if ((imm == 0) && (opc != 0))
1454 instruction->info.data_proc.Rd = Rd;
1455 instruction->info.data_proc.Rn = -1;
1456 instruction->info.data_proc.S = 1;
1458 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1459 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1460 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1462 snprintf(instruction->text, 128,
1463 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address, opcode, mnemonic, Rd, Rm, imm);
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1471 uint8_t imm = opcode & 0xff;
1472 uint8_t Rd = (opcode >> 8) & 0x7;
1473 uint32_t opc = (opcode >> 11) & 0x3;
1474 char *mnemonic = NULL;
1476 instruction->info.data_proc.Rd = Rd;
1477 instruction->info.data_proc.Rn = Rd;
1478 instruction->info.data_proc.S = 1;
1479 instruction->info.data_proc.variant = 0; /*immediate*/
1480 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1485 instruction->type = ARM_MOV;
1487 instruction->info.data_proc.Rn = -1;
1490 instruction->type = ARM_CMP;
1492 instruction->info.data_proc.Rd = -1;
1495 instruction->type = ARM_ADD;
1499 instruction->type = ARM_SUB;
1504 snprintf(instruction->text, 128,
1505 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address, opcode, mnemonic, Rd, imm);
1511 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1513 uint8_t high_reg, op, Rm, Rd,H1,H2;
1514 char *mnemonic = NULL;
1517 high_reg = (opcode & 0x0400) >> 10;
1518 op = (opcode & 0x03C0) >> 6;
1520 Rd = (opcode & 0x0007);
1521 Rm = (opcode & 0x0038) >> 3;
1522 H1 = (opcode & 0x0080) >> 7;
1523 H2 = (opcode & 0x0040) >> 6;
1525 instruction->info.data_proc.Rd = Rd;
1526 instruction->info.data_proc.Rn = Rd;
1527 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1528 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1529 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1540 instruction->type = ARM_ADD;
1544 instruction->type = ARM_CMP;
1548 instruction->type = ARM_MOV;
1554 if ((opcode & 0x7) == 0x0)
1556 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1559 instruction->type = ARM_BLX;
1560 snprintf(instruction->text, 128,
1562 " 0x%4.4x \tBLX\tr%i",
1563 address, opcode, Rm);
1567 instruction->type = ARM_BX;
1568 snprintf(instruction->text, 128,
1570 " 0x%4.4x \tBX\tr%i",
1571 address, opcode, Rm);
1576 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1577 snprintf(instruction->text, 128,
1580 "UNDEFINED INSTRUCTION",
1592 instruction->type = ARM_AND;
1596 instruction->type = ARM_EOR;
1600 instruction->type = ARM_MOV;
1602 instruction->info.data_proc.variant = 2 /*register shift*/;
1603 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1604 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1605 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1608 instruction->type = ARM_MOV;
1610 instruction->info.data_proc.variant = 2 /*register shift*/;
1611 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1612 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1613 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1616 instruction->type = ARM_MOV;
1618 instruction->info.data_proc.variant = 2 /*register shift*/;
1619 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1620 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1621 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1624 instruction->type = ARM_ADC;
1628 instruction->type = ARM_SBC;
1632 instruction->type = ARM_MOV;
1634 instruction->info.data_proc.variant = 2 /*register shift*/;
1635 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1636 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1637 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1640 instruction->type = ARM_TST;
1644 instruction->type = ARM_RSB;
1646 instruction->info.data_proc.variant = 0 /*immediate*/;
1647 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1648 instruction->info.data_proc.Rn = Rm;
1651 instruction->type = ARM_CMP;
1655 instruction->type = ARM_CMN;
1659 instruction->type = ARM_ORR;
1663 instruction->type = ARM_MUL;
1667 instruction->type = ARM_BIC;
1671 instruction->type = ARM_MVN;
1678 snprintf(instruction->text, 128,
1679 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
1681 address, opcode, mnemonic, Rd, Rm);
1683 snprintf(instruction->text, 128,
1684 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1685 address, opcode, mnemonic, Rd, Rm);
1690 /* PC-relative data addressing is word-aligned even with Thumb */
1691 static inline uint32_t thumb_alignpc4(uint32_t addr)
1693 return (addr + 4) & ~3;
1696 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1699 uint8_t Rd = (opcode >> 8) & 0x7;
1701 instruction->type = ARM_LDR;
1702 immediate = opcode & 0x000000ff;
1705 instruction->info.load_store.Rd = Rd;
1706 instruction->info.load_store.Rn = 15 /*PC*/;
1707 instruction->info.load_store.index_mode = 0; /*offset*/
1708 instruction->info.load_store.offset_mode = 0; /*immediate*/
1709 instruction->info.load_store.offset.offset = immediate;
1711 snprintf(instruction->text, 128,
1712 "0x%8.8" PRIx32 " 0x%4.4x \t"
1713 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8x",
1714 address, opcode, Rd, immediate,
1715 thumb_alignpc4(address) + immediate);
1720 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1722 uint8_t Rd = (opcode >> 0) & 0x7;
1723 uint8_t Rn = (opcode >> 3) & 0x7;
1724 uint8_t Rm = (opcode >> 6) & 0x7;
1725 uint8_t opc = (opcode >> 9) & 0x7;
1726 char *mnemonic = NULL;
1731 instruction->type = ARM_STR;
1735 instruction->type = ARM_STRH;
1739 instruction->type = ARM_STRB;
1743 instruction->type = ARM_LDRSB;
1747 instruction->type = ARM_LDR;
1751 instruction->type = ARM_LDRH;
1755 instruction->type = ARM_LDRB;
1759 instruction->type = ARM_LDRSH;
1764 snprintf(instruction->text, 128,
1765 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1766 address, opcode, mnemonic, Rd, Rn, Rm);
1768 instruction->info.load_store.Rd = Rd;
1769 instruction->info.load_store.Rn = Rn;
1770 instruction->info.load_store.index_mode = 0; /*offset*/
1771 instruction->info.load_store.offset_mode = 1; /*register*/
1772 instruction->info.load_store.offset.reg.Rm = Rm;
1777 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1779 uint32_t offset = (opcode >> 6) & 0x1f;
1780 uint8_t Rd = (opcode >> 0) & 0x7;
1781 uint8_t Rn = (opcode >> 3) & 0x7;
1782 uint32_t L = opcode & (1 << 11);
1783 uint32_t B = opcode & (1 << 12);
1790 instruction->type = ARM_LDR;
1795 instruction->type = ARM_STR;
1799 if ((opcode&0xF000) == 0x8000)
1810 snprintf(instruction->text, 128,
1811 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1812 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1814 instruction->info.load_store.Rd = Rd;
1815 instruction->info.load_store.Rn = Rn;
1816 instruction->info.load_store.index_mode = 0; /*offset*/
1817 instruction->info.load_store.offset_mode = 0; /*immediate*/
1818 instruction->info.load_store.offset.offset = offset << shift;
1823 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1825 uint32_t offset = opcode & 0xff;
1826 uint8_t Rd = (opcode >> 8) & 0x7;
1827 uint32_t L = opcode & (1 << 11);
1832 instruction->type = ARM_LDR;
1837 instruction->type = ARM_STR;
1841 snprintf(instruction->text, 128,
1842 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1843 address, opcode, mnemonic, Rd, offset*4);
1845 instruction->info.load_store.Rd = Rd;
1846 instruction->info.load_store.Rn = 13 /*SP*/;
1847 instruction->info.load_store.index_mode = 0; /*offset*/
1848 instruction->info.load_store.offset_mode = 0; /*immediate*/
1849 instruction->info.load_store.offset.offset = offset*4;
1854 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1856 uint32_t imm = opcode & 0xff;
1857 uint8_t Rd = (opcode >> 8) & 0x7;
1859 uint32_t SP = opcode & (1 << 11);
1862 instruction->type = ARM_ADD;
1875 snprintf(instruction->text, 128,
1876 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1877 address, opcode, Rd, reg_name, imm * 4);
1879 instruction->info.data_proc.variant = 0 /* immediate */;
1880 instruction->info.data_proc.Rd = Rd;
1881 instruction->info.data_proc.Rn = Rn;
1882 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1887 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1889 uint32_t imm = opcode & 0x7f;
1890 uint8_t opc = opcode & (1 << 7);
1896 instruction->type = ARM_SUB;
1901 instruction->type = ARM_ADD;
1905 snprintf(instruction->text, 128,
1906 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1907 address, opcode, mnemonic, imm*4);
1909 instruction->info.data_proc.variant = 0 /* immediate */;
1910 instruction->info.data_proc.Rd = 13 /*SP*/;
1911 instruction->info.data_proc.Rn = 13 /*SP*/;
1912 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1917 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1919 uint32_t imm = opcode & 0xff;
1921 instruction->type = ARM_BKPT;
1923 snprintf(instruction->text, 128,
1924 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1925 address, opcode, imm);
1930 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1932 uint32_t reg_list = opcode & 0xff;
1933 uint32_t L = opcode & (1 << 11);
1934 uint32_t R = opcode & (1 << 8);
1935 uint8_t Rn = (opcode >> 8) & 7;
1936 uint8_t addr_mode = 0 /* IA */;
1940 char ptr_name[7] = "";
1943 if ((opcode & 0xf000) == 0xc000)
1944 { /* generic load/store multiple */
1947 instruction->type = ARM_LDM;
1952 instruction->type = ARM_STM;
1955 snprintf(ptr_name,7,"r%i!, ",Rn);
1962 instruction->type = ARM_LDM;
1965 reg_list |= (1 << 15) /*PC*/;
1969 instruction->type = ARM_STM;
1971 addr_mode = 3; /*DB*/
1973 reg_list |= (1 << 14) /*LR*/;
1977 reg_names_p = reg_names;
1978 for (i = 0; i <= 15; i++)
1980 if (reg_list & (1 << i))
1981 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1983 if (reg_names_p > reg_names)
1984 reg_names_p[-2] = '\0';
1985 else /* invalid op : no registers */
1986 reg_names[0] = '\0';
1988 snprintf(instruction->text, 128,
1989 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1990 address, opcode, mnemonic, ptr_name, reg_names);
1992 instruction->info.load_store_multiple.register_list = reg_list;
1993 instruction->info.load_store_multiple.Rn = Rn;
1994 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1999 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2001 uint32_t offset = opcode & 0xff;
2002 uint8_t cond = (opcode >> 8) & 0xf;
2003 uint32_t target_address;
2007 instruction->type = ARM_SWI;
2008 snprintf(instruction->text, 128,
2009 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2010 address, opcode, offset);
2013 else if (cond == 0xe)
2015 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2016 snprintf(instruction->text, 128,
2017 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2022 /* sign extend 8-bit offset */
2023 if (offset & 0x00000080)
2024 offset = 0xffffff00 | offset;
2026 target_address = address + 4 + (offset << 1);
2028 snprintf(instruction->text, 128,
2029 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2031 arm_condition_strings[cond], target_address);
2033 instruction->type = ARM_B;
2034 instruction->info.b_bl_bx_blx.reg_operand = -1;
2035 instruction->info.b_bl_bx_blx.target_address = target_address;
2040 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2041 arm_instruction_t *instruction)
2045 /* added in Thumb2 */
2046 offset = (opcode >> 3) & 0x1f;
2047 offset |= (opcode & 0x0200) >> 4;
2049 snprintf(instruction->text, 128,
2050 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2052 (opcode & 0x0800) ? "N" : "",
2053 opcode & 0x7, address + 4 + (offset << 1));
2058 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2059 arm_instruction_t *instruction)
2061 /* added in ARMv6 */
2062 snprintf(instruction->text, 128,
2063 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2065 (opcode & 0x0080) ? 'U' : 'S',
2066 (opcode & 0x0040) ? 'B' : 'H',
2067 opcode & 0x7, (opcode >> 3) & 0x7);
2072 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2073 arm_instruction_t *instruction)
2075 /* added in ARMv6 */
2076 if ((opcode & 0x0ff0) == 0x0650)
2077 snprintf(instruction->text, 128,
2078 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2080 (opcode & 0x80) ? "BE" : "LE");
2081 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2082 snprintf(instruction->text, 128,
2083 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2085 (opcode & 0x0010) ? 'D' : 'E',
2086 (opcode & 0x0004) ? "A" : "",
2087 (opcode & 0x0002) ? "I" : "",
2088 (opcode & 0x0001) ? "F" : "");
2093 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2094 arm_instruction_t *instruction)
2098 /* added in ARMv6 */
2099 switch (opcode & 0x00c0) {
2110 snprintf(instruction->text, 128,
2111 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2112 address, opcode, suffix,
2113 opcode & 0x7, (opcode >> 3) & 0x7);
2118 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2119 arm_instruction_t *instruction)
2123 switch ((opcode >> 4) & 0x0f) {
2140 hint = "HINT (UNRECOGNIZED)";
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2146 address, opcode, hint);
2151 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2152 arm_instruction_t *instruction)
2154 unsigned cond = (opcode >> 4) & 0x0f;
2155 char *x = "", *y = "", *z = "";
2158 z = (opcode & 0x02) ? "T" : "E";
2160 y = (opcode & 0x04) ? "T" : "E";
2162 x = (opcode & 0x08) ? "T" : "E";
2164 snprintf(instruction->text, 128,
2165 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2167 x, y, z, arm_condition_strings[cond]);
2169 /* NOTE: strictly speaking, the next 1-4 instructions should
2170 * now be displayed with the relevant conditional suffix...
2176 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2178 /* clear fields, to avoid confusion */
2179 memset(instruction, 0, sizeof(arm_instruction_t));
2180 instruction->opcode = opcode;
2181 instruction->instruction_size = 2;
2183 if ((opcode & 0xe000) == 0x0000)
2185 /* add/substract register or immediate */
2186 if ((opcode & 0x1800) == 0x1800)
2187 return evaluate_add_sub_thumb(opcode, address, instruction);
2188 /* shift by immediate */
2190 return evaluate_shift_imm_thumb(opcode, address, instruction);
2193 /* Add/substract/compare/move immediate */
2194 if ((opcode & 0xe000) == 0x2000)
2196 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2199 /* Data processing instructions */
2200 if ((opcode & 0xf800) == 0x4000)
2202 return evaluate_data_proc_thumb(opcode, address, instruction);
2205 /* Load from literal pool */
2206 if ((opcode & 0xf800) == 0x4800)
2208 return evaluate_load_literal_thumb(opcode, address, instruction);
2211 /* Load/Store register offset */
2212 if ((opcode & 0xf000) == 0x5000)
2214 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2217 /* Load/Store immediate offset */
2218 if (((opcode & 0xe000) == 0x6000)
2219 ||((opcode & 0xf000) == 0x8000))
2221 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2224 /* Load/Store from/to stack */
2225 if ((opcode & 0xf000) == 0x9000)
2227 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2231 if ((opcode & 0xf000) == 0xa000)
2233 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2237 if ((opcode & 0xf000) == 0xb000)
2239 switch ((opcode >> 8) & 0x0f) {
2241 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2246 return evaluate_cb_thumb(opcode, address, instruction);
2248 return evaluate_extend_thumb(opcode, address, instruction);
2253 return evaluate_load_store_multiple_thumb(opcode, address,
2256 return evaluate_cps_thumb(opcode, address, instruction);
2258 if ((opcode & 0x00c0) == 0x0080)
2260 return evaluate_byterev_thumb(opcode, address, instruction);
2262 return evaluate_breakpoint_thumb(opcode, address, instruction);
2264 if (opcode & 0x000f)
2265 return evaluate_ifthen_thumb(opcode, address,
2268 return evaluate_hint_thumb(opcode, address,
2272 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2273 snprintf(instruction->text, 128,
2274 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2279 /* Load/Store multiple */
2280 if ((opcode & 0xf000) == 0xc000)
2282 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2285 /* Conditional branch + SWI */
2286 if ((opcode & 0xf000) == 0xd000)
2288 return evaluate_cond_branch_thumb(opcode, address, instruction);
2291 if ((opcode & 0xe000) == 0xe000)
2293 /* Undefined instructions */
2294 if ((opcode & 0xf801) == 0xe801)
2296 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2297 snprintf(instruction->text, 128,
2298 "0x%8.8" PRIx32 " 0x%8.8x\t"
2299 "UNDEFINED INSTRUCTION",
2304 { /* Branch to offset */
2305 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2309 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2313 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2314 arm_instruction_t *instruction, char *cp)
2317 unsigned b21 = 1 << 21;
2318 unsigned b22 = 1 << 22;
2320 /* instead of combining two smaller 16-bit branch instructions,
2321 * Thumb2 uses only one larger 32-bit instruction.
2323 offset = opcode & 0x7ff;
2324 offset |= (opcode & 0x03ff0000) >> 5;
2325 if (opcode & (1 << 26)) {
2326 offset |= 0xff << 23;
2327 if ((opcode & (1 << 11)) == 0)
2329 if ((opcode & (1 << 13)) == 0)
2332 if (opcode & (1 << 11))
2334 if (opcode & (1 << 13))
2342 address += offset << 1;
2344 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2345 instruction->info.b_bl_bx_blx.reg_operand = -1;
2346 instruction->info.b_bl_bx_blx.target_address = address;
2347 sprintf(cp, "%s\t%#8.8" PRIx32,
2348 (opcode & (1 << 14)) ? "BL" : "B.W",
2354 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2355 arm_instruction_t *instruction, char *cp)
2358 unsigned b17 = 1 << 17;
2359 unsigned b18 = 1 << 18;
2360 unsigned cond = (opcode >> 22) & 0x0f;
2362 offset = opcode & 0x7ff;
2363 offset |= (opcode & 0x003f0000) >> 5;
2364 if (opcode & (1 << 26)) {
2365 offset |= 0xffff << 19;
2366 if ((opcode & (1 << 11)) == 0)
2368 if ((opcode & (1 << 13)) == 0)
2371 if (opcode & (1 << 11))
2373 if (opcode & (1 << 13))
2380 address += offset << 1;
2382 instruction->type = ARM_B;
2383 instruction->info.b_bl_bx_blx.reg_operand = -1;
2384 instruction->info.b_bl_bx_blx.target_address = address;
2385 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2386 arm_condition_strings[cond],
2392 static const char *special_name(int number)
2394 char *special = "(RESERVED)";
2425 special = "primask";
2428 special = "basepri";
2431 special = "basepri_max";
2434 special = "faultmask";
2437 special = "control";
2443 static int t2ev_hint(uint32_t opcode, uint32_t address,
2444 arm_instruction_t *instruction, char *cp)
2446 const char *mnemonic;
2448 if (opcode & 0x0700) {
2449 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2450 strcpy(cp, "UNDEFINED");
2454 if (opcode & 0x00f0) {
2455 sprintf(cp, "DBG\t#%d", opcode & 0xf);
2459 switch (opcode & 0x0f) {
2464 mnemonic = "YIELD.W";
2476 mnemonic = "HINT.W (UNRECOGNIZED)";
2479 strcpy(cp, mnemonic);
2483 static int t2ev_misc(uint32_t opcode, uint32_t address,
2484 arm_instruction_t *instruction, char *cp)
2486 const char *mnemonic;
2488 switch ((opcode >> 4) & 0x0f) {
2502 return ERROR_INVALID_ARGUMENTS;
2504 strcpy(cp, mnemonic);
2508 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2509 arm_instruction_t *instruction, char *cp)
2511 /* permanently undefined */
2512 if ((opcode & 0x07f07000) == 0x07f02000) {
2513 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2514 strcpy(cp, "UNDEFINED");
2518 switch ((opcode >> 12) & 0x5) {
2521 return t2ev_b_bl(opcode, address, instruction, cp);
2525 if (((opcode >> 23) & 0x07) == 0x07)
2526 return t2ev_cond_b(opcode, address, instruction, cp);
2527 if (opcode & (1 << 26))
2532 switch ((opcode >> 20) & 0x7f) {
2535 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2536 (opcode >> 16) & 0x0f);
2539 return t2ev_hint(opcode, address, instruction, cp);
2541 return t2ev_misc(opcode, address, instruction, cp);
2544 sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
2545 special_name(opcode & 0xff));
2550 return ERROR_INVALID_ARGUMENTS;
2553 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2554 arm_instruction_t *instruction, char *cp)
2556 char *mnemonic = NULL;
2557 int rn = (opcode >> 16) & 0xf;
2558 int rd = (opcode >> 8) & 0xf;
2559 unsigned immed = opcode & 0xff;
2564 /* ARMv7-M: A5.3.2 Modified immediate constants */
2565 func = (opcode >> 11) & 0x0e;
2568 if (opcode & (1 << 26))
2571 /* "Modified" immediates */
2572 switch (func >> 1) {
2579 immed += immed << 16;
2582 immed += immed << 8;
2583 immed += immed << 16;
2587 immed = ror(immed, func);
2590 if (opcode & (1 << 20))
2593 switch ((opcode >> 21) & 0xf) {
2596 instruction->type = ARM_TST;
2602 instruction->type = ARM_AND;
2607 instruction->type = ARM_BIC;
2612 instruction->type = ARM_MOV;
2616 instruction->type = ARM_ORR;
2622 instruction->type = ARM_MVN;
2626 // instruction->type = ARM_ORN;
2632 instruction->type = ARM_TEQ;
2638 instruction->type = ARM_EOR;
2644 instruction->type = ARM_CMN;
2650 instruction->type = ARM_ADD;
2655 instruction->type = ARM_ADC;
2659 instruction->type = ARM_SBC;
2664 instruction->type = ARM_CMP;
2670 instruction->type = ARM_SUB;
2675 instruction->type = ARM_RSB;
2679 return ERROR_INVALID_ARGUMENTS;
2683 sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
2684 mnemonic, rd, immed, immed);
2686 sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
2687 mnemonic, suffix, rd, rn, immed, immed);
2692 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2693 arm_instruction_t *instruction, char *cp)
2695 char *mnemonic = NULL;
2696 int rn = (opcode >> 16) & 0xf;
2697 int rd = (opcode >> 8) & 0xf;
2700 bool is_signed = false;
2702 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2703 if (opcode & (1 << 27))
2706 switch ((opcode >> 20) & 0x1f) {
2723 /* move constant to top 16 bits of register */
2724 immed |= (opcode >> 4) & 0xf000;
2725 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2732 /* signed/unsigned saturated add */
2733 immed = (opcode >> 6) & 0x03;
2734 immed |= (opcode >> 10) & 0x1c;
2735 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2736 is_signed ? "S" : "U",
2737 rd, (opcode & 0x1f) + 1, rn,
2738 (opcode & (1 << 21)) ? "ASR" : "LSL",
2739 immed ? immed : 32);
2745 /* signed/unsigned bitfield extract */
2746 immed = (opcode >> 6) & 0x03;
2747 immed |= (opcode >> 10) & 0x1c;
2748 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2749 is_signed ? "S" : "U",
2751 (opcode & 0x1f) + 1);
2754 immed = (opcode >> 6) & 0x03;
2755 immed |= (opcode >> 10) & 0x1c;
2756 if (rn == 0xf) /* bitfield clear */
2757 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2759 (opcode & 0x1f) + 1 - immed);
2760 else /* bitfield insert */
2761 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2763 (opcode & 0x1f) + 1 - immed);
2766 return ERROR_INVALID_ARGUMENTS;
2769 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2770 rd, rn, immed, immed);
2774 address = thumb_alignpc4(address);
2779 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2780 * not hiding the pc-relative stuff will sometimes be useful.
2782 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2787 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2788 * always set. That means eventual arm_simulate_step() support for Thumb2
2789 * will need work in this area.
2791 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2798 /* clear low bit ... it's set on function pointers */
2801 /* clear fields, to avoid confusion */
2802 memset(instruction, 0, sizeof(arm_instruction_t));
2804 /* read first halfword, see if this is the only one */
2805 retval = target_read_u16(target, address, &op);
2806 if (retval != ERROR_OK)
2809 switch (op & 0xf800) {
2813 /* 32-bit instructions */
2814 instruction->instruction_size = 4;
2816 retval = target_read_u16(target, address + 2, &op);
2817 if (retval != ERROR_OK)
2820 instruction->opcode = opcode;
2823 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2824 return thumb_evaluate_opcode(op, address, instruction);
2827 snprintf(instruction->text, 128,
2828 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
2830 cp = strchr(instruction->text, 0);
2831 retval = ERROR_FAIL;
2833 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
2834 if ((opcode & 0x1a008000) == 0x10000000)
2835 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
2837 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
2838 else if ((opcode & 0x1a008000) == 0x12000000)
2839 retval = t2ev_data_immed(opcode, address, instruction, cp);
2841 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
2842 else if ((opcode & 0x18008000) == 0x10008000)
2843 retval = t2ev_b_misc(opcode, address, instruction, cp);
2845 /* FIXME decode more 32-bit instructions */
2847 if (retval == ERROR_OK)
2850 if (retval == ERROR_INVALID_ARGUMENTS) {
2851 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2852 strcpy(cp, "UNDEFINED OPCODE");
2856 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2858 strcpy(cp, "(32-bit Thumb2 ...)");
2862 int arm_access_size(arm_instruction_t *instruction)
2864 if ((instruction->type == ARM_LDRB)
2865 || (instruction->type == ARM_LDRBT)
2866 || (instruction->type == ARM_LDRSB)
2867 || (instruction->type == ARM_STRB)
2868 || (instruction->type == ARM_STRBT))
2872 else if ((instruction->type == ARM_LDRH)
2873 || (instruction->type == ARM_LDRSH)
2874 || (instruction->type == ARM_STRH))
2878 else if ((instruction->type == ARM_LDR)
2879 || (instruction->type == ARM_LDRT)
2880 || (instruction->type == ARM_STR)
2881 || (instruction->type == ARM_STRT))
2885 else if ((instruction->type == ARM_LDRD)
2886 || (instruction->type == ARM_STRD))
2892 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);