1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include "arm_disassembler.h"
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings
[] =
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value
, int places
)
39 return (value
>> places
) | (value
<< (32 - places
));
42 int evaluate_pld(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
45 if ((opcode
& 0x0d70f0000) == 0x0550f000)
47 instruction
->type
= ARM_PLD
;
49 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD ...TODO...", address
, opcode
);
55 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
59 LOG_ERROR("should never reach this point");
63 int evaluate_swi(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
65 instruction
->type
= ARM_SWI
;
67 snprintf(instruction
->text
, 128,
68 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSVC %#6.6" PRIx32
,
69 address
, opcode
, (opcode
& 0xffffff));
74 int evaluate_blx_imm(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
78 uint32_t target_address
;
80 instruction
->type
= ARM_BLX
;
81 immediate
= opcode
& 0x00ffffff;
83 /* sign extend 24-bit immediate */
84 if (immediate
& 0x00800000)
85 offset
= 0xff000000 | immediate
;
89 /* shift two bits left */
92 /* odd/event halfword */
93 if (opcode
& 0x01000000)
96 target_address
= address
+ 8 + offset
;
98 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBLX 0x%8.8" PRIx32
"", address
, opcode
, target_address
);
100 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
101 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
106 int evaluate_b_bl(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
111 uint32_t target_address
;
113 immediate
= opcode
& 0x00ffffff;
114 L
= (opcode
& 0x01000000) >> 24;
116 /* sign extend 24-bit immediate */
117 if (immediate
& 0x00800000)
118 offset
= 0xff000000 | immediate
;
122 /* shift two bits left */
125 target_address
= address
+ 8 + offset
;
128 instruction
->type
= ARM_BL
;
130 instruction
->type
= ARM_B
;
132 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tB%s%s 0x%8.8" PRIx32
, address
, opcode
,
133 (L
) ? "L" : "", COND(opcode
), target_address
);
135 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
136 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
145 uint8_t cp_num
= (opcode
& 0xf00) >> 8;
148 if (((opcode
& 0x0ff00000) == 0x0c400000) || ((opcode
& 0x0ff00000) == 0x0c400000))
150 uint8_t cp_opcode
, Rd
, Rn
, CRm
;
153 cp_opcode
= (opcode
& 0xf0) >> 4;
154 Rd
= (opcode
& 0xf000) >> 12;
155 Rn
= (opcode
& 0xf0000) >> 16;
156 CRm
= (opcode
& 0xf);
159 if ((opcode
& 0x0ff00000) == 0x0c400000)
161 instruction
->type
= ARM_MCRR
;
166 if ((opcode
& 0x0ff00000) == 0x0c500000)
168 instruction
->type
= ARM_MRRC
;
172 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s p%i, %x, r%i, r%i, c%i",
173 address
, opcode
, mnemonic
, COND(opcode
), cp_num
, cp_opcode
, Rd
, Rn
, CRm
);
175 else /* LDC or STC */
177 uint8_t CRd
, Rn
, offset
;
180 char addressing_mode
[32];
182 CRd
= (opcode
& 0xf000) >> 12;
183 Rn
= (opcode
& 0xf0000) >> 16;
184 offset
= (opcode
& 0xff);
187 if (opcode
& 0x00100000)
189 instruction
->type
= ARM_LDC
;
194 instruction
->type
= ARM_STC
;
198 U
= (opcode
& 0x00800000) >> 23;
199 N
= (opcode
& 0x00400000) >> 22;
201 /* addressing modes */
202 if ((opcode
& 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]", Rn
, (U
) ? "" : "-", offset
);
204 else if ((opcode
& 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode
, 32, "[r%i, #%s0x%2.2x*4]!", Rn
, (U
) ? "" : "-", offset
);
206 else if ((opcode
& 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode
, 32, "[r%i], #%s0x%2.2x*4", Rn
, (U
) ? "" : "-", offset
);
208 else if ((opcode
& 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode
, 32, "[r%i], #0x%2.2x", Rn
, offset
);
211 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s p%i, c%i, %s",
212 address
, opcode
, mnemonic
, ((opcode
& 0xf0000000) == 0xf0000000) ? COND(opcode
) : "2",
214 cp_num
, CRd
, addressing_mode
);
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
227 uint8_t cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
;
229 cond
= ((opcode
& 0xf0000000) == 0xf0000000) ? "2" : COND(opcode
);
230 cp_num
= (opcode
& 0xf00) >> 8;
231 CRd_Rd
= (opcode
& 0xf000) >> 12;
232 CRn
= (opcode
& 0xf0000) >> 16;
233 CRm
= (opcode
& 0xf);
234 opcode_2
= (opcode
& 0xe0) >> 5;
237 if (opcode
& 0x00000010) /* bit 4 set -> MRC/MCR */
239 if (opcode
& 0x00100000) /* bit 20 set -> MRC */
241 instruction
->type
= ARM_MRC
;
244 else /* bit 20 not set -> MCR */
246 instruction
->type
= ARM_MCR
;
250 opcode_1
= (opcode
& 0x00e00000) >> 21;
252 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
253 address
, opcode
, mnemonic
, cond
,
254 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
256 else /* bit 4 not set -> CDP */
258 instruction
->type
= ARM_CDP
;
261 opcode_1
= (opcode
& 0x00f00000) >> 20;
263 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
264 address
, opcode
, mnemonic
, cond
,
265 cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
);
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
274 uint8_t I
, P
, U
, B
, W
, L
;
276 char *operation
; /* "LDR" or "STR" */
277 char *suffix
; /* "", "B", "T", "BT" */
281 I
= (opcode
& 0x02000000) >> 25;
282 P
= (opcode
& 0x01000000) >> 24;
283 U
= (opcode
& 0x00800000) >> 23;
284 B
= (opcode
& 0x00400000) >> 22;
285 W
= (opcode
& 0x00200000) >> 21;
286 L
= (opcode
& 0x00100000) >> 20;
288 /* target register */
289 Rd
= (opcode
& 0xf000) >> 12;
292 Rn
= (opcode
& 0xf0000) >> 16;
294 instruction
->info
.load_store
.Rd
= Rd
;
295 instruction
->info
.load_store
.Rn
= Rn
;
296 instruction
->info
.load_store
.U
= U
;
298 /* determine operation */
304 /* determine instruction type and suffix */
307 if ((P
== 0) && (W
== 1))
310 instruction
->type
= ARM_LDRBT
;
312 instruction
->type
= ARM_STRBT
;
318 instruction
->type
= ARM_LDRB
;
320 instruction
->type
= ARM_STRB
;
326 if ((P
== 0) && (W
== 1))
329 instruction
->type
= ARM_LDRT
;
331 instruction
->type
= ARM_STRT
;
337 instruction
->type
= ARM_LDR
;
339 instruction
->type
= ARM_STR
;
344 if (!I
) /* #+-<offset_12> */
346 uint32_t offset_12
= (opcode
& 0xfff);
348 snprintf(offset
, 32, ", #%s0x%" PRIx32
"", (U
) ? "" : "-", offset_12
);
350 snprintf(offset
, 32, "%s", "");
352 instruction
->info
.load_store
.offset_mode
= 0;
353 instruction
->info
.load_store
.offset
.offset
= offset_12
;
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
357 uint8_t shift_imm
, shift
;
360 shift_imm
= (opcode
& 0xf80) >> 7;
361 shift
= (opcode
& 0x60) >> 5;
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift
== 0x1) && (shift_imm
== 0x0))
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift
== 0x2) && (shift_imm
== 0x0))
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift
== 0x3) && (shift_imm
== 0x0))
376 instruction
->info
.load_store
.offset_mode
= 1;
377 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
378 instruction
->info
.load_store
.offset
.reg
.shift
= shift
;
379 instruction
->info
.load_store
.offset
.reg
.shift_imm
= shift_imm
;
381 if ((shift_imm
== 0x0) && (shift
== 0x0)) /* +-<Rm> */
383 snprintf(offset
, 32, ", %sr%i", (U
) ? "" : "-", Rm
);
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
390 snprintf(offset
, 32, ", %sr%i, LSL #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
393 snprintf(offset
, 32, ", %sr%i, LSR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
396 snprintf(offset
, 32, ", %sr%i, ASR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
399 snprintf(offset
, 32, ", %sr%i, ROR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
402 snprintf(offset
, 32, ", %sr%i, RRX", (U
) ? "" : "-", Rm
);
410 if (W
== 0) /* offset */
412 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i%s]",
413 address
, opcode
, operation
, COND(opcode
), suffix
,
416 instruction
->info
.load_store
.index_mode
= 0;
418 else /* pre-indexed */
420 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i%s]!",
421 address
, opcode
, operation
, COND(opcode
), suffix
,
424 instruction
->info
.load_store
.index_mode
= 1;
427 else /* post-indexed */
429 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i]%s",
430 address
, opcode
, operation
, COND(opcode
), suffix
,
433 instruction
->info
.load_store
.index_mode
= 2;
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
442 uint8_t P
, U
, I
, W
, L
, S
, H
;
444 char *operation
; /* "LDR" or "STR" */
445 char *suffix
; /* "H", "SB", "SH", "D" */
449 P
= (opcode
& 0x01000000) >> 24;
450 U
= (opcode
& 0x00800000) >> 23;
451 I
= (opcode
& 0x00400000) >> 22;
452 W
= (opcode
& 0x00200000) >> 21;
453 L
= (opcode
& 0x00100000) >> 20;
454 S
= (opcode
& 0x00000040) >> 6;
455 H
= (opcode
& 0x00000020) >> 5;
457 /* target register */
458 Rd
= (opcode
& 0xf000) >> 12;
461 Rn
= (opcode
& 0xf0000) >> 16;
463 instruction
->info
.load_store
.Rd
= Rd
;
464 instruction
->info
.load_store
.Rn
= Rn
;
465 instruction
->info
.load_store
.U
= U
;
467 /* determine instruction type and suffix */
475 instruction
->type
= ARM_LDRSH
;
481 instruction
->type
= ARM_LDRSB
;
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
491 instruction
->type
= ARM_STRD
;
496 instruction
->type
= ARM_LDRD
;
506 instruction
->type
= ARM_LDRH
;
511 instruction
->type
= ARM_STRH
;
515 if (I
) /* Immediate offset/index (#+-<offset_8>)*/
517 uint32_t offset_8
= ((opcode
& 0xf00) >> 4) | (opcode
& 0xf);
518 snprintf(offset
, 32, "#%s0x%" PRIx32
"", (U
) ? "" : "-", offset_8
);
520 instruction
->info
.load_store
.offset_mode
= 0;
521 instruction
->info
.load_store
.offset
.offset
= offset_8
;
523 else /* Register offset/index (+-<Rm>) */
527 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
529 instruction
->info
.load_store
.offset_mode
= 1;
530 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
531 instruction
->info
.load_store
.offset
.reg
.shift
= 0x0;
532 instruction
->info
.load_store
.offset
.reg
.shift_imm
= 0x0;
537 if (W
== 0) /* offset */
539 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i, %s]",
540 address
, opcode
, operation
, COND(opcode
), suffix
,
543 instruction
->info
.load_store
.index_mode
= 0;
545 else /* pre-indexed */
547 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i, %s]!",
548 address
, opcode
, operation
, COND(opcode
), suffix
,
551 instruction
->info
.load_store
.index_mode
= 1;
554 else /* post-indexed */
556 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i], %s",
557 address
, opcode
, operation
, COND(opcode
), suffix
,
560 instruction
->info
.load_store
.index_mode
= 2;
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
569 uint8_t P
, U
, S
, W
, L
, Rn
;
570 uint32_t register_list
;
571 char *addressing_mode
;
578 P
= (opcode
& 0x01000000) >> 24;
579 U
= (opcode
& 0x00800000) >> 23;
580 S
= (opcode
& 0x00400000) >> 22;
581 W
= (opcode
& 0x00200000) >> 21;
582 L
= (opcode
& 0x00100000) >> 20;
583 register_list
= (opcode
& 0xffff);
584 Rn
= (opcode
& 0xf0000) >> 16;
586 instruction
->info
.load_store_multiple
.Rn
= Rn
;
587 instruction
->info
.load_store_multiple
.register_list
= register_list
;
588 instruction
->info
.load_store_multiple
.S
= S
;
589 instruction
->info
.load_store_multiple
.W
= W
;
593 instruction
->type
= ARM_LDM
;
598 instruction
->type
= ARM_STM
;
606 instruction
->info
.load_store_multiple
.addressing_mode
= 1;
607 addressing_mode
= "IB";
611 instruction
->info
.load_store_multiple
.addressing_mode
= 3;
612 addressing_mode
= "DB";
619 instruction
->info
.load_store_multiple
.addressing_mode
= 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode
= "";
625 instruction
->info
.load_store_multiple
.addressing_mode
= 2;
626 addressing_mode
= "DA";
630 reg_list_p
= reg_list
;
631 for (i
= 0; i
<= 15; i
++)
633 if ((register_list
>> i
) & 1)
638 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), "r%i", i
);
642 reg_list_p
+= snprintf(reg_list_p
, (reg_list
+ 69 - reg_list_p
), ", r%i", i
);
647 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i%s, {%s}%s",
648 address
, opcode
, mnemonic
, COND(opcode
), addressing_mode
,
649 Rn
, (W
) ? "!" : "", reg_list
, (S
) ? "^" : "");
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode
& 0x000000f0) == 0x00000090)
660 /* Multiply (accumulate) */
661 if ((opcode
& 0x0f800000) == 0x00000000)
663 uint8_t Rm
, Rs
, Rn
, Rd
, S
;
665 Rs
= (opcode
& 0xf00) >> 8;
666 Rn
= (opcode
& 0xf000) >> 12;
667 Rd
= (opcode
& 0xf0000) >> 16;
668 S
= (opcode
& 0x00100000) >> 20;
670 /* examine A bit (accumulate) */
671 if (opcode
& 0x00200000)
673 instruction
->type
= ARM_MLA
;
674 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMLA%s%s r%i, r%i, r%i, r%i",
675 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
, Rn
);
679 instruction
->type
= ARM_MUL
;
680 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMUL%s%s r%i, r%i, r%i",
681 address
, opcode
, COND(opcode
), (S
) ? "S" : "", Rd
, Rm
, Rs
);
687 /* Multiply (accumulate) long */
688 if ((opcode
& 0x0f800000) == 0x00800000)
690 char* mnemonic
= NULL
;
691 uint8_t Rm
, Rs
, RdHi
, RdLow
, S
;
693 Rs
= (opcode
& 0xf00) >> 8;
694 RdHi
= (opcode
& 0xf000) >> 12;
695 RdLow
= (opcode
& 0xf0000) >> 16;
696 S
= (opcode
& 0x00100000) >> 20;
698 switch ((opcode
& 0x00600000) >> 21)
701 instruction
->type
= ARM_UMULL
;
705 instruction
->type
= ARM_UMLAL
;
709 instruction
->type
= ARM_SMULL
;
713 instruction
->type
= ARM_SMLAL
;
718 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, r%i, r%i, r%i",
719 address
, opcode
, mnemonic
, COND(opcode
), (S
) ? "S" : "",
720 RdLow
, RdHi
, Rm
, Rs
);
726 if ((opcode
& 0x0f800000) == 0x01000000)
730 Rd
= (opcode
& 0xf000) >> 12;
731 Rn
= (opcode
& 0xf0000) >> 16;
734 instruction
->type
= (opcode
& 0x00400000) ? ARM_SWPB
: ARM_SWP
;
736 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, r%i, [r%i]",
737 address
, opcode
, (opcode
& 0x00400000) ? "SWPB" : "SWP", COND(opcode
), Rd
, Rm
, Rn
);
743 return evaluate_misc_load_store(opcode
, address
, instruction
);
746 int evaluate_mrs_msr(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
748 int R
= (opcode
& 0x00400000) >> 22;
749 char *PSR
= (R
) ? "SPSR" : "CPSR";
751 /* Move register to status register (MSR) */
752 if (opcode
& 0x00200000)
754 instruction
->type
= ARM_MSR
;
756 /* immediate variant */
757 if (opcode
& 0x02000000)
759 uint8_t immediate
= (opcode
& 0xff);
760 uint8_t rotate
= (opcode
& 0xf00);
762 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32
,
763 address
, opcode
, COND(opcode
), PSR
,
764 (opcode
& 0x10000) ? "c" : "",
765 (opcode
& 0x20000) ? "x" : "",
766 (opcode
& 0x40000) ? "s" : "",
767 (opcode
& 0x80000) ? "f" : "",
768 ror(immediate
, (rotate
* 2))
771 else /* register variant */
773 uint8_t Rm
= opcode
& 0xf;
774 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMSR%s %s_%s%s%s%s, r%i",
775 address
, opcode
, COND(opcode
), PSR
,
776 (opcode
& 0x10000) ? "c" : "",
777 (opcode
& 0x20000) ? "x" : "",
778 (opcode
& 0x40000) ? "s" : "",
779 (opcode
& 0x80000) ? "f" : "",
785 else /* Move status register to register (MRS) */
789 instruction
->type
= ARM_MRS
;
790 Rd
= (opcode
& 0x0000f000) >> 12;
792 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMRS%s r%i, %s",
793 address
, opcode
, COND(opcode
), Rd
, PSR
);
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
803 if ((opcode
& 0x000000f0) == 0x00000000)
805 evaluate_mrs_msr(opcode
, address
, instruction
);
809 if ((opcode
& 0x006000f0) == 0x00200010)
812 instruction
->type
= ARM_BX
;
815 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBX%s r%i",
816 address
, opcode
, COND(opcode
), Rm
);
818 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
819 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
823 if ((opcode
& 0x006000f0) == 0x00600010)
826 instruction
->type
= ARM_CLZ
;
828 Rd
= (opcode
& 0xf000) >> 12;
830 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tCLZ%s r%i, r%i",
831 address
, opcode
, COND(opcode
), Rd
, Rm
);
835 if ((opcode
& 0x006000f0) == 0x00200030)
838 instruction
->type
= ARM_BLX
;
841 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBLX%s r%i",
842 address
, opcode
, COND(opcode
), Rm
);
844 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
845 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
848 /* Enhanced DSP add/subtracts */
849 if ((opcode
& 0x0000000f0) == 0x00000050)
852 char *mnemonic
= NULL
;
854 Rd
= (opcode
& 0xf000) >> 12;
855 Rn
= (opcode
& 0xf0000) >> 16;
857 switch ((opcode
& 0x00600000) >> 21)
860 instruction
->type
= ARM_QADD
;
864 instruction
->type
= ARM_QSUB
;
868 instruction
->type
= ARM_QDADD
;
872 instruction
->type
= ARM_QDSUB
;
877 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, r%i, r%i",
878 address
, opcode
, mnemonic
, COND(opcode
), Rd
, Rm
, Rn
);
881 /* Software breakpoints */
882 if ((opcode
& 0x0000000f0) == 0x00000070)
885 instruction
->type
= ARM_BKPT
;
886 immediate
= ((opcode
& 0x000fff00) >> 4) | (opcode
& 0xf);
888 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBKPT 0x%4.4" PRIx32
"",
889 address
, opcode
, immediate
);
892 /* Enhanced DSP multiplies */
893 if ((opcode
& 0x000000090) == 0x00000080)
895 int x
= (opcode
& 0x20) >> 5;
896 int y
= (opcode
& 0x40) >> 6;
899 if ((opcode
& 0x00600000) == 0x00000000)
901 uint8_t Rd
, Rm
, Rs
, Rn
;
902 instruction
->type
= ARM_SMLAxy
;
903 Rd
= (opcode
& 0xf0000) >> 16;
905 Rs
= (opcode
& 0xf00) >> 8;
906 Rn
= (opcode
& 0xf000) >> 12;
908 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
914 if ((opcode
& 0x00600000) == 0x00400000)
916 uint8_t RdLow
, RdHi
, Rm
, Rs
;
917 instruction
->type
= ARM_SMLAxy
;
918 RdHi
= (opcode
& 0xf0000) >> 16;
919 RdLow
= (opcode
& 0xf000) >> 12;
921 Rs
= (opcode
& 0xf00) >> 8;
923 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
925 RdLow
, RdHi
, Rm
, Rs
);
929 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 0))
931 uint8_t Rd
, Rm
, Rs
, Rn
;
932 instruction
->type
= ARM_SMLAWy
;
933 Rd
= (opcode
& 0xf0000) >> 16;
935 Rs
= (opcode
& 0xf00) >> 8;
936 Rn
= (opcode
& 0xf000) >> 12;
938 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
944 if ((opcode
& 0x00600000) == 0x00300000)
947 instruction
->type
= ARM_SMULxy
;
948 Rd
= (opcode
& 0xf0000) >> 16;
950 Rs
= (opcode
& 0xf00) >> 8;
952 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMULW%s%s%s r%i, r%i, r%i",
953 address
, opcode
, (x
) ? "T" : "B", (y
) ? "T" : "B", COND(opcode
),
958 if (((opcode
& 0x00600000) == 0x00100000) && (x
== 1))
961 instruction
->type
= ARM_SMULWy
;
962 Rd
= (opcode
& 0xf0000) >> 16;
964 Rs
= (opcode
& 0xf00) >> 8;
966 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMULW%s%s r%i, r%i, r%i",
967 address
, opcode
, (y
) ? "T" : "B", COND(opcode
),
975 int evaluate_data_proc(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
977 uint8_t I
, op
, S
, Rn
, Rd
;
978 char *mnemonic
= NULL
;
979 char shifter_operand
[32];
981 I
= (opcode
& 0x02000000) >> 25;
982 op
= (opcode
& 0x01e00000) >> 21;
983 S
= (opcode
& 0x00100000) >> 20;
985 Rd
= (opcode
& 0xf000) >> 12;
986 Rn
= (opcode
& 0xf0000) >> 16;
988 instruction
->info
.data_proc
.Rd
= Rd
;
989 instruction
->info
.data_proc
.Rn
= Rn
;
990 instruction
->info
.data_proc
.S
= S
;
995 instruction
->type
= ARM_AND
;
999 instruction
->type
= ARM_EOR
;
1003 instruction
->type
= ARM_SUB
;
1007 instruction
->type
= ARM_RSB
;
1011 instruction
->type
= ARM_ADD
;
1015 instruction
->type
= ARM_ADC
;
1019 instruction
->type
= ARM_SBC
;
1023 instruction
->type
= ARM_RSC
;
1027 instruction
->type
= ARM_TST
;
1031 instruction
->type
= ARM_TEQ
;
1035 instruction
->type
= ARM_CMP
;
1039 instruction
->type
= ARM_CMN
;
1043 instruction
->type
= ARM_ORR
;
1047 instruction
->type
= ARM_MOV
;
1051 instruction
->type
= ARM_BIC
;
1055 instruction
->type
= ARM_MVN
;
1060 if (I
) /* immediate shifter operand (#<immediate>)*/
1062 uint8_t immed_8
= opcode
& 0xff;
1063 uint8_t rotate_imm
= (opcode
& 0xf00) >> 8;
1066 immediate
= ror(immed_8
, rotate_imm
* 2);
1068 snprintf(shifter_operand
, 32, "#0x%" PRIx32
"", immediate
);
1070 instruction
->info
.data_proc
.variant
= 0;
1071 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= immediate
;
1073 else /* register-based shifter operand */
1076 shift
= (opcode
& 0x60) >> 5;
1077 Rm
= (opcode
& 0xf);
1079 if ((opcode
& 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1082 shift_imm
= (opcode
& 0xf80) >> 7;
1084 instruction
->info
.data_proc
.variant
= 1;
1085 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1086 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= shift_imm
;
1087 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= shift
;
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift
== 0x1) && (shift_imm
== 0x0))
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift
== 0x2) && (shift_imm
== 0x0))
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift
== 0x3) && (shift_imm
== 0x0))
1101 if ((shift_imm
== 0x0) && (shift
== 0x0))
1103 snprintf(shifter_operand
, 32, "r%i", Rm
);
1107 if (shift
== 0x0) /* LSL */
1109 snprintf(shifter_operand
, 32, "r%i, LSL #0x%x", Rm
, shift_imm
);
1111 else if (shift
== 0x1) /* LSR */
1113 snprintf(shifter_operand
, 32, "r%i, LSR #0x%x", Rm
, shift_imm
);
1115 else if (shift
== 0x2) /* ASR */
1117 snprintf(shifter_operand
, 32, "r%i, ASR #0x%x", Rm
, shift_imm
);
1119 else if (shift
== 0x3) /* ROR */
1121 snprintf(shifter_operand
, 32, "r%i, ROR #0x%x", Rm
, shift_imm
);
1123 else if (shift
== 0x4) /* RRX */
1125 snprintf(shifter_operand
, 32, "r%i, RRX", Rm
);
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1131 uint8_t Rs
= (opcode
& 0xf00) >> 8;
1133 instruction
->info
.data_proc
.variant
= 2;
1134 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rm
;
1135 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rs
;
1136 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= shift
;
1138 if (shift
== 0x0) /* LSL */
1140 snprintf(shifter_operand
, 32, "r%i, LSL r%i", Rm
, Rs
);
1142 else if (shift
== 0x1) /* LSR */
1144 snprintf(shifter_operand
, 32, "r%i, LSR r%i", Rm
, Rs
);
1146 else if (shift
== 0x2) /* ASR */
1148 snprintf(shifter_operand
, 32, "r%i, ASR r%i", Rm
, Rs
);
1150 else if (shift
== 0x3) /* ROR */
1152 snprintf(shifter_operand
, 32, "r%i, ROR r%i", Rm
, Rs
);
1157 if ((op
< 0x8) || (op
== 0xc) || (op
== 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1159 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, r%i, %s",
1160 address
, opcode
, mnemonic
, COND(opcode
),
1161 (S
) ? "S" : "", Rd
, Rn
, shifter_operand
);
1163 else if ((op
== 0xd) || (op
== 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1165 if (opcode
== 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tNOP",address
, opcode
);
1168 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, %s",
1169 address
, opcode
, mnemonic
, COND(opcode
),
1170 (S
) ? "S" : "", Rd
, shifter_operand
);
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1174 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, %s",
1175 address
, opcode
, mnemonic
, COND(opcode
),
1176 Rn
, shifter_operand
);
1182 int arm_evaluate_opcode(uint32_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1184 /* clear fields, to avoid confusion */
1185 memset(instruction
, 0, sizeof(arm_instruction_t
));
1186 instruction
->opcode
= opcode
;
1187 instruction
->instruction_size
= 4;
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode
& 0xf0000000) == 0xf0000000)
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode
& 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode
, address
, instruction
);
1196 /* Undefined instruction */
1197 if ((opcode
& 0x0e000000) == 0x08000000)
1199 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1200 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEFINED INSTRUCTION", address
, opcode
);
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode
& 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode
, address
, instruction
);
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode
& 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1213 /* Coprocessor data processing */
1214 if ((opcode
& 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1217 /* Coprocessor register transfers */
1218 if ((opcode
& 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1221 /* Undefined instruction */
1222 if ((opcode
& 0x0f000000) == 0x0f000000)
1224 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1225 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEFINED INSTRUCTION", address
, opcode
);
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode
& 0x0e000000) == 0x00000000)
1233 /* Multiplies, extra load/stores */
1234 if ((opcode
& 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode
, address
, instruction
);
1237 /* Miscellaneous instructions */
1238 if ((opcode
& 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode
, address
, instruction
);
1241 return evaluate_data_proc(opcode
, address
, instruction
);
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode
& 0x0e000000) == 0x02000000)
1247 /* Undefined instruction */
1248 if ((opcode
& 0x0fb00000) == 0x03000000)
1250 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1251 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEFINED INSTRUCTION", address
, opcode
);
1255 /* Move immediate to status register */
1256 if ((opcode
& 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode
, address
, instruction
);
1259 return evaluate_data_proc(opcode
, address
, instruction
);
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode
& 0x0e000000) == 0x04000000)
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode
, address
, instruction
);
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode
& 0x0e000000) == 0x06000000)
1273 /* Undefined instruction */
1274 if ((opcode
& 0x00000010) == 0x00000010)
1276 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1277 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEFINED INSTRUCTION", address
, opcode
);
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode
, address
, instruction
);
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode
& 0x0e000000) == 0x08000000)
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode
, address
, instruction
);
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode
& 0x0e000000) == 0x0a000000)
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode
, address
, instruction
);
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode
& 0x0e000000) == 0x0a000000)
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode
& 0x0e000000) == 0x0e000000)
1310 /* Software interrupt */
1311 if ((opcode
& 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode
, address
, instruction
);
1314 /* Coprocessor data processing */
1315 if ((opcode
& 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1318 /* Coprocessor register transfers */
1319 if ((opcode
& 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1323 LOG_ERROR("should never reach this point");
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1329 uint32_t offset
= opcode
& 0x7ff;
1330 uint32_t opc
= (opcode
>> 11) & 0x3;
1331 uint32_t target_address
;
1332 char *mnemonic
= NULL
;
1334 /* sign extend 11-bit offset */
1335 if (((opc
== 0) || (opc
== 2)) && (offset
& 0x00000400))
1336 offset
= 0xfffff800 | offset
;
1338 target_address
= address
+ 4 + (offset
<< 1);
1342 /* unconditional branch */
1344 instruction
->type
= ARM_B
;
1349 instruction
->type
= ARM_BLX
;
1354 instruction
->type
= ARM_UNKNOWN_INSTUCTION
;
1355 mnemonic
= "prefix";
1356 target_address
= offset
<< 12;
1360 instruction
->type
= ARM_BL
;
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1370 snprintf(instruction
->text
, 128,
1371 "0x%8.8" PRIx32
" 0x%4.4x \t%s\t%#8.8" PRIx32
,
1372 address
, opcode
, mnemonic
, target_address
);
1374 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
1375 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
1380 int evaluate_add_sub_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1382 uint8_t Rd
= (opcode
>> 0) & 0x7;
1383 uint8_t Rn
= (opcode
>> 3) & 0x7;
1384 uint8_t Rm_imm
= (opcode
>> 6) & 0x7;
1385 uint32_t opc
= opcode
& (1 << 9);
1386 uint32_t reg_imm
= opcode
& (1 << 10);
1391 instruction
->type
= ARM_SUB
;
1396 instruction
->type
= ARM_ADD
;
1400 instruction
->info
.data_proc
.Rd
= Rd
;
1401 instruction
->info
.data_proc
.Rn
= Rn
;
1402 instruction
->info
.data_proc
.S
= 1;
1406 instruction
->info
.data_proc
.variant
= 0; /*immediate*/
1407 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= Rm_imm
;
1408 snprintf(instruction
->text
, 128,
1409 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
1414 instruction
->info
.data_proc
.variant
= 1; /*immediate shift*/
1415 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm_imm
;
1416 snprintf(instruction
->text
, 128,
1417 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
1424 int evaluate_shift_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1426 uint8_t Rd
= (opcode
>> 0) & 0x7;
1427 uint8_t Rm
= (opcode
>> 3) & 0x7;
1428 uint8_t imm
= (opcode
>> 6) & 0x1f;
1429 uint8_t opc
= (opcode
>> 11) & 0x3;
1430 char *mnemonic
= NULL
;
1435 instruction
->type
= ARM_MOV
;
1437 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 0;
1440 instruction
->type
= ARM_MOV
;
1442 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 1;
1445 instruction
->type
= ARM_MOV
;
1447 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 2;
1451 if ((imm
== 0) && (opc
!= 0))
1454 instruction
->info
.data_proc
.Rd
= Rd
;
1455 instruction
->info
.data_proc
.Rn
= -1;
1456 instruction
->info
.data_proc
.S
= 1;
1458 instruction
->info
.data_proc
.variant
= 1; /*immediate_shift*/
1459 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1460 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= imm
;
1462 snprintf(instruction
->text
, 128,
1463 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address
, opcode
, mnemonic
, Rd
, Rm
, imm
);
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1471 uint8_t imm
= opcode
& 0xff;
1472 uint8_t Rd
= (opcode
>> 8) & 0x7;
1473 uint32_t opc
= (opcode
>> 11) & 0x3;
1474 char *mnemonic
= NULL
;
1476 instruction
->info
.data_proc
.Rd
= Rd
;
1477 instruction
->info
.data_proc
.Rn
= Rd
;
1478 instruction
->info
.data_proc
.S
= 1;
1479 instruction
->info
.data_proc
.variant
= 0; /*immediate*/
1480 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
;
1485 instruction
->type
= ARM_MOV
;
1487 instruction
->info
.data_proc
.Rn
= -1;
1490 instruction
->type
= ARM_CMP
;
1492 instruction
->info
.data_proc
.Rd
= -1;
1495 instruction
->type
= ARM_ADD
;
1499 instruction
->type
= ARM_SUB
;
1504 snprintf(instruction
->text
, 128,
1505 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address
, opcode
, mnemonic
, Rd
, imm
);
1511 int evaluate_data_proc_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1513 uint8_t high_reg
, op
, Rm
, Rd
,H1
,H2
;
1514 char *mnemonic
= NULL
;
1516 high_reg
= (opcode
& 0x0400) >> 10;
1517 op
= (opcode
& 0x03C0) >> 6;
1519 Rd
= (opcode
& 0x0007);
1520 Rm
= (opcode
& 0x0038) >> 3;
1521 H1
= (opcode
& 0x0080) >> 7;
1522 H2
= (opcode
& 0x0040) >> 6;
1524 instruction
->info
.data_proc
.Rd
= Rd
;
1525 instruction
->info
.data_proc
.Rn
= Rd
;
1526 instruction
->info
.data_proc
.S
= (!high_reg
|| (instruction
->type
== ARM_CMP
));
1527 instruction
->info
.data_proc
.variant
= 1 /*immediate shift*/;
1528 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1539 instruction
->type
= ARM_ADD
;
1543 instruction
->type
= ARM_CMP
;
1547 instruction
->type
= ARM_MOV
;
1551 if ((opcode
& 0x7) == 0x0)
1553 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
1556 instruction
->type
= ARM_BLX
;
1557 snprintf(instruction
->text
, 128,
1559 " 0x%4.4x \tBLX\tr%i",
1560 address
, opcode
, Rm
);
1564 instruction
->type
= ARM_BX
;
1565 snprintf(instruction
->text
, 128,
1567 " 0x%4.4x \tBX\tr%i",
1568 address
, opcode
, Rm
);
1573 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1574 snprintf(instruction
->text
, 128,
1577 "UNDEFINED INSTRUCTION",
1589 instruction
->type
= ARM_AND
;
1593 instruction
->type
= ARM_EOR
;
1597 instruction
->type
= ARM_MOV
;
1599 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1600 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 0;
1601 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1602 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1605 instruction
->type
= ARM_MOV
;
1607 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1608 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 1;
1609 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1610 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1613 instruction
->type
= ARM_MOV
;
1615 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1616 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 2;
1617 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1618 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1621 instruction
->type
= ARM_ADC
;
1625 instruction
->type
= ARM_SBC
;
1629 instruction
->type
= ARM_MOV
;
1631 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1632 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 3;
1633 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1634 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1637 instruction
->type
= ARM_TST
;
1641 instruction
->type
= ARM_RSB
;
1643 instruction
->info
.data_proc
.variant
= 0 /*immediate*/;
1644 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= 0;
1645 instruction
->info
.data_proc
.Rn
= Rm
;
1648 instruction
->type
= ARM_CMP
;
1652 instruction
->type
= ARM_CMN
;
1656 instruction
->type
= ARM_ORR
;
1660 instruction
->type
= ARM_MUL
;
1664 instruction
->type
= ARM_BIC
;
1668 instruction
->type
= ARM_MVN
;
1674 snprintf(instruction
->text
, 128,
1675 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i",
1676 address
, opcode
, mnemonic
, Rd
, Rm
);
1681 int evaluate_load_literal_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1684 uint8_t Rd
= (opcode
>> 8) & 0x7;
1686 instruction
->type
= ARM_LDR
;
1687 immediate
= opcode
& 0x000000ff;
1689 snprintf(instruction
->text
, 128,
1690 "0x%8.8" PRIx32
" 0x%4.4x \tLDR\tr%i, [pc, #%#" PRIx32
"]",
1691 address
, opcode
, Rd
, immediate
*4);
1693 instruction
->info
.load_store
.Rd
= Rd
;
1694 instruction
->info
.load_store
.Rn
= 15 /*PC*/;
1695 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1696 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1697 instruction
->info
.load_store
.offset
.offset
= immediate
*4;
1702 int evaluate_load_store_reg_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1704 uint8_t Rd
= (opcode
>> 0) & 0x7;
1705 uint8_t Rn
= (opcode
>> 3) & 0x7;
1706 uint8_t Rm
= (opcode
>> 6) & 0x7;
1707 uint8_t opc
= (opcode
>> 9) & 0x7;
1708 char *mnemonic
= NULL
;
1713 instruction
->type
= ARM_STR
;
1717 instruction
->type
= ARM_STRH
;
1721 instruction
->type
= ARM_STRB
;
1725 instruction
->type
= ARM_LDRSB
;
1729 instruction
->type
= ARM_LDR
;
1733 instruction
->type
= ARM_LDRH
;
1737 instruction
->type
= ARM_LDRB
;
1741 instruction
->type
= ARM_LDRSH
;
1746 snprintf(instruction
->text
, 128,
1747 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1748 address
, opcode
, mnemonic
, Rd
, Rn
, Rm
);
1750 instruction
->info
.load_store
.Rd
= Rd
;
1751 instruction
->info
.load_store
.Rn
= Rn
;
1752 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1753 instruction
->info
.load_store
.offset_mode
= 1; /*register*/
1754 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
1759 int evaluate_load_store_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1761 uint32_t offset
= (opcode
>> 6) & 0x1f;
1762 uint8_t Rd
= (opcode
>> 0) & 0x7;
1763 uint8_t Rn
= (opcode
>> 3) & 0x7;
1764 uint32_t L
= opcode
& (1 << 11);
1765 uint32_t B
= opcode
& (1 << 12);
1772 instruction
->type
= ARM_LDR
;
1777 instruction
->type
= ARM_STR
;
1781 if ((opcode
&0xF000) == 0x8000)
1792 snprintf(instruction
->text
, 128,
1793 "0x%8.8" PRIx32
" 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32
"]",
1794 address
, opcode
, mnemonic
, suffix
, Rd
, Rn
, offset
<< shift
);
1796 instruction
->info
.load_store
.Rd
= Rd
;
1797 instruction
->info
.load_store
.Rn
= Rn
;
1798 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1799 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1800 instruction
->info
.load_store
.offset
.offset
= offset
<< shift
;
1805 int evaluate_load_store_stack_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1807 uint32_t offset
= opcode
& 0xff;
1808 uint8_t Rd
= (opcode
>> 8) & 0x7;
1809 uint32_t L
= opcode
& (1 << 11);
1814 instruction
->type
= ARM_LDR
;
1819 instruction
->type
= ARM_STR
;
1823 snprintf(instruction
->text
, 128,
1824 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32
"]",
1825 address
, opcode
, mnemonic
, Rd
, offset
*4);
1827 instruction
->info
.load_store
.Rd
= Rd
;
1828 instruction
->info
.load_store
.Rn
= 13 /*SP*/;
1829 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1830 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1831 instruction
->info
.load_store
.offset
.offset
= offset
*4;
1836 int evaluate_add_sp_pc_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1838 uint32_t imm
= opcode
& 0xff;
1839 uint8_t Rd
= (opcode
>> 8) & 0x7;
1841 uint32_t SP
= opcode
& (1 << 11);
1844 instruction
->type
= ARM_ADD
;
1857 snprintf(instruction
->text
, 128,
1858 "0x%8.8" PRIx32
" 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32
,
1859 address
, opcode
, Rd
, reg_name
, imm
* 4);
1861 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
1862 instruction
->info
.data_proc
.Rd
= Rd
;
1863 instruction
->info
.data_proc
.Rn
= Rn
;
1864 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
1869 int evaluate_adjust_stack_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1871 uint32_t imm
= opcode
& 0x7f;
1872 uint8_t opc
= opcode
& (1 << 7);
1878 instruction
->type
= ARM_SUB
;
1883 instruction
->type
= ARM_ADD
;
1887 snprintf(instruction
->text
, 128,
1888 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tSP, #%#" PRIx32
,
1889 address
, opcode
, mnemonic
, imm
*4);
1891 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
1892 instruction
->info
.data_proc
.Rd
= 13 /*SP*/;
1893 instruction
->info
.data_proc
.Rn
= 13 /*SP*/;
1894 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
1899 int evaluate_breakpoint_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1901 uint32_t imm
= opcode
& 0xff;
1903 instruction
->type
= ARM_BKPT
;
1905 snprintf(instruction
->text
, 128,
1906 "0x%8.8" PRIx32
" 0x%4.4x \tBKPT\t%#2.2" PRIx32
"",
1907 address
, opcode
, imm
);
1912 int evaluate_load_store_multiple_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1914 uint32_t reg_list
= opcode
& 0xff;
1915 uint32_t L
= opcode
& (1 << 11);
1916 uint32_t R
= opcode
& (1 << 8);
1917 uint8_t Rn
= (opcode
>> 8) & 7;
1918 uint8_t addr_mode
= 0 /* IA */;
1922 char ptr_name
[7] = "";
1925 if ((opcode
& 0xf000) == 0xc000)
1926 { /* generic load/store multiple */
1929 instruction
->type
= ARM_LDM
;
1934 instruction
->type
= ARM_STM
;
1937 snprintf(ptr_name
,7,"r%i!, ",Rn
);
1944 instruction
->type
= ARM_LDM
;
1947 reg_list
|= (1 << 15) /*PC*/;
1951 instruction
->type
= ARM_STM
;
1953 addr_mode
= 3; /*DB*/
1955 reg_list
|= (1 << 14) /*LR*/;
1959 reg_names_p
= reg_names
;
1960 for (i
= 0; i
<= 15; i
++)
1962 if (reg_list
& (1 << i
))
1963 reg_names_p
+= snprintf(reg_names_p
, (reg_names
+ 40 - reg_names_p
), "r%i, ", i
);
1965 if (reg_names_p
> reg_names
)
1966 reg_names_p
[-2] = '\0';
1967 else /* invalid op : no registers */
1968 reg_names
[0] = '\0';
1970 snprintf(instruction
->text
, 128,
1971 "0x%8.8" PRIx32
" 0x%4.4x \t%s\t%s{%s}",
1972 address
, opcode
, mnemonic
, ptr_name
, reg_names
);
1974 instruction
->info
.load_store_multiple
.register_list
= reg_list
;
1975 instruction
->info
.load_store_multiple
.Rn
= Rn
;
1976 instruction
->info
.load_store_multiple
.addressing_mode
= addr_mode
;
1981 int evaluate_cond_branch_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1983 uint32_t offset
= opcode
& 0xff;
1984 uint8_t cond
= (opcode
>> 8) & 0xf;
1985 uint32_t target_address
;
1989 instruction
->type
= ARM_SWI
;
1990 snprintf(instruction
->text
, 128,
1991 "0x%8.8" PRIx32
" 0x%4.4x \tSVC\t%#2.2" PRIx32
,
1992 address
, opcode
, offset
);
1995 else if (cond
== 0xe)
1997 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1998 snprintf(instruction
->text
, 128,
1999 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2004 /* sign extend 8-bit offset */
2005 if (offset
& 0x00000080)
2006 offset
= 0xffffff00 | offset
;
2008 target_address
= address
+ 4 + (offset
<< 1);
2010 snprintf(instruction
->text
, 128,
2011 "0x%8.8" PRIx32
" 0x%4.4x \tB%s\t%#8.8" PRIx32
,
2013 arm_condition_strings
[cond
], target_address
);
2015 instruction
->type
= ARM_B
;
2016 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
2017 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
2022 static int evaluate_cb_thumb(uint16_t opcode
, uint32_t address
,
2023 arm_instruction_t
*instruction
)
2027 /* added in Thumb2 */
2028 offset
= (opcode
>> 3) & 0x1f;
2029 offset
|= (opcode
& 0x0200) >> 4;
2031 snprintf(instruction
->text
, 128,
2032 "0x%8.8" PRIx32
" 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32
,
2034 (opcode
& 0x0800) ? "N" : "",
2035 opcode
& 0x7, address
+ 4 + (offset
<< 1));
2040 static int evaluate_extend_thumb(uint16_t opcode
, uint32_t address
,
2041 arm_instruction_t
*instruction
)
2043 /* added in ARMv6 */
2044 snprintf(instruction
->text
, 128,
2045 "0x%8.8" PRIx32
" 0x%4.4x \t%cXT%c\tr%d, r%d",
2047 (opcode
& 0x0080) ? 'U' : 'S',
2048 (opcode
& 0x0040) ? 'B' : 'H',
2049 opcode
& 0x7, (opcode
>> 3) & 0x7);
2054 static int evaluate_cps_thumb(uint16_t opcode
, uint32_t address
,
2055 arm_instruction_t
*instruction
)
2057 /* added in ARMv6 */
2058 if ((opcode
& 0x0ff0) == 0x0650)
2059 snprintf(instruction
->text
, 128,
2060 "0x%8.8" PRIx32
" 0x%4.4x \tSETEND %s",
2062 (opcode
& 0x80) ? "BE" : "LE");
2063 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2064 snprintf(instruction
->text
, 128,
2065 "0x%8.8" PRIx32
" 0x%4.4x \tCPSI%c %s%s%s",
2067 (opcode
& 0x0010) ? 'D' : 'E',
2068 (opcode
& 0x0004) ? "A" : "",
2069 (opcode
& 0x0002) ? "I" : "",
2070 (opcode
& 0x0001) ? "F" : "");
2075 static int evaluate_byterev_thumb(uint16_t opcode
, uint32_t address
,
2076 arm_instruction_t
*instruction
)
2080 /* added in ARMv6 */
2081 switch (opcode
& 0x00c0) {
2092 snprintf(instruction
->text
, 128,
2093 "0x%8.8" PRIx32
" 0x%4.4x \tREV%s\tr%d, r%d",
2094 address
, opcode
, suffix
,
2095 opcode
& 0x7, (opcode
>> 3) & 0x7);
2100 static int evaluate_hint_thumb(uint16_t opcode
, uint32_t address
,
2101 arm_instruction_t
*instruction
)
2105 switch ((opcode
>> 4) & 0x0f) {
2122 hint
= "HINT (UNRECOGNIZED)";
2126 snprintf(instruction
->text
, 128,
2127 "0x%8.8" PRIx32
" 0x%4.4x \t%s",
2128 address
, opcode
, hint
);
2133 static int evaluate_ifthen_thumb(uint16_t opcode
, uint32_t address
,
2134 arm_instruction_t
*instruction
)
2136 unsigned cond
= (opcode
>> 4) & 0x0f;
2137 char *x
= "", *y
= "", *z
= "";
2140 z
= (opcode
& 0x02) ? "T" : "E";
2142 y
= (opcode
& 0x04) ? "T" : "E";
2144 x
= (opcode
& 0x08) ? "T" : "E";
2146 snprintf(instruction
->text
, 128,
2147 "0x%8.8" PRIx32
" 0x%4.4x \tIT%s%s%s\t%s",
2149 x
, y
, z
, arm_condition_strings
[cond
]);
2151 /* NOTE: strictly speaking, the next 1-4 instructions should
2152 * now be displayed with the relevant conditional suffix...
2158 int thumb_evaluate_opcode(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
2160 /* clear fields, to avoid confusion */
2161 memset(instruction
, 0, sizeof(arm_instruction_t
));
2162 instruction
->opcode
= opcode
;
2163 instruction
->instruction_size
= 2;
2165 if ((opcode
& 0xe000) == 0x0000)
2167 /* add/substract register or immediate */
2168 if ((opcode
& 0x1800) == 0x1800)
2169 return evaluate_add_sub_thumb(opcode
, address
, instruction
);
2170 /* shift by immediate */
2172 return evaluate_shift_imm_thumb(opcode
, address
, instruction
);
2175 /* Add/substract/compare/move immediate */
2176 if ((opcode
& 0xe000) == 0x2000)
2178 return evaluate_data_proc_imm_thumb(opcode
, address
, instruction
);
2181 /* Data processing instructions */
2182 if ((opcode
& 0xf800) == 0x4000)
2184 return evaluate_data_proc_thumb(opcode
, address
, instruction
);
2187 /* Load from literal pool */
2188 if ((opcode
& 0xf800) == 0x4800)
2190 return evaluate_load_literal_thumb(opcode
, address
, instruction
);
2193 /* Load/Store register offset */
2194 if ((opcode
& 0xf000) == 0x5000)
2196 return evaluate_load_store_reg_thumb(opcode
, address
, instruction
);
2199 /* Load/Store immediate offset */
2200 if (((opcode
& 0xe000) == 0x6000)
2201 ||((opcode
& 0xf000) == 0x8000))
2203 return evaluate_load_store_imm_thumb(opcode
, address
, instruction
);
2206 /* Load/Store from/to stack */
2207 if ((opcode
& 0xf000) == 0x9000)
2209 return evaluate_load_store_stack_thumb(opcode
, address
, instruction
);
2213 if ((opcode
& 0xf000) == 0xa000)
2215 return evaluate_add_sp_pc_thumb(opcode
, address
, instruction
);
2219 if ((opcode
& 0xf000) == 0xb000)
2221 switch ((opcode
>> 8) & 0x0f) {
2223 return evaluate_adjust_stack_thumb(opcode
, address
, instruction
);
2228 return evaluate_cb_thumb(opcode
, address
, instruction
);
2230 return evaluate_extend_thumb(opcode
, address
, instruction
);
2235 return evaluate_load_store_multiple_thumb(opcode
, address
,
2238 return evaluate_cps_thumb(opcode
, address
, instruction
);
2240 if ((opcode
& 0x00c0) == 0x0080)
2242 return evaluate_byterev_thumb(opcode
, address
, instruction
);
2244 return evaluate_breakpoint_thumb(opcode
, address
, instruction
);
2246 if (opcode
& 0x000f)
2247 return evaluate_ifthen_thumb(opcode
, address
,
2250 return evaluate_hint_thumb(opcode
, address
,
2254 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2255 snprintf(instruction
->text
, 128,
2256 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2261 /* Load/Store multiple */
2262 if ((opcode
& 0xf000) == 0xc000)
2264 return evaluate_load_store_multiple_thumb(opcode
, address
, instruction
);
2267 /* Conditional branch + SWI */
2268 if ((opcode
& 0xf000) == 0xd000)
2270 return evaluate_cond_branch_thumb(opcode
, address
, instruction
);
2273 if ((opcode
& 0xe000) == 0xe000)
2275 /* Undefined instructions */
2276 if ((opcode
& 0xf801) == 0xe801)
2278 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2279 snprintf(instruction
->text
, 128,
2280 "0x%8.8" PRIx32
" 0x%8.8x\t"
2281 "UNDEFINED INSTRUCTION",
2286 { /* Branch to offset */
2287 return evaluate_b_bl_blx_thumb(opcode
, address
, instruction
);
2291 LOG_ERROR("should never reach this point (opcode=%04x)",opcode
);
2296 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2297 * always set. That means eventual arm_simulate_step() support for Thumb2
2298 * will need work in this area.
2300 int thumb2_opcode(target_t
*target
, uint32_t address
, arm_instruction_t
*instruction
)
2306 /* clear low bit ... it's set on function pointers */
2309 /* clear fields, to avoid confusion */
2310 memset(instruction
, 0, sizeof(arm_instruction_t
));
2312 /* read first halfword, see if this is the only one */
2313 retval
= target_read_u16(target
, address
, &op
);
2314 if (retval
!= ERROR_OK
)
2317 switch (op
& 0xf800) {
2321 /* 32-bit instructions */
2322 instruction
->instruction_size
= 4;
2324 retval
= target_read_u16(target
, address
+ 2, &op
);
2325 if (retval
!= ERROR_OK
)
2328 instruction
->opcode
= opcode
;
2331 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2332 return thumb_evaluate_opcode(op
, address
, instruction
);
2335 /* FIXME decode the 32-bit instructions */
2337 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode
);
2339 snprintf(instruction
->text
, 128,
2340 "0x%8.8" PRIx32
" 0x%8.8x\t... 32-bit Thumb2 ...",
2345 int arm_access_size(arm_instruction_t
*instruction
)
2347 if ((instruction
->type
== ARM_LDRB
)
2348 || (instruction
->type
== ARM_LDRBT
)
2349 || (instruction
->type
== ARM_LDRSB
)
2350 || (instruction
->type
== ARM_STRB
)
2351 || (instruction
->type
== ARM_STRBT
))
2355 else if ((instruction
->type
== ARM_LDRH
)
2356 || (instruction
->type
== ARM_LDRSH
)
2357 || (instruction
->type
== ARM_STRH
))
2361 else if ((instruction
->type
== ARM_LDR
)
2362 || (instruction
->type
== ARM_LDRT
)
2363 || (instruction
->type
== ARM_STR
)
2364 || (instruction
->type
== ARM_STRT
))
2368 else if ((instruction
->type
== ARM_LDRD
)
2369 || (instruction
->type
== ARM_STRD
))
2375 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction
->type
);
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)