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 ***************************************************************************/
24 #include "arm_disassembler.h"
30 /* textual represenation of the condition field */
31 /* ALways (default) is ommitted (empty string) */
32 char *arm_condition_strings
[] =
34 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
37 /* make up for C's missing ROR */
38 u32
ror(u32 value
, int places
)
40 return (value
>> places
) | (value
<< (32 - places
));
43 int evaluate_pld(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
46 if ((opcode
& 0x0d70f0000) == 0x0550f000)
48 instruction
->type
= ARM_PLD
;
50 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tPLD ...TODO...", address
, opcode
);
56 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
60 ERROR("should never reach this point");
64 int evaluate_swi(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
66 instruction
->type
= ARM_SWI
;
68 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSWI 0x%6.6x", address
, opcode
, (opcode
& 0xffffff));
73 int evaluate_blx_imm(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
79 instruction
->type
= ARM_BLX
;
80 immediate
= opcode
& 0x00ffffff;
82 /* sign extend 24-bit immediate */
83 if (immediate
& 0x00800000)
84 offset
= 0xff000000 | immediate
;
88 /* shift two bits left */
91 /* odd/event halfword */
92 if (opcode
& 0x01000000)
95 target_address
= address
+ 8 + offset
;
97 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBLX 0x%8.8x", address
, opcode
, target_address
);
99 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
100 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
105 int evaluate_b_bl(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
112 immediate
= opcode
& 0x00ffffff;
113 L
= (opcode
& 0x01000000) >> 24;
115 /* sign extend 24-bit immediate */
116 if (immediate
& 0x00800000)
117 offset
= 0xff000000 | immediate
;
121 /* shift two bits left */
124 target_address
= address
+ 8 + offset
;
127 instruction
->type
= ARM_BL
;
129 instruction
->type
= ARM_B
;
131 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tB%s%s 0x%8.8x", address
, opcode
,
132 (L
) ? "L" : "", COND(opcode
), target_address
);
134 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
135 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
140 /* Coprocessor load/store and double register transfers */
141 /* both normal and extended instruction space (condition field b1111) */
142 int evaluate_ldc_stc_mcrr_mrrc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
144 u8 cp_num
= (opcode
& 0xf00) >> 8;
147 if (((opcode
& 0x0ff00000) == 0x0c400000) || ((opcode
& 0x0ff00000) == 0x0c400000))
149 u8 cp_opcode
, Rd
, Rn
, CRm
;
152 cp_opcode
= (opcode
& 0xf0) >> 4;
153 Rd
= (opcode
& 0xf000) >> 12;
154 Rn
= (opcode
& 0xf0000) >> 16;
155 CRm
= (opcode
& 0xf);
158 if ((opcode
& 0x0ff00000) == 0x0c400000)
160 instruction
->type
= ARM_MCRR
;
165 if ((opcode
& 0x0ff00000) == 0x0c500000)
167 instruction
->type
= ARM_MRRC
;
171 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, %x, r%i, r%i, c%i",
172 address
, opcode
, mnemonic
, COND(opcode
), cp_num
, cp_opcode
, Rd
, Rn
, CRm
);
174 else /* LDC or STC */
179 char addressing_mode
[32];
181 CRd
= (opcode
& 0xf000) >> 12;
182 Rn
= (opcode
& 0xf0000) >> 16;
183 offset
= (opcode
& 0xff);
186 if (opcode
& 0x00100000)
188 instruction
->type
= ARM_LDC
;
193 instruction
->type
= ARM_STC
;
197 U
= (opcode
& 0x00800000) >> 23;
198 N
= (opcode
& 0x00400000) >> 22;
200 /* addressing modes */
201 if ((opcode
& 0x01200000) == 0x01000000) /* immediate offset */
202 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]", Rn
, (U
) ? "" : "-", offset
);
203 else if ((opcode
& 0x01200000) == 0x01200000) /* immediate pre-indexed */
204 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]!", Rn
, (U
) ? "" : "-", offset
);
205 else if ((opcode
& 0x01200000) == 0x00200000) /* immediate post-indexed */
206 snprintf(addressing_mode
, 32, "[r%i], #%s0x%2.2x*4", Rn
, (U
) ? "" : "-", offset
);
207 else if ((opcode
& 0x01200000) == 0x00000000) /* unindexed */
208 snprintf(addressing_mode
, 32, "[r%i], #0x%2.2x", Rn
, offset
);
210 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s p%i, c%i, %s",
211 address
, opcode
, mnemonic
, ((opcode
& 0xf0000000) == 0xf0000000) ? COND(opcode
) : "2",
213 cp_num
, CRd
, addressing_mode
);
219 /* Coprocessor data processing instructions */
220 /* Coprocessor register transfer instructions */
221 /* both normal and extended instruction space (condition field b1111) */
222 int evaluate_cdp_mcr_mrc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
226 u8 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
;
228 cond
= ((opcode
& 0xf0000000) == 0xf0000000) ? "2" : COND(opcode
);
229 cp_num
= (opcode
& 0xf00) >> 8;
230 CRd_Rd
= (opcode
& 0xf000) >> 12;
231 CRn
= (opcode
& 0xf0000) >> 16;
232 CRm
= (opcode
& 0xf);
233 opcode_2
= (opcode
& 0xe0) >> 5;
236 if (opcode
& 0x00000010) /* bit 4 set -> MRC/MCR */
238 if (opcode
& 0x00100000) /* bit 20 set -> MRC */
240 instruction
->type
= ARM_MRC
;
243 else /* bit 20 not set -> MCR */
245 instruction
->type
= ARM_MCR
;
249 opcode_1
= (opcode
& 0x00e00000) >> 21;
251 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",
252 address
, opcode
, mnemonic
, cond
,
253 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
255 else /* bit 4 not set -> CDP */
257 instruction
->type
= ARM_CDP
;
260 opcode_1
= (opcode
& 0x00f00000) >> 20;
262 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",
263 address
, opcode
, mnemonic
, cond
,
264 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
270 /* Load/store instructions */
271 int evaluate_load_store(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
275 char *operation
; /* "LDR" or "STR" */
276 char *suffix
; /* "", "B", "T", "BT" */
280 I
= (opcode
& 0x02000000) >> 25;
281 P
= (opcode
& 0x01000000) >> 24;
282 U
= (opcode
& 0x00800000) >> 23;
283 B
= (opcode
& 0x00400000) >> 22;
284 W
= (opcode
& 0x00200000) >> 21;
285 L
= (opcode
& 0x00100000) >> 20;
287 /* target register */
288 Rd
= (opcode
& 0xf000) >> 12;
291 Rn
= (opcode
& 0xf0000) >> 16;
293 instruction
->info
.load_store
.Rd
= Rd
;
294 instruction
->info
.load_store
.Rn
= Rn
;
295 instruction
->info
.load_store
.U
= U
;
297 /* determine operation */
303 /* determine instruction type and suffix */
306 if ((P
== 0) && (W
== 1))
309 instruction
->type
= ARM_LDRBT
;
311 instruction
->type
= ARM_STRBT
;
317 instruction
->type
= ARM_LDRB
;
319 instruction
->type
= ARM_STRB
;
325 if ((P
== 0) && (W
== 1))
328 instruction
->type
= ARM_LDRT
;
330 instruction
->type
= ARM_STRT
;
336 instruction
->type
= ARM_LDR
;
338 instruction
->type
= ARM_STR
;
343 if (!I
) /* #+-<offset_12> */
345 u32 offset_12
= (opcode
& 0xfff);
346 snprintf(offset
, 32, "#%s0x%x", (U
) ? "" : "-", offset_12
);
348 instruction
->info
.load_store
.offset_mode
= 0;
349 instruction
->info
.load_store
.offset
.offset
= offset_12
;
351 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
356 shift_imm
= (opcode
& 0xf80) >> 7;
357 shift
= (opcode
& 0x60) >> 5;
360 /* LSR encodes a shift by 32 bit as 0x0 */
361 if ((shift
== 0x1) && (shift_imm
== 0x0))
364 /* ASR encodes a shift by 32 bit as 0x0 */
365 if ((shift
== 0x2) && (shift_imm
== 0x0))
368 /* ROR by 32 bit is actually a RRX */
369 if ((shift
== 0x3) && (shift_imm
== 0x0))
372 instruction
->info
.load_store
.offset_mode
= 1;
373 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
374 instruction
->info
.load_store
.offset
.reg
.shift
= shift
;
375 instruction
->info
.load_store
.offset
.reg
.shift_imm
= shift_imm
;
377 if ((shift_imm
== 0x0) && (shift
== 0x0)) /* +-<Rm> */
379 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
381 else /* +-<Rm>, <Shift>, #<shift_imm> */
386 snprintf(offset
, 32, "%sr%i, LSL #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
389 snprintf(offset
, 32, "%sr%i, LSR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
392 snprintf(offset
, 32, "%sr%i, ASR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
395 snprintf(offset
, 32, "%sr%i, ROR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
398 snprintf(offset
, 32, "%sr%i, RRX", (U
) ? "" : "-", Rm
);
406 if (W
== 0) /* offset */
408 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
409 address
, opcode
, operation
, COND(opcode
), suffix
,
412 instruction
->info
.load_store
.index_mode
= 0;
414 else /* pre-indexed */
416 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
417 address
, opcode
, operation
, COND(opcode
), suffix
,
420 instruction
->info
.load_store
.index_mode
= 1;
423 else /* post-indexed */
425 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
426 address
, opcode
, operation
, COND(opcode
), suffix
,
429 instruction
->info
.load_store
.index_mode
= 2;
435 /* Miscellaneous load/store instructions */
436 int evaluate_misc_load_store(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
438 u8 P
, U
, I
, W
, L
, S
, H
;
440 char *operation
; /* "LDR" or "STR" */
441 char *suffix
; /* "H", "SB", "SH", "D" */
445 P
= (opcode
& 0x01000000) >> 24;
446 U
= (opcode
& 0x00800000) >> 23;
447 I
= (opcode
& 0x00400000) >> 22;
448 W
= (opcode
& 0x00200000) >> 21;
449 L
= (opcode
& 0x00100000) >> 20;
450 S
= (opcode
& 0x00000040) >> 6;
451 H
= (opcode
& 0x00000020) >> 5;
453 /* target register */
454 Rd
= (opcode
& 0xf000) >> 12;
457 Rn
= (opcode
& 0xf0000) >> 16;
459 instruction
->info
.load_store
.Rd
= Rd
;
460 instruction
->info
.load_store
.Rn
= Rn
;
461 instruction
->info
.load_store
.U
= U
;
463 /* determine instruction type and suffix */
471 instruction
->type
= ARM_LDRSH
;
477 instruction
->type
= ARM_LDRSB
;
481 else /* there are no signed stores, so this is used to encode double-register load/stores */
487 instruction
->type
= ARM_STRD
;
492 instruction
->type
= ARM_LDRD
;
502 instruction
->type
= ARM_LDRH
;
507 instruction
->type
= ARM_STRH
;
511 if (I
) /* Immediate offset/index (#+-<offset_8>)*/
513 u32 offset_8
= ((opcode
& 0xf00) >> 4) | (opcode
& 0xf);
514 snprintf(offset
, 32, "#%s0x%x", (U
) ? "" : "-", offset_8
);
516 instruction
->info
.load_store
.offset_mode
= 0;
517 instruction
->info
.load_store
.offset
.offset
= offset_8
;
519 else /* Register offset/index (+-<Rm>) */
523 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
525 instruction
->info
.load_store
.offset_mode
= 1;
526 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
527 instruction
->info
.load_store
.offset
.reg
.shift
= 0x0;
528 instruction
->info
.load_store
.offset
.reg
.shift_imm
= 0x0;
533 if (W
== 0) /* offset */
535 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
536 address
, opcode
, operation
, COND(opcode
), suffix
,
539 instruction
->info
.load_store
.index_mode
= 0;
541 else /* pre-indexed */
543 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
544 address
, opcode
, operation
, COND(opcode
), suffix
,
547 instruction
->info
.load_store
.index_mode
= 1;
550 else /* post-indexed */
552 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
553 address
, opcode
, operation
, COND(opcode
), suffix
,
556 instruction
->info
.load_store
.index_mode
= 2;
562 /* Load/store multiples instructions */
563 int evaluate_ldm_stm(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
565 u8 P
, U
, S
, W
, L
, Rn
;
567 char *addressing_mode
;
574 P
= (opcode
& 0x01000000) >> 24;
575 U
= (opcode
& 0x00800000) >> 23;
576 S
= (opcode
& 0x00400000) >> 22;
577 W
= (opcode
& 0x00200000) >> 21;
578 L
= (opcode
& 0x00100000) >> 20;
579 register_list
= (opcode
& 0xffff);
580 Rn
= (opcode
& 0xf0000) >> 16;
582 instruction
->info
.load_store_multiple
.Rn
= Rn
;
583 instruction
->info
.load_store_multiple
.register_list
= register_list
;
584 instruction
->info
.load_store_multiple
.S
= S
;
585 instruction
->info
.load_store_multiple
.W
= W
;
589 instruction
->type
= ARM_LDM
;
594 instruction
->type
= ARM_STM
;
602 instruction
->info
.load_store_multiple
.addressing_mode
= 1;
603 addressing_mode
= "IB";
607 instruction
->info
.load_store_multiple
.addressing_mode
= 3;
608 addressing_mode
= "DB";
615 instruction
->info
.load_store_multiple
.addressing_mode
= 0;
616 addressing_mode
= "IA";
620 instruction
->info
.load_store_multiple
.addressing_mode
= 2;
621 addressing_mode
= "DA";
625 reg_list_p
= reg_list
;
626 for (i
= 0; i
<= 15; i
++)
628 if ((register_list
>> i
) & 1)
633 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), "r%i", i
);
637 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), ", r%i", i
);
642 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i%s, {%s}%s",
643 address
, opcode
, mnemonic
, COND(opcode
), addressing_mode
,
644 Rn
, (W
) ? "!" : "", reg_list
, (S
) ? "^" : "");
649 /* Multiplies, extra load/stores */
650 int evaluate_mul_and_extra_ld_st(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
652 /* Multiply (accumulate) (long) and Swap/swap byte */
653 if ((opcode
& 0x000000f0) == 0x00000090)
655 /* Multiply (accumulate) */
656 if ((opcode
& 0x0f800000) == 0x00000000)
658 u8 Rm
, Rs
, Rn
, Rd
, S
;
660 Rs
= (opcode
& 0xf00) >> 8;
661 Rn
= (opcode
& 0xf000) >> 12;
662 Rd
= (opcode
& 0xf0000) >> 16;
663 S
= (opcode
& 0x00100000) >> 20;
665 /* examine A bit (accumulate) */
666 if (opcode
& 0x00200000)
668 instruction
->type
= ARM_MLA
;
669 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMLA%s%s r%i, r%i, r%i, r%i",
670 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
, Rn
);
674 instruction
->type
= ARM_MUL
;
675 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMUL%s%s r%i, r%i, r%i",
676 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
);
682 /* Multiply (accumulate) long */
683 if ((opcode
& 0x0f800000) == 0x00800000)
685 char* mnemonic
= NULL
;
686 u8 Rm
, Rs
, RdHi
, RdLow
, S
;
688 Rs
= (opcode
& 0xf00) >> 8;
689 RdHi
= (opcode
& 0xf000) >> 12;
690 RdLow
= (opcode
& 0xf0000) >> 16;
691 S
= (opcode
& 0x00100000) >> 20;
693 switch ((opcode
& 0x00600000) >> 21)
696 instruction
->type
= ARM_UMULL
;
700 instruction
->type
= ARM_UMLAL
;
704 instruction
->type
= ARM_SMULL
;
708 instruction
->type
= ARM_SMLAL
;
713 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, r%i, r%i",
714 address
, opcode
, mnemonic
, COND(opcode
), (S
) ? "S" : "",
715 RdLow
, RdHi
, Rm
, Rs
);
721 if ((opcode
& 0x0f800000) == 0x01000000)
725 Rd
= (opcode
& 0xf000) >> 12;
726 Rn
= (opcode
& 0xf0000) >> 16;
729 instruction
->type
= (opcode
& 0x00400000) ? ARM_SWPB
: ARM_SWP
;
731 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, [r%i]",
732 address
, opcode
, (opcode
& 0x00400000) ? "SWPB" : "SWP", COND(opcode
), Rd
, Rm
, Rn
);
738 return evaluate_misc_load_store(opcode
, address
, instruction
);
741 int evaluate_mrs_msr(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
743 int R
= (opcode
& 0x00400000) >> 22;
744 char *PSR
= (R
) ? "SPSR" : "CPSR";
746 /* Move register to status register (MSR) */
747 if (opcode
& 0x00200000)
749 instruction
->type
= ARM_MSR
;
751 /* immediate variant */
752 if (opcode
& 0x02000000)
754 u8 immediate
= (opcode
& 0xff);
755 u8 rotate
= (opcode
& 0xf00);
757 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
758 address
, opcode
, COND(opcode
), PSR
,
759 (opcode
& 0x10000) ? "c" : "",
760 (opcode
& 0x20000) ? "x" : "",
761 (opcode
& 0x40000) ? "s" : "",
762 (opcode
& 0x80000) ? "f" : "",
763 ror(immediate
, (rotate
* 2))
766 else /* register variant */
768 u8 Rm
= opcode
& 0xf;
769 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
770 address
, opcode
, COND(opcode
), PSR
,
771 (opcode
& 0x10000) ? "c" : "",
772 (opcode
& 0x20000) ? "x" : "",
773 (opcode
& 0x40000) ? "s" : "",
774 (opcode
& 0x80000) ? "f" : "",
780 else /* Move status register to register (MRS) */
784 instruction
->type
= ARM_MRS
;
785 Rd
= (opcode
& 0x0000f000) >> 12;
787 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tMRS%s r%i, %s",
788 address
, opcode
, COND(opcode
), Rd
, PSR
);
794 /* Miscellaneous instructions */
795 int evaluate_misc_instr(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
798 if ((opcode
& 0x000000f0) == 0x00000000)
800 evaluate_mrs_msr(opcode
, address
, instruction
);
804 if ((opcode
& 0x006000f0) == 0x00200010)
807 instruction
->type
= ARM_BX
;
810 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBX%s r%i",
811 address
, opcode
, COND(opcode
), Rm
);
813 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
814 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
818 if ((opcode
& 0x0060000f0) == 0x00300010)
821 instruction
->type
= ARM_CLZ
;
823 Rd
= (opcode
& 0xf000) >> 12;
825 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tCLZ%s r%i, r%i",
826 address
, opcode
, COND(opcode
), Rd
, Rm
);
830 if ((opcode
& 0x0060000f0) == 0x00200030)
833 instruction
->type
= ARM_BLX
;
836 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
837 address
, opcode
, COND(opcode
), Rm
);
839 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
840 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
843 /* Enhanced DSP add/subtracts */
844 if ((opcode
& 0x0000000f0) == 0x00000050)
847 char *mnemonic
= NULL
;
849 Rd
= (opcode
& 0xf000) >> 12;
850 Rn
= (opcode
& 0xf0000) >> 16;
852 switch ((opcode
& 0x00600000) >> 21)
855 instruction
->type
= ARM_QADD
;
859 instruction
->type
= ARM_QSUB
;
863 instruction
->type
= ARM_QDADD
;
867 instruction
->type
= ARM_QDSUB
;
872 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, r%i",
873 address
, opcode
, mnemonic
, COND(opcode
), Rd
, Rm
, Rn
);
876 /* Software breakpoints */
877 if ((opcode
& 0x0000000f0) == 0x00000070)
880 instruction
->type
= ARM_BKPT
;
881 immediate
= ((opcode
& 0x000fff00) >> 4) | (opcode
& 0xf);
883 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tBKPT 0x%4.4x",
884 address
, opcode
, immediate
);
887 /* Enhanced DSP multiplies */
888 if ((opcode
& 0x000000090) == 0x00000080)
890 int x
= (opcode
& 0x20) >> 5;
891 int y
= (opcode
& 0x40) >> 6;
894 if ((opcode
& 0x00600000) == 0x00000000)
897 instruction
->type
= ARM_SMLAxy
;
898 Rd
= (opcode
& 0xf0000) >> 16;
900 Rs
= (opcode
& 0xf00) >> 8;
901 Rn
= (opcode
& 0xf000) >> 12;
903 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
904 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
909 if ((opcode
& 0x00600000) == 0x00400000)
911 u8 RdLow
, RdHi
, Rm
, Rs
;
912 instruction
->type
= ARM_SMLAxy
;
913 RdHi
= (opcode
& 0xf0000) >> 16;
914 RdLow
= (opcode
& 0xf000) >> 12;
916 Rs
= (opcode
& 0xf00) >> 8;
918 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
919 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
920 RdLow
, RdHi
, Rm
, Rs
);
924 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 0))
927 instruction
->type
= ARM_SMLAWy
;
928 Rd
= (opcode
& 0xf0000) >> 16;
930 Rs
= (opcode
& 0xf00) >> 8;
931 Rn
= (opcode
& 0xf000) >> 12;
933 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMLAW%s%s r%i, r%i, r%i, r%i",
934 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
939 if ((opcode
& 0x00600000) == 0x00300000)
942 instruction
->type
= ARM_SMULxy
;
943 Rd
= (opcode
& 0xf0000) >> 16;
945 Rs
= (opcode
& 0xf00) >> 8;
947 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s%s r%i, r%i, r%i",
948 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
953 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 1))
956 instruction
->type
= ARM_SMULWy
;
957 Rd
= (opcode
& 0xf0000) >> 16;
959 Rs
= (opcode
& 0xf00) >> 8;
961 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s r%i, r%i, r%i",
962 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
970 int evaluate_data_proc(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
973 char *mnemonic
= NULL
;
974 char shifter_operand
[32];
976 I
= (opcode
& 0x02000000) >> 25;
977 op
= (opcode
& 0x01e00000) >> 21;
978 S
= (opcode
& 0x00100000) >> 20;
980 Rd
= (opcode
& 0xf000) >> 12;
981 Rn
= (opcode
& 0xf0000) >> 16;
983 instruction
->info
.data_proc
.Rd
= Rd
;
984 instruction
->info
.data_proc
.Rn
= Rn
;
985 instruction
->info
.data_proc
.S
= S
;
990 instruction
->type
= ARM_AND
;
994 instruction
->type
= ARM_EOR
;
998 instruction
->type
= ARM_SUB
;
1002 instruction
->type
= ARM_RSB
;
1006 instruction
->type
= ARM_ADD
;
1010 instruction
->type
= ARM_ADC
;
1014 instruction
->type
= ARM_SBC
;
1018 instruction
->type
= ARM_RSC
;
1022 instruction
->type
= ARM_TST
;
1026 instruction
->type
= ARM_TEQ
;
1030 instruction
->type
= ARM_CMP
;
1034 instruction
->type
= ARM_CMN
;
1038 instruction
->type
= ARM_ORR
;
1042 instruction
->type
= ARM_MOV
;
1046 instruction
->type
= ARM_BIC
;
1050 instruction
->type
= ARM_MVN
;
1055 if (I
) /* immediate shifter operand (#<immediate>)*/
1057 u8 immed_8
= opcode
& 0xff;
1058 u8 rotate_imm
= (opcode
& 0xf00) >> 8;
1061 immediate
= ror(immed_8
, rotate_imm
* 2);
1063 snprintf(shifter_operand
, 32, "#0x%x", immediate
);
1065 instruction
->info
.data_proc
.variant
= 0;
1066 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= immediate
;
1068 else /* register-based shifter operand */
1071 shift
= (opcode
& 0x60) >> 5;
1072 Rm
= (opcode
& 0xf);
1074 if ((opcode
& 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1077 shift_imm
= (opcode
& 0xf80) >> 7;
1079 instruction
->info
.data_proc
.variant
= 1;
1080 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1081 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= shift_imm
;
1082 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= shift
;
1084 /* LSR encodes a shift by 32 bit as 0x0 */
1085 if ((shift
== 0x1) && (shift_imm
== 0x0))
1088 /* ASR encodes a shift by 32 bit as 0x0 */
1089 if ((shift
== 0x2) && (shift_imm
== 0x0))
1092 /* ROR by 32 bit is actually a RRX */
1093 if ((shift
== 0x3) && (shift_imm
== 0x0))
1096 if ((shift_imm
== 0x0) && (shift
== 0x0))
1098 snprintf(shifter_operand
, 32, "r%i", Rm
);
1102 if (shift
== 0x0) /* LSL */
1104 snprintf(shifter_operand
, 32, "r%i, LSL #0x%x", Rm
, shift_imm
);
1106 else if (shift
== 0x1) /* LSR */
1108 snprintf(shifter_operand
, 32, "r%i, LSR #0x%x", Rm
, shift_imm
);
1110 else if (shift
== 0x2) /* ASR */
1112 snprintf(shifter_operand
, 32, "r%i, ASR #0x%x", Rm
, shift_imm
);
1114 else if (shift
== 0x3) /* ROR */
1116 snprintf(shifter_operand
, 32, "r%i, ROR #0x%x", Rm
, shift_imm
);
1118 else if (shift
== 0x4) /* RRX */
1120 snprintf(shifter_operand
, 32, "r%i, RRX", Rm
);
1124 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1126 u8 Rs
= (opcode
& 0xf00) >> 8;
1128 instruction
->info
.data_proc
.variant
= 2;
1129 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rm
;
1130 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rs
;
1131 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= shift
;
1133 if (shift
== 0x0) /* LSL */
1135 snprintf(shifter_operand
, 32, "r%i, LSL r%i", Rm
, Rs
);
1137 else if (shift
== 0x1) /* LSR */
1139 snprintf(shifter_operand
, 32, "r%i, LSR r%i", Rm
, Rs
);
1141 else if (shift
== 0x2) /* ASR */
1143 snprintf(shifter_operand
, 32, "r%i, ASR r%i", Rm
, Rs
);
1145 else if (shift
== 0x3) /* ROR */
1147 snprintf(shifter_operand
, 32, "r%i, ROR r%i", Rm
, Rs
);
1152 if ((op
< 0x8) || (op
== 0xc) || (op
== 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1154 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, %s",
1155 address
, opcode
, mnemonic
, COND(opcode
),
1156 (S
) ? "S" : "", Rd
, Rn
, shifter_operand
);
1158 else if ((op
== 0xd) || (op
== 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1160 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
1161 address
, opcode
, mnemonic
, COND(opcode
),
1162 (S
) ? "S" : "", Rd
, shifter_operand
);
1164 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1166 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, %s",
1167 address
, opcode
, mnemonic
, COND(opcode
),
1168 Rn
, shifter_operand
);
1174 int arm_evaluate_opcode(u32 opcode
, u32 address
, arm_instruction_t
*instruction
)
1176 /* clear fields, to avoid confusion */
1177 memset(instruction
, 0, sizeof(arm_instruction_t
));
1178 instruction
->opcode
= opcode
;
1180 /* catch opcodes with condition field [31:28] = b1111 */
1181 if ((opcode
& 0xf0000000) == 0xf0000000)
1183 /* Undefined instruction (or ARMv5E cache preload PLD) */
1184 if ((opcode
& 0x08000000) == 0x00000000)
1185 return evaluate_pld(opcode
, address
, instruction
);
1187 /* Undefined instruction */
1188 if ((opcode
& 0x0e000000) == 0x08000000)
1190 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1191 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1195 /* Branch and branch with link and change to Thumb */
1196 if ((opcode
& 0x0e000000) == 0x0a000000)
1197 return evaluate_blx_imm(opcode
, address
, instruction
);
1199 /* Extended coprocessor opcode space (ARMv5 and higher )*/
1200 /* Coprocessor load/store and double register transfers */
1201 if ((opcode
& 0x0e000000) == 0x0c000000)
1202 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1204 /* Coprocessor data processing */
1205 if ((opcode
& 0x0f000100) == 0x0c000000)
1206 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1208 /* Coprocessor register transfers */
1209 if ((opcode
& 0x0f000010) == 0x0c000010)
1210 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1212 /* Undefined instruction */
1213 if ((opcode
& 0x0f000000) == 0x0f000000)
1215 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1216 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1221 /* catch opcodes with [27:25] = b000 */
1222 if ((opcode
& 0x0e000000) == 0x00000000)
1224 /* Multiplies, extra load/stores */
1225 if ((opcode
& 0x00000090) == 0x00000090)
1226 return evaluate_mul_and_extra_ld_st(opcode
, address
, instruction
);
1228 /* Miscellaneous instructions */
1229 if ((opcode
& 0x0f900000) == 0x01000000)
1230 return evaluate_misc_instr(opcode
, address
, instruction
);
1232 return evaluate_data_proc(opcode
, address
, instruction
);
1235 /* catch opcodes with [27:25] = b001 */
1236 if ((opcode
& 0x0e000000) == 0x02000000)
1238 /* Undefined instruction */
1239 if ((opcode
& 0x0fb00000) == 0x03000000)
1241 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1242 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1246 /* Move immediate to status register */
1247 if ((opcode
& 0x0fb00000) == 0x03200000)
1248 return evaluate_mrs_msr(opcode
, address
, instruction
);
1250 return evaluate_data_proc(opcode
, address
, instruction
);
1254 /* catch opcodes with [27:25] = b010 */
1255 if ((opcode
& 0x0e000000) == 0x04000000)
1257 /* Load/store immediate offset */
1258 return evaluate_load_store(opcode
, address
, instruction
);
1261 /* catch opcodes with [27:25] = b011 */
1262 if ((opcode
& 0x0e000000) == 0x06000000)
1264 /* Undefined instruction */
1265 if ((opcode
& 0x00000010) == 0x00000010)
1267 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1268 snprintf(instruction
->text
, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
1272 /* Load/store register offset */
1273 return evaluate_load_store(opcode
, address
, instruction
);
1277 /* catch opcodes with [27:25] = b100 */
1278 if ((opcode
& 0x0e000000) == 0x08000000)
1280 /* Load/store multiple */
1281 return evaluate_ldm_stm(opcode
, address
, instruction
);
1284 /* catch opcodes with [27:25] = b101 */
1285 if ((opcode
& 0x0e000000) == 0x0a000000)
1287 /* Branch and branch with link */
1288 return evaluate_b_bl(opcode
, address
, instruction
);
1291 /* catch opcodes with [27:25] = b110 */
1292 if ((opcode
& 0x0e000000) == 0x0a000000)
1294 /* Coprocessor load/store and double register transfers */
1295 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1298 /* catch opcodes with [27:25] = b111 */
1299 if ((opcode
& 0x0e000000) == 0x0e000000)
1301 /* Software interrupt */
1302 if ((opcode
& 0x0f000000) == 0x0f000000)
1303 return evaluate_swi(opcode
, address
, instruction
);
1305 /* Coprocessor data processing */
1306 if ((opcode
& 0x0f000010) == 0x0e000000)
1307 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1309 /* Coprocessor register transfers */
1310 if ((opcode
& 0x0f000010) == 0x0e000010)
1311 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1314 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)