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
)
75 instruction
->type
= ARM_BLX
;
76 immediate
= opcode
& 0x00ffffff;
78 /* sign extend 24-bit immediate */
79 if (immediate
& 0x00800000)
80 offset
= 0xff000000 | immediate
;
84 /* shift two bits left */
87 /* odd/event halfword */
88 if (opcode
& 0x01000000)
91 target_address
= address
+ 8 + offset
;
93 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBLX 0x%8.8x", address
, opcode
, target_address
);
95 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
96 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
101 int evaluate_b_bl(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
108 immediate
= opcode
& 0x00ffffff;
109 L
= (opcode
& 0x01000000) >> 24;
111 /* sign extend 24-bit immediate */
112 if (immediate
& 0x00800000)
113 offset
= 0xff000000 | immediate
;
117 /* shift two bits left */
120 target_address
= address
+ 8 + offset
;
123 instruction
->type
= ARM_BL
;
125 instruction
->type
= ARM_B
;
127 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tB%s%s 0x%8.8x", address
, opcode
,
128 (L
) ? "L" : "", COND(opcode
), target_address
);
130 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
131 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
136 /* Coprocessor load/store and double register transfers */
137 /* both normal and extended instruction space (condition field b1111) */
138 int evaluate_ldc_stc_mcrr_mrrc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
140 u8 cp_num
= (opcode
& 0xf00) >> 8;
143 if (((opcode
& 0x0ff00000) == 0x0c400000) || ((opcode
& 0x0ff00000) == 0x0c400000))
145 u8 cp_opcode
, Rd
, Rn
, CRm
;
148 cp_opcode
= (opcode
& 0xf0) >> 4;
149 Rd
= (opcode
& 0xf000) >> 12;
150 Rn
= (opcode
& 0xf0000) >> 16;
151 CRm
= (opcode
& 0xf);
154 if ((opcode
& 0x0ff00000) == 0x0c400000)
156 instruction
->type
= ARM_MCRR
;
161 if ((opcode
& 0x0ff00000) == 0x0c500000)
163 instruction
->type
= ARM_MRRC
;
167 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, %x, r%i, r%i, c%i",
168 address
, opcode
, mnemonic
, COND(opcode
), cp_num
, cp_opcode
, Rd
, Rn
, CRm
);
170 else /* LDC or STC */
175 char addressing_mode
[32];
177 CRd
= (opcode
& 0xf000) >> 12;
178 Rn
= (opcode
& 0xf0000) >> 16;
179 offset
= (opcode
& 0xff);
182 if (opcode
& 0x00100000)
184 instruction
->type
= ARM_LDC
;
189 instruction
->type
= ARM_STC
;
193 U
= (opcode
& 0x00800000) >> 23;
194 N
= (opcode
& 0x00400000) >> 22;
196 /* addressing modes */
197 if ((opcode
& 0x01200000) == 0x01000000) /* immediate offset */
198 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]", Rn
, (U
) ? "" : "-", offset
);
199 else if ((opcode
& 0x01200000) == 0x01200000) /* immediate pre-indexed */
200 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]!", Rn
, (U
) ? "" : "-", offset
);
201 else if ((opcode
& 0x01200000) == 0x00200000) /* immediate post-indexed */
202 snprintf(addressing_mode
, 32, "[r%i], #%s0x%2.2x*4", Rn
, (U
) ? "" : "-", offset
);
203 else if ((opcode
& 0x01200000) == 0x00000000) /* unindexed */
204 snprintf(addressing_mode
, 32, "[r%i], #0x%2.2x", Rn
, offset
);
206 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s p%i, c%i, %s",
207 address
, opcode
, mnemonic
, ((opcode
& 0xf0000000) == 0xf0000000) ? COND(opcode
) : "2",
209 cp_num
, CRd
, addressing_mode
);
215 /* Coprocessor data processing instructions */
216 /* Coprocessor register transfer instructions */
217 /* both normal and extended instruction space (condition field b1111) */
218 int evaluate_cdp_mcr_mrc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
222 u8 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
;
224 cond
= ((opcode
& 0xf0000000) == 0xf0000000) ? "2" : COND(opcode
);
225 cp_num
= (opcode
& 0xf00) >> 8;
226 CRd_Rd
= (opcode
& 0xf000) >> 12;
227 CRn
= (opcode
& 0xf0000) >> 16;
228 CRm
= (opcode
& 0xf);
229 opcode_2
= (opcode
& 0xe0) >> 5;
232 if (opcode
& 0x00000010) /* bit 4 set -> MRC/MCR */
234 if (opcode
& 0x00100000) /* bit 20 set -> MRC */
236 instruction
->type
= ARM_MRC
;
239 else /* bit 20 not set -> MCR */
241 instruction
->type
= ARM_MCR
;
245 opcode_1
= (opcode
& 0x00e00000) >> 21;
247 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",
248 address
, opcode
, mnemonic
, cond
,
249 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
251 else /* bit 4 not set -> CDP */
253 instruction
->type
= ARM_CDP
;
256 opcode_1
= (opcode
& 0x00f00000) >> 20;
258 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",
259 address
, opcode
, mnemonic
, cond
,
260 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
266 /* Load/store instructions */
267 int evaluate_load_store(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
271 char *operation
; /* "LDR" or "STR" */
272 char *suffix
; /* "", "B", "T", "BT" */
276 I
= (opcode
& 0x02000000) >> 25;
277 P
= (opcode
& 0x01000000) >> 24;
278 U
= (opcode
& 0x00800000) >> 23;
279 B
= (opcode
& 0x00400000) >> 22;
280 W
= (opcode
& 0x00200000) >> 21;
281 L
= (opcode
& 0x00100000) >> 20;
283 /* target register */
284 Rd
= (opcode
& 0xf000) >> 12;
287 Rn
= (opcode
& 0xf0000) >> 16;
289 instruction
->info
.load_store
.Rd
= Rd
;
290 instruction
->info
.load_store
.Rn
= Rn
;
291 instruction
->info
.load_store
.U
= U
;
293 /* determine operation */
299 /* determine instruction type and suffix */
302 if ((P
== 0) && (W
== 1))
305 instruction
->type
= ARM_LDRBT
;
307 instruction
->type
= ARM_STRBT
;
313 instruction
->type
= ARM_LDRB
;
315 instruction
->type
= ARM_STRB
;
321 if ((P
== 0) && (W
== 1))
324 instruction
->type
= ARM_LDRT
;
326 instruction
->type
= ARM_STRT
;
332 instruction
->type
= ARM_LDR
;
334 instruction
->type
= ARM_STR
;
339 if (!I
) /* #+-<offset_12> */
341 u32 offset_12
= (opcode
& 0xfff);
342 snprintf(offset
, 32, "#%s0x%x", (U
) ? "" : "-", offset_12
);
344 instruction
->info
.load_store
.offset_mode
= 0;
345 instruction
->info
.load_store
.offset
.offset
= offset_12
;
347 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
352 shift_imm
= (opcode
& 0xf80) >> 7;
353 shift
= (opcode
& 0x60) >> 5;
356 /* LSR encodes a shift by 32 bit as 0x0 */
357 if ((shift
== 0x1) && (shift_imm
== 0x0))
360 /* ASR encodes a shift by 32 bit as 0x0 */
361 if ((shift
== 0x2) && (shift_imm
== 0x0))
364 /* ROR by 32 bit is actually a RRX */
365 if ((shift
== 0x3) && (shift_imm
== 0x0))
368 instruction
->info
.load_store
.offset_mode
= 1;
369 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
370 instruction
->info
.load_store
.offset
.reg
.shift
= shift
;
371 instruction
->info
.load_store
.offset
.reg
.shift_imm
= shift_imm
;
373 if ((shift_imm
== 0x0) && (shift
== 0x0)) /* +-<Rm> */
375 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
377 else /* +-<Rm>, <Shift>, #<shift_imm> */
382 snprintf(offset
, 32, "%sr%i, LSL #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
385 snprintf(offset
, 32, "%sr%i, LSR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
388 snprintf(offset
, 32, "%sr%i, ASR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
391 snprintf(offset
, 32, "%sr%i, ROR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
394 snprintf(offset
, 32, "%sr%i, RRX", (U
) ? "" : "-", Rm
);
402 if (W
== 0) /* offset */
404 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
405 address
, opcode
, operation
, COND(opcode
), suffix
,
408 instruction
->info
.load_store
.index_mode
= 0;
410 else /* pre-indexed */
412 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
413 address
, opcode
, operation
, COND(opcode
), suffix
,
416 instruction
->info
.load_store
.index_mode
= 1;
419 else /* post-indexed */
421 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
422 address
, opcode
, operation
, COND(opcode
), suffix
,
425 instruction
->info
.load_store
.index_mode
= 2;
431 /* Miscellaneous load/store instructions */
432 int evaluate_misc_load_store(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
434 u8 P
, U
, I
, W
, L
, S
, H
;
436 char *operation
; /* "LDR" or "STR" */
437 char *suffix
; /* "H", "SB", "SH", "D" */
441 P
= (opcode
& 0x01000000) >> 24;
442 U
= (opcode
& 0x00800000) >> 23;
443 I
= (opcode
& 0x00400000) >> 22;
444 W
= (opcode
& 0x00200000) >> 21;
445 L
= (opcode
& 0x00100000) >> 20;
446 S
= (opcode
& 0x00000040) >> 6;
447 H
= (opcode
& 0x00000020) >> 5;
449 /* target register */
450 Rd
= (opcode
& 0xf000) >> 12;
453 Rn
= (opcode
& 0xf0000) >> 16;
455 instruction
->info
.load_store
.Rd
= Rd
;
456 instruction
->info
.load_store
.Rn
= Rn
;
457 instruction
->info
.load_store
.U
= U
;
459 /* determine instruction type and suffix */
467 instruction
->type
= ARM_LDRSH
;
473 instruction
->type
= ARM_LDRSB
;
477 else /* there are no signed stores, so this is used to encode double-register load/stores */
483 instruction
->type
= ARM_STRD
;
488 instruction
->type
= ARM_LDRD
;
498 instruction
->type
= ARM_LDRH
;
503 instruction
->type
= ARM_STRH
;
507 if (I
) /* Immediate offset/index (#+-<offset_8>)*/
509 u32 offset_8
= ((opcode
& 0xf00) >> 4) | (opcode
& 0xf);
510 snprintf(offset
, 32, "#%s0x%x", (U
) ? "" : "-", offset_8
);
512 instruction
->info
.load_store
.offset_mode
= 0;
513 instruction
->info
.load_store
.offset
.offset
= offset_8
;
515 else /* Register offset/index (+-<Rm>) */
519 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
521 instruction
->info
.load_store
.offset_mode
= 1;
522 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
523 instruction
->info
.load_store
.offset
.reg
.shift
= 0x0;
524 instruction
->info
.load_store
.offset
.reg
.shift_imm
= 0x0;
529 if (W
== 0) /* offset */
531 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
532 address
, opcode
, operation
, COND(opcode
), suffix
,
535 instruction
->info
.load_store
.index_mode
= 0;
537 else /* pre-indexed */
539 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
540 address
, opcode
, operation
, COND(opcode
), suffix
,
543 instruction
->info
.load_store
.index_mode
= 1;
546 else /* post-indexed */
548 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
549 address
, opcode
, operation
, COND(opcode
), suffix
,
552 instruction
->info
.load_store
.index_mode
= 2;
558 /* Load/store multiples instructions */
559 int evaluate_ldm_stm(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
561 u8 P
, U
, S
, W
, L
, Rn
;
563 char *addressing_mode
;
570 P
= (opcode
& 0x01000000) >> 24;
571 U
= (opcode
& 0x00800000) >> 23;
572 S
= (opcode
& 0x00400000) >> 22;
573 W
= (opcode
& 0x00200000) >> 21;
574 L
= (opcode
& 0x00100000) >> 20;
575 register_list
= (opcode
& 0xffff);
576 Rn
= (opcode
& 0xf0000) >> 16;
578 instruction
->info
.load_store_multiple
.Rn
= Rn
;
579 instruction
->info
.load_store_multiple
.register_list
= register_list
;
580 instruction
->info
.load_store_multiple
.S
= S
;
581 instruction
->info
.load_store_multiple
.W
= W
;
585 instruction
->type
= ARM_LDM
;
590 instruction
->type
= ARM_STM
;
598 instruction
->info
.load_store_multiple
.addressing_mode
= 1;
599 addressing_mode
= "IB";
603 instruction
->info
.load_store_multiple
.addressing_mode
= 3;
604 addressing_mode
= "DB";
611 instruction
->info
.load_store_multiple
.addressing_mode
= 0;
612 addressing_mode
= "IA";
616 instruction
->info
.load_store_multiple
.addressing_mode
= 2;
617 addressing_mode
= "DA";
621 reg_list_p
= reg_list
;
622 for (i
= 0; i
<= 15; i
++)
624 if ((register_list
>> i
) & 1)
629 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), "r%i", i
);
633 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), ", r%i", i
);
638 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i%s, {%s}%s",
639 address
, opcode
, mnemonic
, COND(opcode
), addressing_mode
,
640 Rn
, (W
) ? "!" : "", reg_list
, (S
) ? "^" : "");
645 /* Multiplies, extra load/stores */
646 int evaluate_mul_and_extra_ld_st(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
648 /* Multiply (accumulate) (long) and Swap/swap byte */
649 if ((opcode
& 0x000000f0) == 0x00000090)
651 /* Multiply (accumulate) */
652 if ((opcode
& 0x0f800000) == 0x00000000)
654 u8 Rm
, Rs
, Rn
, Rd
, S
;
656 Rs
= (opcode
& 0xf00) >> 8;
657 Rn
= (opcode
& 0xf000) >> 12;
658 Rd
= (opcode
& 0xf0000) >> 16;
659 S
= (opcode
& 0x00100000) >> 20;
661 /* examine A bit (accumulate) */
662 if (opcode
& 0x00200000)
664 instruction
->type
= ARM_MLA
;
665 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMLA%s%s r%i, r%i, r%i, r%i",
666 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
, Rn
);
670 instruction
->type
= ARM_MUL
;
671 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMUL%s%s r%i, r%i, r%i",
672 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
);
678 /* Multiply (accumulate) long */
679 if ((opcode
& 0x0f800000) == 0x00800000)
682 u8 Rm
, Rs
, RdHi
, RdLow
, S
;
684 Rs
= (opcode
& 0xf00) >> 8;
685 RdHi
= (opcode
& 0xf000) >> 12;
686 RdLow
= (opcode
& 0xf0000) >> 16;
687 S
= (opcode
& 0x00100000) >> 20;
689 switch ((opcode
& 0x00600000) >> 21)
692 instruction
->type
= ARM_UMULL
;
696 instruction
->type
= ARM_UMLAL
;
700 instruction
->type
= ARM_SMULL
;
704 instruction
->type
= ARM_SMLAL
;
709 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, r%i, r%i",
710 address
, opcode
, mnemonic
, COND(opcode
), (S
) ? "S" : "",
711 RdLow
, RdHi
, Rm
, Rs
);
717 if ((opcode
& 0x0f800000) == 0x01000000)
721 Rd
= (opcode
& 0xf000) >> 12;
722 Rn
= (opcode
& 0xf0000) >> 16;
725 instruction
->type
= (opcode
& 0x00400000) ? ARM_SWPB
: ARM_SWP
;
727 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, [r%i]",
728 address
, opcode
, (opcode
& 0x00400000) ? "SWPB" : "SWP", COND(opcode
), Rd
, Rm
, Rn
);
734 return evaluate_misc_load_store(opcode
, address
, instruction
);
737 int evaluate_mrs_msr(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
739 int R
= (opcode
& 0x00400000) >> 22;
740 char *PSR
= (R
) ? "SPSR" : "CPSR";
742 /* Move register to status register (MSR) */
743 if (opcode
& 0x00200000)
745 instruction
->type
= ARM_MSR
;
747 /* immediate variant */
748 if (opcode
& 0x02000000)
750 u8 immediate
= (opcode
& 0xff);
751 u8 rotate
= (opcode
& 0xf00);
753 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
754 address
, opcode
, COND(opcode
), PSR
,
755 (opcode
& 0x10000) ? "c" : "",
756 (opcode
& 0x20000) ? "x" : "",
757 (opcode
& 0x40000) ? "s" : "",
758 (opcode
& 0x80000) ? "f" : "",
759 ror(immediate
, (rotate
* 2))
762 else /* register variant */
764 u8 Rm
= opcode
& 0xf;
765 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
766 address
, opcode
, COND(opcode
), PSR
,
767 (opcode
& 0x10000) ? "c" : "",
768 (opcode
& 0x20000) ? "x" : "",
769 (opcode
& 0x40000) ? "s" : "",
770 (opcode
& 0x80000) ? "f" : "",
776 else /* Move status register to register (MRS) */
780 instruction
->type
= ARM_MRS
;
781 Rd
= (opcode
& 0x0000f000) >> 12;
783 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMRS%s r%i, %s",
784 address
, opcode
, COND(opcode
), Rd
, PSR
);
790 /* Miscellaneous instructions */
791 int evaluate_misc_instr(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
794 if ((opcode
& 0x000000f0) == 0x00000000)
796 evaluate_mrs_msr(opcode
, address
, instruction
);
800 if ((opcode
& 0x006000f0) == 0x00200010)
803 instruction
->type
= ARM_BX
;
806 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBX%s r%i",
807 address
, opcode
, COND(opcode
), Rm
);
809 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
810 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
814 if ((opcode
& 0x0060000f0) == 0x00300010)
817 instruction
->type
= ARM_CLZ
;
819 Rd
= (opcode
& 0xf000) >> 12;
821 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tCLZ%s r%i, r%i",
822 address
, opcode
, COND(opcode
), Rd
, Rm
);
826 if ((opcode
& 0x0060000f0) == 0x00200030)
829 instruction
->type
= ARM_BLX
;
832 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
833 address
, opcode
, COND(opcode
), Rm
);
836 /* Enhanced DSP add/subtracts */
837 if ((opcode
& 0x0000000f0) == 0x00000050)
842 Rd
= (opcode
& 0xf000) >> 12;
843 Rn
= (opcode
& 0xf0000) >> 16;
845 switch ((opcode
& 0x00600000) >> 21)
848 instruction
->type
= ARM_QADD
;
852 instruction
->type
= ARM_QSUB
;
856 instruction
->type
= ARM_QDADD
;
860 instruction
->type
= ARM_QDSUB
;
865 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, r%i",
866 address
, opcode
, mnemonic
, COND(opcode
), Rd
, Rm
, Rn
);
869 /* Software breakpoints */
870 if ((opcode
& 0x0000000f0) == 0x00000070)
873 instruction
->type
= ARM_BKPT
;
874 immediate
= ((opcode
& 0x000fff00) >> 4) | (opcode
& 0xf);
876 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBKPT 0x%4.4x",
877 address
, opcode
, immediate
);
880 /* Enhanced DSP multiplies */
881 if ((opcode
& 0x000000090) == 0x00000080)
883 int x
= (opcode
& 0x20) >> 5;
884 int y
= (opcode
& 0x40) >> 6;
887 if ((opcode
& 0x00600000) == 0x00000000)
890 instruction
->type
= ARM_SMLAxy
;
891 Rd
= (opcode
& 0xf0000) >> 16;
893 Rs
= (opcode
& 0xf00) >> 8;
894 Rn
= (opcode
& 0xf000) >> 12;
896 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
897 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
902 if ((opcode
& 0x00600000) == 0x00400000)
904 u8 RdLow
, RdHi
, Rm
, Rs
;
905 instruction
->type
= ARM_SMLAxy
;
906 RdHi
= (opcode
& 0xf0000) >> 16;
907 RdLow
= (opcode
& 0xf000) >> 12;
909 Rs
= (opcode
& 0xf00) >> 8;
911 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
912 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
913 RdLow
, RdHi
, Rm
, Rs
);
917 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 0))
920 instruction
->type
= ARM_SMLAWy
;
921 Rd
= (opcode
& 0xf0000) >> 16;
923 Rs
= (opcode
& 0xf00) >> 8;
924 Rn
= (opcode
& 0xf000) >> 12;
926 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLAW%s%s r%i, r%i, r%i, r%i",
927 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
932 if ((opcode
& 0x00600000) == 0x00300000)
935 instruction
->type
= ARM_SMULxy
;
936 Rd
= (opcode
& 0xf0000) >> 16;
938 Rs
= (opcode
& 0xf00) >> 8;
940 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s%s r%i, r%i, r%i",
941 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
946 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 1))
949 instruction
->type
= ARM_SMULWy
;
950 Rd
= (opcode
& 0xf0000) >> 16;
952 Rs
= (opcode
& 0xf00) >> 8;
954 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s r%i, r%i, r%i",
955 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
963 int evaluate_data_proc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
967 char shifter_operand
[32];
969 I
= (opcode
& 0x02000000) >> 25;
970 op
= (opcode
& 0x01e00000) >> 21;
971 S
= (opcode
& 0x00100000) >> 20;
973 Rd
= (opcode
& 0xf000) >> 12;
974 Rn
= (opcode
& 0xf0000) >> 16;
976 instruction
->info
.data_proc
.Rd
= Rd
;
977 instruction
->info
.data_proc
.Rn
= Rn
;
978 instruction
->info
.data_proc
.S
= S
;
983 instruction
->type
= ARM_AND
;
987 instruction
->type
= ARM_EOR
;
991 instruction
->type
= ARM_SUB
;
995 instruction
->type
= ARM_RSB
;
999 instruction
->type
= ARM_ADD
;
1003 instruction
->type
= ARM_ADC
;
1007 instruction
->type
= ARM_SBC
;
1011 instruction
->type
= ARM_RSC
;
1015 instruction
->type
= ARM_TST
;
1019 instruction
->type
= ARM_TEQ
;
1023 instruction
->type
= ARM_CMP
;
1027 instruction
->type
= ARM_CMN
;
1031 instruction
->type
= ARM_ORR
;
1035 instruction
->type
= ARM_MOV
;
1039 instruction
->type
= ARM_BIC
;
1043 instruction
->type
= ARM_MVN
;
1048 if (I
) /* immediate shifter operand (#<immediate>)*/
1050 u8 immed_8
= opcode
& 0xff;
1051 u8 rotate_imm
= (opcode
& 0xf00) >> 8;
1054 immediate
= ror(immed_8
, rotate_imm
* 2);
1056 snprintf(shifter_operand
, 32, "#0x%x", immediate
);
1058 instruction
->info
.data_proc
.variant
= 0;
1059 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= immediate
;
1061 else /* register-based shifter operand */
1064 shift
= (opcode
& 0x60) >> 5;
1065 Rm
= (opcode
& 0xf);
1067 if ((opcode
& 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1070 shift_imm
= (opcode
& 0xf80) >> 7;
1072 instruction
->info
.data_proc
.variant
= 1;
1073 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1074 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= shift_imm
;
1075 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= shift
;
1077 if ((shift_imm
== 0x0) && (shift
== 0x0))
1079 snprintf(shifter_operand
, 32, "r%i", Rm
);
1083 if (shift
== 0x0) /* LSL */
1085 snprintf(shifter_operand
, 32, "r%i, LSL #0x%x", Rm
, shift_imm
);
1087 else if (shift
== 0x1) /* LSR */
1089 if (shift_imm
== 0x0)
1091 snprintf(shifter_operand
, 32, "r%i, LSR #0x%x", Rm
, shift_imm
);
1093 else if (shift
== 0x2) /* ASR */
1095 if (shift_imm
== 0x0)
1097 snprintf(shifter_operand
, 32, "r%i, ASR #0x%x", Rm
, shift_imm
);
1099 else if (shift
== 0x3) /* ROR or RRX */
1101 if (shift_imm
== 0x0) /* RRX */
1102 snprintf(shifter_operand
, 32, "r%i, RRX", Rm
);
1104 snprintf(shifter_operand
, 32, "r%i, ROR #0x%x", Rm
, shift_imm
);
1108 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1110 u8 Rs
= (opcode
& 0xf00) >> 8;
1112 instruction
->info
.data_proc
.variant
= 2;
1113 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rm
;
1114 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rs
;
1115 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= shift
;
1117 if (shift
== 0x0) /* LSL */
1119 snprintf(shifter_operand
, 32, "r%i, LSL r%i", Rm
, Rs
);
1121 else if (shift
== 0x1) /* LSR */
1123 snprintf(shifter_operand
, 32, "r%i, LSR r%i", Rm
, Rs
);
1125 else if (shift
== 0x2) /* ASR */
1127 snprintf(shifter_operand
, 32, "r%i, ASR r%i", Rm
, Rs
);
1129 else if (shift
== 0x3) /* ROR or RRX */
1131 snprintf(shifter_operand
, 32, "r%i, ROR r%i", Rm
, Rs
);
1136 if ((op
< 0x8) || (op
== 0xc) || (op
== 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1138 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, %s",
1139 address
, opcode
, mnemonic
, COND(opcode
),
1140 (S
) ? "S" : "", Rd
, Rn
, shifter_operand
);
1142 else if ((op
== 0xd) || (op
== 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1144 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
1145 address
, opcode
, mnemonic
, COND(opcode
),
1146 (S
) ? "S" : "", Rd
, shifter_operand
);
1148 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1150 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, %s",
1151 address
, opcode
, mnemonic
, COND(opcode
),
1152 Rn
, shifter_operand
);
1158 int evaluate_opcode(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
1160 /* clear fields, to avoid confusion */
1161 memset(instruction
, 0, sizeof(arm_instruction_t
));
1162 instruction
->opcode
= opcode
;
1164 /* catch opcodes with condition field [31:28] = b1111 */
1165 if ((opcode
& 0xf0000000) == 0xf0000000)
1167 /* Undefined instruction (or ARMv5E cache preload PLD) */
1168 if ((opcode
& 0x08000000) == 0x00000000)
1169 return evaluate_pld(opcode
, address
, instruction
);
1171 /* Undefined instruction */
1172 if ((opcode
& 0x0e000000) == 0x08000000)
1174 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1175 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1179 /* Branch and branch with link and change to Thumb */
1180 if ((opcode
& 0x0e000000) == 0x0a000000)
1181 return evaluate_blx_imm(opcode
, address
, instruction
);
1183 /* Extended coprocessor opcode space (ARMv5 and higher )*/
1184 /* Coprocessor load/store and double register transfers */
1185 if ((opcode
& 0x0e000000) == 0x0c000000)
1186 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1188 /* Coprocessor data processing */
1189 if ((opcode
& 0x0f000100) == 0x0c000000)
1190 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1192 /* Coprocessor register transfers */
1193 if ((opcode
& 0x0f000010) == 0x0c000010)
1194 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1196 /* Undefined instruction */
1197 if ((opcode
& 0x0f000000) == 0x0f000000)
1199 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1200 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1205 /* catch opcodes with [27:25] = b000 */
1206 if ((opcode
& 0x0e000000) == 0x00000000)
1208 /* Multiplies, extra load/stores */
1209 if ((opcode
& 0x00000090) == 0x00000090)
1210 return evaluate_mul_and_extra_ld_st(opcode
, address
, instruction
);
1212 /* Miscellaneous instructions */
1213 if ((opcode
& 0x0f900000) == 0x01000000)
1214 return evaluate_misc_instr(opcode
, address
, instruction
);
1216 return evaluate_data_proc(opcode
, address
, instruction
);
1219 /* catch opcodes with [27:25] = b001 */
1220 if ((opcode
& 0x0e000000) == 0x02000000)
1222 /* Undefined instruction */
1223 if ((opcode
& 0x0fb00000) == 0x03000000)
1225 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1226 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1230 /* Move immediate to status register */
1231 if ((opcode
& 0x0fb00000) == 0x03200000)
1232 return evaluate_mrs_msr(opcode
, address
, instruction
);
1234 return evaluate_data_proc(opcode
, address
, instruction
);
1238 /* catch opcodes with [27:25] = b010 */
1239 if ((opcode
& 0x0e000000) == 0x04000000)
1241 /* Load/store immediate offset */
1242 return evaluate_load_store(opcode
, address
, instruction
);
1245 /* catch opcodes with [27:25] = b011 */
1246 if ((opcode
& 0x0e000000) == 0x04000000)
1248 /* Undefined instruction */
1249 if ((opcode
& 0x00000010) == 0x00000010)
1251 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1252 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1256 /* Load/store register offset */
1257 return evaluate_load_store(opcode
, address
, instruction
);
1261 /* catch opcodes with [27:25] = b100 */
1262 if ((opcode
& 0x0e000000) == 0x08000000)
1264 /* Load/store multiple */
1265 return evaluate_ldm_stm(opcode
, address
, instruction
);
1268 /* catch opcodes with [27:25] = b101 */
1269 if ((opcode
& 0x0e000000) == 0x0a000000)
1271 /* Branch and branch with link */
1272 return evaluate_b_bl(opcode
, address
, instruction
);
1275 /* catch opcodes with [27:25] = b110 */
1276 if ((opcode
& 0x0e000000) == 0x0a000000)
1278 /* Coprocessor load/store and double register transfers */
1279 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1282 /* catch opcodes with [27:25] = b111 */
1283 if ((opcode
& 0x0e000000) == 0x0e000000)
1285 /* Software interrupt */
1286 if ((opcode
& 0x0f000000) == 0x0f000000)
1287 return evaluate_swi(opcode
, address
, instruction
);
1289 /* Coprocessor data processing */
1290 if ((opcode
& 0x0f000010) == 0x0e000000)
1291 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1293 /* Coprocessor register transfers */
1294 if ((opcode
& 0x0f000010) == 0x0e000010)
1295 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1298 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)