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");
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)