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 ***************************************************************************/
20 #include "arm_disassembler.h"
26 /* textual represenation of the condition field */
27 /* ALways (default) is ommitted (empty string) */
28 char *arm_condition_strings[] =
30 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
33 /* make up for C's missing ROR */
34 u32 ror(u32 value, int places)
36 return (value >> places) | (value << (32 - places));
39 int evaluate_pld(u32 opcode, u32 address, arm_instruction_t *instruction)
42 if ((opcode & 0x0d70f0000) == 0x0550f000)
44 instruction->type = ARM_PLD;
46 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tPLD ...TODO...", address, opcode);
52 instruction->type = ARM_UNDEFINED_INSTRUCTION;
56 ERROR("should never reach this point");
60 int evaluate_swi(u32 opcode, u32 address, arm_instruction_t *instruction)
62 instruction->type = ARM_SWI;
64 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSWI 0x%6.6x", address, opcode, (opcode & 0xffffff));
69 int evaluate_blx_imm(u32 opcode, u32 address, arm_instruction_t *instruction)
74 instruction->type = ARM_BLX;
75 immediate = opcode & 0x00ffffff;
77 /* sign extend 24-bit immediate */
78 if (immediate & 0x00800000)
79 offset = 0xff000000 | immediate;
83 /* shift two bits left */
86 /* odd/event halfword */
87 if (opcode & 0x01000000)
90 instruction->target_address = address + 8 + offset;
92 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX 0x%8.8x", address, opcode, instruction->target_address);
97 int evaluate_b_bl(u32 opcode, u32 address, arm_instruction_t *instruction)
103 immediate = opcode & 0x00ffffff;
104 L = (opcode & 0x01000000) >> 24;
106 /* sign extend 24-bit immediate */
107 if (immediate & 0x00800000)
108 offset = 0xff000000 | immediate;
112 /* shift two bits left */
115 instruction->target_address = address + 8 + offset;
118 instruction->type = ARM_BL;
120 instruction->type = ARM_B;
122 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tB%s%s 0x%8.8x", address, opcode,
123 (L) ? "L" : "", COND(opcode), instruction->target_address);
128 /* Coprocessor load/store and double register transfers */
129 /* both normal and extended instruction space (condition field b1111) */
130 int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instruction)
132 u8 cp_num = (opcode & 0xf00) >> 8;
135 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
137 u8 cp_opcode, Rd, Rn, CRm;
140 cp_opcode = (opcode & 0xf0) >> 4;
141 Rd = (opcode & 0xf000) >> 12;
142 Rn = (opcode & 0xf0000) >> 16;
143 CRm = (opcode & 0xf);
146 if ((opcode & 0x0ff00000) == 0x0c400000)
148 instruction->type = ARM_MCRR;
153 if ((opcode & 0x0ff00000) == 0x0c500000)
155 instruction->type = ARM_MRRC;
159 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, %x, r%i, r%i, c%i",
160 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
162 else /* LDC or STC */
167 char addressing_mode[32];
169 CRd = (opcode & 0xf000) >> 12;
170 Rn = (opcode & 0xf0000) >> 16;
171 offset = (opcode & 0xff);
174 if (opcode & 0x00100000)
176 instruction->type = ARM_LDC;
181 instruction->type = ARM_STC;
185 U = (opcode & 0x00800000) >> 23;
186 N = (opcode & 0x00400000) >> 22;
188 /* addressing modes */
189 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
190 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
191 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
192 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
193 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
194 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
195 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
196 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
198 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s p%i, c%i, %s",
199 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
201 cp_num, CRd, addressing_mode);
207 /* Coprocessor data processing instructions */
208 /* Coprocessor register transfer instructions */
209 /* both normal and extended instruction space (condition field b1111) */
210 int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction)
214 u8 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
216 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
217 cp_num = (opcode & 0xf00) >> 8;
218 CRd_Rd = (opcode & 0xf000) >> 12;
219 CRn = (opcode & 0xf0000) >> 16;
220 CRm = (opcode & 0xf);
221 opcode_2 = (opcode & 0xe0) >> 5;
224 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
226 if (opcode & 0x00100000) /* bit 20 set -> MRC */
228 instruction->type = ARM_MRC;
231 else /* bit 20 not set -> MCR */
233 instruction->type = ARM_MCR;
237 opcode_1 = (opcode & 0x00e00000) >> 21;
239 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
240 address, opcode, mnemonic, cond,
241 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
243 else /* bit 4 not set -> CDP */
245 instruction->type = ARM_CDP;
248 opcode_1 = (opcode & 0x00f00000) >> 20;
250 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
251 address, opcode, mnemonic, cond,
252 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
258 /* Load/store instructions */
259 int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
263 char *operation; /* "LDR" or "STR" */
264 char *suffix; /* "", "B", "T", "BT" */
268 I = (opcode & 0x02000000) >> 25;
269 P = (opcode & 0x01000000) >> 24;
270 U = (opcode & 0x00800000) >> 23;
271 B = (opcode & 0x00400000) >> 22;
272 W = (opcode & 0x00200000) >> 21;
273 L = (opcode & 0x00100000) >> 20;
275 /* target register */
276 Rd = (opcode & 0xf000) >> 12;
279 Rn = (opcode & 0xf0000) >> 16;
281 /* determine operation */
287 /* determine instruction type and suffix */
290 if ((P == 0) && (W == 1))
293 instruction->type = ARM_LDRBT;
295 instruction->type = ARM_STRBT;
301 instruction->type = ARM_LDRB;
303 instruction->type = ARM_STRB;
309 if ((P == 0) && (W == 1))
312 instruction->type = ARM_LDRT;
314 instruction->type = ARM_STRT;
320 instruction->type = ARM_LDR;
322 instruction->type = ARM_STR;
327 if (!I) /* #+-<offset_12> */
329 u32 offset_12 = (opcode & 0xfff);
330 snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_12);
332 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
337 shift_imm = (opcode & 0xf80) >> 7;
338 shift = (opcode & 0x60) >> 5;
341 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
343 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
345 else /* +-<Rm>, <Shift>, #<shift_imm> */
347 if (shift == 0x0) /* LSL */
349 snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
351 else if (shift == 0x1) /* LSR */
353 snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
355 else if (shift == 0x2) /* ASR */
357 snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
359 else if (shift == 0x3) /* ROR or RRX */
361 if (shift_imm == 0x0) /* RRX */
362 snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
364 snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
371 if (W == 0) /* offset */
373 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
374 address, opcode, operation, COND(opcode), suffix,
377 else /* pre-indexed */
379 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
380 address, opcode, operation, COND(opcode), suffix,
384 else /* post-indexed */
386 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
387 address, opcode, operation, COND(opcode), suffix,
394 /* Miscellaneous load/store instructions */
395 int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
397 u8 P, U, I, W, L, S, H;
399 char *operation; /* "LDR" or "STR" */
400 char *suffix; /* "H", "SB", "SH", "D" */
404 P = (opcode & 0x01000000) >> 24;
405 U = (opcode & 0x00800000) >> 23;
406 I = (opcode & 0x00400000) >> 22;
407 W = (opcode & 0x00200000) >> 21;
408 L = (opcode & 0x00100000) >> 20;
409 S = (opcode & 0x00000040) >> 6;
410 H = (opcode & 0x00000020) >> 5;
412 /* target register */
413 Rd = (opcode & 0xf000) >> 12;
416 Rn = (opcode & 0xf0000) >> 16;
418 /* determine instruction type and suffix */
426 instruction->type = ARM_LDRSH;
432 instruction->type = ARM_LDRSB;
436 else /* there are no signed stores, so this is used to encode double-register load/stores */
442 instruction->type = ARM_STRD;
447 instruction->type = ARM_LDRD;
457 instruction->type = ARM_LDRH;
462 instruction->type = ARM_STRH;
466 if (I) /* Immediate offset/index (#+-<offset_8>)*/
468 u32 offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
469 snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_8);
471 else /* Register offset/index (+-<Rm>) */
475 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
480 if (W == 0) /* offset */
482 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
483 address, opcode, operation, COND(opcode), suffix,
486 else /* pre-indexed */
488 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
489 address, opcode, operation, COND(opcode), suffix,
493 else /* post-indexed */
495 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
496 address, opcode, operation, COND(opcode), suffix,
503 /* Load/store multiples instructions */
504 int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
506 u8 P, U, S, W, L, Rn;
508 char *addressing_mode;
515 P = (opcode & 0x01000000) >> 24;
516 U = (opcode & 0x00800000) >> 23;
517 S = (opcode & 0x00400000) >> 22;
518 W = (opcode & 0x00200000) >> 21;
519 L = (opcode & 0x00100000) >> 20;
520 register_list = (opcode & 0xffff);
521 Rn = (opcode & 0xf0000) >> 16;
525 instruction->type = ARM_LDM;
530 instruction->type = ARM_STM;
537 addressing_mode = "IB";
539 addressing_mode = "DB";
544 addressing_mode = "IA";
546 addressing_mode = "DA";
549 reg_list_p = reg_list;
550 for (i = 0; i <= 15; i++)
552 if ((register_list >> i) & 1)
557 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
561 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
566 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i%s, {%s}%s",
567 address, opcode, mnemonic, COND(opcode), addressing_mode,
568 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
573 /* Multiplies, extra load/stores */
574 int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *instruction)
576 /* Multiply (accumulate) (long) and Swap/swap byte */
577 if ((opcode & 0x000000f0) == 0x00000090)
579 /* Multiply (accumulate) */
580 if ((opcode & 0x0f800000) == 0x00000000)
582 u8 Rm, Rs, Rn, Rd, S;
584 Rs = (opcode & 0xf00) >> 8;
585 Rn = (opcode & 0xf000) >> 12;
586 Rd = (opcode & 0xf0000) >> 16;
587 S = (opcode & 0x00100000) >> 20;
589 /* examine A bit (accumulate) */
590 if (opcode & 0x00200000)
592 instruction->type = ARM_MLA;
593 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMLA%s%s r%i, r%i, r%i, r%i",
594 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
598 instruction->type = ARM_MUL;
599 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMUL%s%s r%i, r%i, r%i",
600 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
606 /* Multiply (accumulate) long */
607 if ((opcode & 0x0f800000) == 0x00800000)
610 u8 Rm, Rs, RdHi, RdLow, S;
612 Rs = (opcode & 0xf00) >> 8;
613 RdHi = (opcode & 0xf000) >> 12;
614 RdLow = (opcode & 0xf0000) >> 16;
615 S = (opcode & 0x00100000) >> 20;
617 switch ((opcode & 0x00600000) >> 21)
620 instruction->type = ARM_UMULL;
624 instruction->type = ARM_UMLAL;
628 instruction->type = ARM_SMULL;
632 instruction->type = ARM_SMLAL;
637 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, r%i, r%i",
638 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
639 RdLow, RdHi, Rm, Rs);
645 if ((opcode & 0x0f800000) == 0x01000000)
649 Rd = (opcode & 0xf000) >> 12;
650 Rn = (opcode & 0xf0000) >> 16;
653 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
655 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, [r%i]",
656 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
662 return evaluate_misc_load_store(opcode, address, instruction);
665 int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
667 int R = (opcode & 0x00400000) >> 22;
668 char *PSR = (R) ? "SPSR" : "CPSR";
670 /* Move register to status register (MSR) */
671 if (opcode & 0x00200000)
673 instruction->type = ARM_MSR;
675 /* immediate variant */
676 if (opcode & 0x02000000)
678 u8 immediate = (opcode & 0xff);
679 u8 rotate = (opcode & 0xf00);
681 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
682 address, opcode, COND(opcode), PSR,
683 (opcode & 0x10000) ? "c" : "",
684 (opcode & 0x20000) ? "x" : "",
685 (opcode & 0x40000) ? "s" : "",
686 (opcode & 0x80000) ? "f" : "",
687 ror(immediate, (rotate * 2))
690 else /* register variant */
692 u8 Rm = opcode & 0xf;
693 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
694 address, opcode, COND(opcode), PSR,
695 (opcode & 0x10000) ? "c" : "",
696 (opcode & 0x20000) ? "x" : "",
697 (opcode & 0x40000) ? "s" : "",
698 (opcode & 0x80000) ? "f" : "",
704 else /* Move status register to register (MRS) */
708 instruction->type = ARM_MRS;
709 Rd = (opcode & 0x0000f000) >> 12;
711 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMRS%s r%i, %s",
712 address, opcode, COND(opcode), Rd, PSR);
718 /* Miscellaneous instructions */
719 int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
722 if ((opcode & 0x000000f0) == 0x00000000)
724 evaluate_mrs_msr(opcode, address, instruction);
728 if ((opcode & 0x006000f0) == 0x00200010)
731 instruction->type = ARM_BX;
734 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBX%s r%i",
735 address, opcode, COND(opcode), Rm);
739 if ((opcode & 0x0060000f0) == 0x00300010)
742 instruction->type = ARM_CLZ;
744 Rd = (opcode & 0xf000) >> 12;
746 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tCLZ%s r%i, r%i",
747 address, opcode, COND(opcode), Rd, Rm);
751 if ((opcode & 0x0060000f0) == 0x00200030)
754 instruction->type = ARM_BLX;
757 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
758 address, opcode, COND(opcode), Rm);
761 /* Enhanced DSP add/subtracts */
762 if ((opcode & 0x0000000f0) == 0x00000050)
767 Rd = (opcode & 0xf000) >> 12;
768 Rn = (opcode & 0xf0000) >> 16;
770 switch ((opcode & 0x00600000) >> 21)
773 instruction->type = ARM_QADD;
777 instruction->type = ARM_QSUB;
781 instruction->type = ARM_QDADD;
785 instruction->type = ARM_QDSUB;
790 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, r%i",
791 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
794 /* Software breakpoints */
795 if ((opcode & 0x0000000f0) == 0x00000070)
798 instruction->type = ARM_BKPT;
799 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
801 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBKPT 0x%4.4x",
802 address, opcode, immediate);
805 /* Enhanced DSP multiplies */
806 if ((opcode & 0x000000090) == 0x00000080)
808 int x = (opcode & 0x20) >> 5;
809 int y = (opcode & 0x40) >> 6;
812 if ((opcode & 0x00600000) == 0x00000000)
815 instruction->type = ARM_SMLAxy;
816 Rd = (opcode & 0xf0000) >> 16;
818 Rs = (opcode & 0xf00) >> 8;
819 Rn = (opcode & 0xf000) >> 12;
821 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
822 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
827 if ((opcode & 0x00600000) == 0x00400000)
829 u8 RdLow, RdHi, Rm, Rs;
830 instruction->type = ARM_SMLAxy;
831 RdHi = (opcode & 0xf0000) >> 16;
832 RdLow = (opcode & 0xf000) >> 12;
834 Rs = (opcode & 0xf00) >> 8;
836 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
837 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
838 RdLow, RdHi, Rm, Rs);
842 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
845 instruction->type = ARM_SMLAWy;
846 Rd = (opcode & 0xf0000) >> 16;
848 Rs = (opcode & 0xf00) >> 8;
849 Rn = (opcode & 0xf000) >> 12;
851 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLAW%s%s r%i, r%i, r%i, r%i",
852 address, opcode, (y) ? "T" : "B", COND(opcode),
857 if ((opcode & 0x00600000) == 0x00300000)
860 instruction->type = ARM_SMULxy;
861 Rd = (opcode & 0xf0000) >> 16;
863 Rs = (opcode & 0xf00) >> 8;
865 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s%s r%i, r%i, r%i",
866 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
871 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
874 instruction->type = ARM_SMULWy;
875 Rd = (opcode & 0xf0000) >> 16;
877 Rs = (opcode & 0xf00) >> 8;
879 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s r%i, r%i, r%i",
880 address, opcode, (y) ? "T" : "B", COND(opcode),
888 int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
892 char shifter_operand[32];
894 I = (opcode & 0x02000000) >> 25;
895 op = (opcode & 0x01e00000) >> 21;
896 S = (opcode & 0x00100000) >> 20;
898 Rd = (opcode & 0xf000) >> 12;
899 Rn = (opcode & 0xf0000) >> 16;
904 instruction->type = ARM_AND;
908 instruction->type = ARM_EOR;
912 instruction->type = ARM_SUB;
916 instruction->type = ARM_RSB;
920 instruction->type = ARM_ADD;
924 instruction->type = ARM_ADC;
928 instruction->type = ARM_SBC;
932 instruction->type = ARM_RSC;
936 instruction->type = ARM_TST;
940 instruction->type = ARM_TEQ;
944 instruction->type = ARM_CMP;
948 instruction->type = ARM_CMN;
952 instruction->type = ARM_ORR;
956 instruction->type = ARM_MOV;
960 instruction->type = ARM_BIC;
964 instruction->type = ARM_MVN;
969 if (I) /* immediate shifter operand (#<immediate>)*/
971 u8 immed_8 = opcode & 0xff;
972 u8 rotate_imm = (opcode & 0xf00) >> 8;
975 immediate = ror(immed_8, rotate_imm * 2);
977 snprintf(shifter_operand, 32, "#0x%x", immediate);
979 else /* register-based shifter operand */
982 shift = (opcode & 0x60) >> 5;
985 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
988 shift_imm = (opcode & 0xf80) >> 7;
991 if ((shift_imm == 0x0) && (shift == 0x0))
993 snprintf(shifter_operand, 32, "r%i", Rm);
997 if (shift == 0x0) /* LSL */
999 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1001 else if (shift == 0x1) /* LSR */
1003 if (shift_imm == 0x0)
1005 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1007 else if (shift == 0x2) /* ASR */
1009 if (shift_imm == 0x0)
1011 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1013 else if (shift == 0x3) /* ROR or RRX */
1015 if (shift_imm == 0x0) /* RRX */
1016 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1018 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1022 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1024 u8 Rs = (opcode & 0xf00) >> 8;
1026 if (shift == 0x0) /* LSL */
1028 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1030 else if (shift == 0x1) /* LSR */
1032 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1034 else if (shift == 0x2) /* ASR */
1036 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1038 else if (shift == 0x3) /* ROR or RRX */
1040 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1045 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1047 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, %s",
1048 address, opcode, mnemonic, COND(opcode),
1049 (S) ? "S" : "", Rd, Rn, shifter_operand);
1051 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1053 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
1054 address, opcode, mnemonic, COND(opcode),
1055 (S) ? "S" : "", Rd, shifter_operand);
1057 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1059 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, %s",
1060 address, opcode, mnemonic, COND(opcode),
1061 Rn, shifter_operand);
1067 int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
1069 /* clear fields, to avoid confusion */
1070 bzero(instruction, sizeof(arm_instruction_t));
1071 instruction->opcode = opcode;
1073 /* catch opcodes with condition field [31:28] = b1111 */
1074 if ((opcode & 0xf0000000) == 0xf0000000)
1076 /* Undefined instruction (or ARMv5E cache preload PLD) */
1077 if ((opcode & 0x08000000) == 0x00000000)
1078 return evaluate_pld(opcode, address, instruction);
1080 /* Undefined instruction */
1081 if ((opcode & 0x0e000000) == 0x08000000)
1083 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1084 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1088 /* Branch and branch with link and change to Thumb */
1089 if ((opcode & 0x0e000000) == 0x0a000000)
1090 return evaluate_blx_imm(opcode, address, instruction);
1092 /* Extended coprocessor opcode space (ARMv5 and higher )*/
1093 /* Coprocessor load/store and double register transfers */
1094 if ((opcode & 0x0e000000) == 0x0c000000)
1095 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1097 /* Coprocessor data processing */
1098 if ((opcode & 0x0f000100) == 0x0c000000)
1099 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1101 /* Coprocessor register transfers */
1102 if ((opcode & 0x0f000010) == 0x0c000010)
1103 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1105 /* Undefined instruction */
1106 if ((opcode & 0x0f000000) == 0x0f000000)
1108 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1109 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1114 /* catch opcodes with [27:25] = b000 */
1115 if ((opcode & 0x0e000000) == 0x00000000)
1117 /* Multiplies, extra load/stores */
1118 if ((opcode & 0x00000090) == 0x00000090)
1119 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1121 /* Miscellaneous instructions */
1122 if ((opcode & 0x0f900000) == 0x01000000)
1123 return evaluate_misc_instr(opcode, address, instruction);
1125 return evaluate_data_proc(opcode, address, instruction);
1128 /* catch opcodes with [27:25] = b001 */
1129 if ((opcode & 0x0e000000) == 0x02000000)
1131 /* Undefined instruction */
1132 if ((opcode & 0x0fb00000) == 0x03000000)
1134 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1135 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1139 /* Move immediate to status register */
1140 if ((opcode & 0x0fb00000) == 0x03200000)
1141 return evaluate_mrs_msr(opcode, address, instruction);
1143 return evaluate_data_proc(opcode, address, instruction);
1147 /* catch opcodes with [27:25] = b010 */
1148 if ((opcode & 0x0e000000) == 0x04000000)
1150 /* Load/store immediate offset */
1151 return evaluate_load_store(opcode, address, instruction);
1154 /* catch opcodes with [27:25] = b011 */
1155 if ((opcode & 0x0e000000) == 0x04000000)
1157 /* Undefined instruction */
1158 if ((opcode & 0x00000010) == 0x00000010)
1160 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1161 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1165 /* Load/store register offset */
1166 return evaluate_load_store(opcode, address, instruction);
1170 /* catch opcodes with [27:25] = b100 */
1171 if ((opcode & 0x0e000000) == 0x08000000)
1173 /* Load/store multiple */
1174 return evaluate_ldm_stm(opcode, address, instruction);
1177 /* catch opcodes with [27:25] = b101 */
1178 if ((opcode & 0x0e000000) == 0x0a000000)
1180 /* Branch and branch with link */
1181 return evaluate_b_bl(opcode, address, instruction);
1184 /* catch opcodes with [27:25] = b110 */
1185 if ((opcode & 0x0e000000) == 0x0a000000)
1187 /* Coprocessor load/store and double register transfers */
1188 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1191 /* catch opcodes with [27:25] = b111 */
1192 if ((opcode & 0x0e000000) == 0x0e000000)
1194 /* Software interrupt */
1195 if ((opcode & 0x0f000000) == 0x0f000000)
1196 return evaluate_swi(opcode, address, instruction);
1198 /* Coprocessor data processing */
1199 if ((opcode & 0x0f000010) == 0x0e000000)
1200 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1202 /* Coprocessor register transfers */
1203 if ((opcode & 0x0f000010) == 0x0e000010)
1204 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1207 ERROR("should never reach this point");