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, "0x%8.8" PRIx32
"\t0x%4.4x\t%s 0x%8.8" PRIx32
, address
, opcode
,mnemonic
, target_address
);
1372 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
1373 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
1378 int evaluate_add_sub_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1380 uint8_t Rd
= (opcode
>> 0) & 0x7;
1381 uint8_t Rn
= (opcode
>> 3) & 0x7;
1382 uint8_t Rm_imm
= (opcode
>> 6) & 0x7;
1383 uint32_t opc
= opcode
& (1 << 9);
1384 uint32_t reg_imm
= opcode
& (1 << 10);
1389 instruction
->type
= ARM_SUB
;
1394 instruction
->type
= ARM_ADD
;
1398 instruction
->info
.data_proc
.Rd
= Rd
;
1399 instruction
->info
.data_proc
.Rn
= Rn
;
1400 instruction
->info
.data_proc
.S
= 1;
1404 instruction
->info
.data_proc
.variant
= 0; /*immediate*/
1405 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= Rm_imm
;
1406 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, r%i, #%d",
1407 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
1411 instruction
->info
.data_proc
.variant
= 1; /*immediate shift*/
1412 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm_imm
;
1413 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, r%i, r%i",
1414 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
1420 int evaluate_shift_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1422 uint8_t Rd
= (opcode
>> 0) & 0x7;
1423 uint8_t Rm
= (opcode
>> 3) & 0x7;
1424 uint8_t imm
= (opcode
>> 6) & 0x1f;
1425 uint8_t opc
= (opcode
>> 11) & 0x3;
1426 char *mnemonic
= NULL
;
1431 instruction
->type
= ARM_MOV
;
1433 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 0;
1436 instruction
->type
= ARM_MOV
;
1438 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 1;
1441 instruction
->type
= ARM_MOV
;
1443 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 2;
1447 if ((imm
== 0) && (opc
!= 0))
1450 instruction
->info
.data_proc
.Rd
= Rd
;
1451 instruction
->info
.data_proc
.Rn
= -1;
1452 instruction
->info
.data_proc
.S
= 1;
1454 instruction
->info
.data_proc
.variant
= 1; /*immediate_shift*/
1455 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1456 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= imm
;
1458 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, r%i, #0x%02x" ,
1459 address
, opcode
, mnemonic
, Rd
, Rm
, imm
);
1464 int evaluate_data_proc_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1466 uint8_t imm
= opcode
& 0xff;
1467 uint8_t Rd
= (opcode
>> 8) & 0x7;
1468 uint32_t opc
= (opcode
>> 11) & 0x3;
1469 char *mnemonic
= NULL
;
1471 instruction
->info
.data_proc
.Rd
= Rd
;
1472 instruction
->info
.data_proc
.Rn
= Rd
;
1473 instruction
->info
.data_proc
.S
= 1;
1474 instruction
->info
.data_proc
.variant
= 0; /*immediate*/
1475 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
;
1480 instruction
->type
= ARM_MOV
;
1482 instruction
->info
.data_proc
.Rn
= -1;
1485 instruction
->type
= ARM_CMP
;
1487 instruction
->info
.data_proc
.Rd
= -1;
1490 instruction
->type
= ARM_ADD
;
1494 instruction
->type
= ARM_SUB
;
1499 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, #0x%02x" ,
1500 address
, opcode
, mnemonic
, Rd
, imm
);
1505 int evaluate_data_proc_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1507 uint8_t high_reg
, op
, Rm
, Rd
,H1
,H2
;
1508 char *mnemonic
= NULL
;
1510 high_reg
= (opcode
& 0x0400) >> 10;
1511 op
= (opcode
& 0x03C0) >> 6;
1513 Rd
= (opcode
& 0x0007);
1514 Rm
= (opcode
& 0x0038) >> 3;
1515 H1
= (opcode
& 0x0080) >> 7;
1516 H2
= (opcode
& 0x0040) >> 6;
1518 instruction
->info
.data_proc
.Rd
= Rd
;
1519 instruction
->info
.data_proc
.Rn
= Rd
;
1520 instruction
->info
.data_proc
.S
= (!high_reg
|| (instruction
->type
== ARM_CMP
));
1521 instruction
->info
.data_proc
.variant
= 1 /*immediate shift*/;
1522 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1533 instruction
->type
= ARM_ADD
;
1537 instruction
->type
= ARM_CMP
;
1541 instruction
->type
= ARM_MOV
;
1545 if ((opcode
& 0x7) == 0x0)
1547 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
1550 instruction
->type
= ARM_BLX
;
1551 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tBLX r%i", address
, opcode
, Rm
);
1555 instruction
->type
= ARM_BX
;
1556 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tBX r%i", address
, opcode
, Rm
);
1561 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1562 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tUNDEFINED INSTRUCTION", address
, opcode
);
1573 instruction
->type
= ARM_AND
;
1577 instruction
->type
= ARM_EOR
;
1581 instruction
->type
= ARM_MOV
;
1583 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1584 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 0;
1585 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1586 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1589 instruction
->type
= ARM_MOV
;
1591 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1592 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 1;
1593 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
1594 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
1597 instruction
->type
= ARM_MOV
;
1599 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1600 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 2;
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_ADC
;
1609 instruction
->type
= ARM_SBC
;
1613 instruction
->type
= ARM_MOV
;
1615 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
1616 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 3;
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_TST
;
1625 instruction
->type
= ARM_RSB
;
1627 instruction
->info
.data_proc
.variant
= 0 /*immediate*/;
1628 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= 0;
1629 instruction
->info
.data_proc
.Rn
= Rm
;
1632 instruction
->type
= ARM_CMP
;
1636 instruction
->type
= ARM_CMN
;
1640 instruction
->type
= ARM_ORR
;
1644 instruction
->type
= ARM_MUL
;
1648 instruction
->type
= ARM_BIC
;
1652 instruction
->type
= ARM_MVN
;
1658 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, r%i",
1659 address
, opcode
, mnemonic
, Rd
, Rm
);
1664 int evaluate_load_literal_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1667 uint8_t Rd
= (opcode
>> 8) & 0x7;
1669 instruction
->type
= ARM_LDR
;
1670 immediate
= opcode
& 0x000000ff;
1672 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tLDR r%i, [PC, #0x%" PRIx32
"]", address
, opcode
, Rd
, immediate
*4);
1674 instruction
->info
.load_store
.Rd
= Rd
;
1675 instruction
->info
.load_store
.Rn
= 15 /*PC*/;
1676 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1677 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1678 instruction
->info
.load_store
.offset
.offset
= immediate
*4;
1683 int evaluate_load_store_reg_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1685 uint8_t Rd
= (opcode
>> 0) & 0x7;
1686 uint8_t Rn
= (opcode
>> 3) & 0x7;
1687 uint8_t Rm
= (opcode
>> 6) & 0x7;
1688 uint8_t opc
= (opcode
>> 9) & 0x7;
1689 char *mnemonic
= NULL
;
1694 instruction
->type
= ARM_STR
;
1698 instruction
->type
= ARM_STRH
;
1702 instruction
->type
= ARM_STRB
;
1706 instruction
->type
= ARM_LDRSB
;
1710 instruction
->type
= ARM_LDR
;
1714 instruction
->type
= ARM_LDRH
;
1718 instruction
->type
= ARM_LDRB
;
1722 instruction
->type
= ARM_LDRSH
;
1727 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, [r%i, r%i]", address
, opcode
, mnemonic
, Rd
, Rn
, Rm
);
1729 instruction
->info
.load_store
.Rd
= Rd
;
1730 instruction
->info
.load_store
.Rn
= Rn
;
1731 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1732 instruction
->info
.load_store
.offset_mode
= 1; /*register*/
1733 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
1738 int evaluate_load_store_imm_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1740 uint32_t offset
= (opcode
>> 6) & 0x1f;
1741 uint8_t Rd
= (opcode
>> 0) & 0x7;
1742 uint8_t Rn
= (opcode
>> 3) & 0x7;
1743 uint32_t L
= opcode
& (1 << 11);
1744 uint32_t B
= opcode
& (1 << 12);
1751 instruction
->type
= ARM_LDR
;
1756 instruction
->type
= ARM_STR
;
1760 if ((opcode
&0xF000) == 0x8000)
1771 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s%c r%i, [r%i, #0x%" PRIx32
"]", address
, opcode
, mnemonic
, suffix
, Rd
, Rn
, offset
<< shift
);
1773 instruction
->info
.load_store
.Rd
= Rd
;
1774 instruction
->info
.load_store
.Rn
= Rn
;
1775 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1776 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1777 instruction
->info
.load_store
.offset
.offset
= offset
<< shift
;
1782 int evaluate_load_store_stack_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1784 uint32_t offset
= opcode
& 0xff;
1785 uint8_t Rd
= (opcode
>> 8) & 0x7;
1786 uint32_t L
= opcode
& (1 << 11);
1791 instruction
->type
= ARM_LDR
;
1796 instruction
->type
= ARM_STR
;
1800 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s r%i, [SP, #0x%" PRIx32
"]", address
, opcode
, mnemonic
, Rd
, offset
*4);
1802 instruction
->info
.load_store
.Rd
= Rd
;
1803 instruction
->info
.load_store
.Rn
= 13 /*SP*/;
1804 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
1805 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
1806 instruction
->info
.load_store
.offset
.offset
= offset
*4;
1811 int evaluate_add_sp_pc_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1813 uint32_t imm
= opcode
& 0xff;
1814 uint8_t Rd
= (opcode
>> 8) & 0x7;
1816 uint32_t SP
= opcode
& (1 << 11);
1819 instruction
->type
= ARM_ADD
;
1832 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tADD r%i, %s, #0x%" PRIx32
"", address
, opcode
, Rd
,reg_name
, imm
*4);
1834 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
1835 instruction
->info
.data_proc
.Rd
= Rd
;
1836 instruction
->info
.data_proc
.Rn
= Rn
;
1837 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
1842 int evaluate_adjust_stack_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1844 uint32_t imm
= opcode
& 0x7f;
1845 uint8_t opc
= opcode
& (1 << 7);
1851 instruction
->type
= ARM_SUB
;
1856 instruction
->type
= ARM_ADD
;
1860 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s SP, #0x%" PRIx32
"", address
, opcode
, mnemonic
, imm
*4);
1862 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
1863 instruction
->info
.data_proc
.Rd
= 13 /*SP*/;
1864 instruction
->info
.data_proc
.Rn
= 13 /*SP*/;
1865 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
1870 int evaluate_breakpoint_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1872 uint32_t imm
= opcode
& 0xff;
1874 instruction
->type
= ARM_BKPT
;
1876 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tBKPT 0x%02" PRIx32
"", address
, opcode
, imm
);
1881 int evaluate_load_store_multiple_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1883 uint32_t reg_list
= opcode
& 0xff;
1884 uint32_t L
= opcode
& (1 << 11);
1885 uint32_t R
= opcode
& (1 << 8);
1886 uint8_t Rn
= (opcode
>> 8) & 7;
1887 uint8_t addr_mode
= 0 /* IA */;
1891 char ptr_name
[7] = "";
1894 if ((opcode
& 0xf000) == 0xc000)
1895 { /* generic load/store multiple */
1898 instruction
->type
= ARM_LDM
;
1903 instruction
->type
= ARM_STM
;
1906 snprintf(ptr_name
,7,"r%i!, ",Rn
);
1913 instruction
->type
= ARM_LDM
;
1916 reg_list
|= (1 << 15) /*PC*/;
1920 instruction
->type
= ARM_STM
;
1922 addr_mode
= 3; /*DB*/
1924 reg_list
|= (1 << 14) /*LR*/;
1928 reg_names_p
= reg_names
;
1929 for (i
= 0; i
<= 15; i
++)
1931 if (reg_list
& (1 << i
))
1932 reg_names_p
+= snprintf(reg_names_p
, (reg_names
+ 40 - reg_names_p
), "r%i, ", i
);
1934 if (reg_names_p
> reg_names
)
1935 reg_names_p
[-2] = '\0';
1936 else /* invalid op : no registers */
1937 reg_names
[0] = '\0';
1939 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\t%s %s{%s}", address
, opcode
, mnemonic
, ptr_name
,reg_names
);
1941 instruction
->info
.load_store_multiple
.register_list
= reg_list
;
1942 instruction
->info
.load_store_multiple
.Rn
= Rn
;
1943 instruction
->info
.load_store_multiple
.addressing_mode
= addr_mode
;
1948 int evaluate_cond_branch_thumb(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
1950 uint32_t offset
= opcode
& 0xff;
1951 uint8_t cond
= (opcode
>> 8) & 0xf;
1952 uint32_t target_address
;
1956 instruction
->type
= ARM_SWI
;
1957 snprintf(instruction
->text
, 128,
1958 "0x%8.8" PRIx32
"\t0x%4.4x\tSVC 0x%02" PRIx32
,
1959 address
, opcode
, offset
);
1962 else if (cond
== 0xe)
1964 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1965 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tUNDEFINED INSTRUCTION", address
, opcode
);
1969 /* sign extend 8-bit offset */
1970 if (offset
& 0x00000080)
1971 offset
= 0xffffff00 | offset
;
1973 target_address
= address
+ 4 + (offset
<< 1);
1975 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%4.4x\tB%s 0x%8.8" PRIx32
, address
, opcode
,
1976 arm_condition_strings
[cond
], target_address
);
1978 instruction
->type
= ARM_B
;
1979 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
1980 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
1985 static int evaluate_cb_thumb(uint16_t opcode
, uint32_t address
,
1986 arm_instruction_t
*instruction
)
1990 /* added in Thumb2 */
1991 offset
= (opcode
>> 3) & 0x1f;
1992 offset
|= (opcode
& 0x0200) >> 4;
1994 snprintf(instruction
->text
, 128,
1995 "0x%8.8" PRIx32
"\t0x%4.4x\tCB%sZ r%d, %#8.8" PRIx32
,
1997 (opcode
& 0x0800) ? "N" : "",
1998 opcode
& 0x7, address
+ 4 + (offset
<< 1));
2003 static int evaluate_extend_thumb(uint16_t opcode
, uint32_t address
,
2004 arm_instruction_t
*instruction
)
2006 /* added in ARMv6 */
2007 snprintf(instruction
->text
, 128,
2008 "0x%8.8" PRIx32
"\t0x%4.4x\t%cXT%c r%d, r%d",
2010 (opcode
& 0x0080) ? 'U' : 'S',
2011 (opcode
& 0x0040) ? 'B' : 'H',
2012 opcode
& 0x7, (opcode
>> 3) & 0x7);
2017 static int evaluate_cps_thumb(uint16_t opcode
, uint32_t address
,
2018 arm_instruction_t
*instruction
)
2020 /* added in ARMv6 */
2021 if ((opcode
& 0x0ff0) == 0x0650)
2022 snprintf(instruction
->text
, 128,
2023 "0x%8.8" PRIx32
"\t0x%4.4x\tSETEND %s",
2025 (opcode
& 0x80) ? "BE" : "LE");
2026 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2027 snprintf(instruction
->text
, 128,
2028 "0x%8.8" PRIx32
"\t0x%4.4x\tCPSI%c %s%s%s",
2030 (opcode
& 0x0010) ? 'D' : 'E',
2031 (opcode
& 0x0004) ? "A" : "",
2032 (opcode
& 0x0002) ? "I" : "",
2033 (opcode
& 0x0001) ? "F" : "");
2038 static int evaluate_byterev_thumb(uint16_t opcode
, uint32_t address
,
2039 arm_instruction_t
*instruction
)
2043 /* added in ARMv6 */
2044 switch (opcode
& 0x00c0) {
2055 snprintf(instruction
->text
, 128,
2056 "0x%8.8" PRIx32
"\t0x%4.4x\tREV%s r%d, r%d",
2057 address
, opcode
, suffix
,
2058 opcode
& 0x7, (opcode
>> 3) & 0x7);
2063 static int evaluate_hint_thumb(uint16_t opcode
, uint32_t address
,
2064 arm_instruction_t
*instruction
)
2068 switch ((opcode
>> 4) & 0x0f) {
2085 hint
= "HINT (UNRECOGNIZED)";
2089 snprintf(instruction
->text
, 128,
2090 "0x%8.8" PRIx32
"\t0x%4.4x\t%s",
2091 address
, opcode
, hint
);
2096 static int evaluate_ifthen_thumb(uint16_t opcode
, uint32_t address
,
2097 arm_instruction_t
*instruction
)
2099 unsigned cond
= (opcode
>> 4) & 0x0f;
2100 char *x
= "", *y
= "", *z
= "";
2103 z
= (opcode
& 0x02) ? "T" : "E";
2105 y
= (opcode
& 0x04) ? "T" : "E";
2107 x
= (opcode
& 0x08) ? "T" : "E";
2109 snprintf(instruction
->text
, 128,
2110 "0x%8.8" PRIx32
"\t0x%4.4x\tIT%s%s%s %s",
2112 x
, y
, z
, arm_condition_strings
[cond
]);
2114 /* NOTE: strictly speaking, the next 1-4 instructions should
2115 * now be displayed with the relevant conditional suffix...
2121 int thumb_evaluate_opcode(uint16_t opcode
, uint32_t address
, arm_instruction_t
*instruction
)
2123 /* clear fields, to avoid confusion */
2124 memset(instruction
, 0, sizeof(arm_instruction_t
));
2125 instruction
->opcode
= opcode
;
2126 instruction
->instruction_size
= 2;
2128 if ((opcode
& 0xe000) == 0x0000)
2130 /* add/substract register or immediate */
2131 if ((opcode
& 0x1800) == 0x1800)
2132 return evaluate_add_sub_thumb(opcode
, address
, instruction
);
2133 /* shift by immediate */
2135 return evaluate_shift_imm_thumb(opcode
, address
, instruction
);
2138 /* Add/substract/compare/move immediate */
2139 if ((opcode
& 0xe000) == 0x2000)
2141 return evaluate_data_proc_imm_thumb(opcode
, address
, instruction
);
2144 /* Data processing instructions */
2145 if ((opcode
& 0xf800) == 0x4000)
2147 return evaluate_data_proc_thumb(opcode
, address
, instruction
);
2150 /* Load from literal pool */
2151 if ((opcode
& 0xf800) == 0x4800)
2153 return evaluate_load_literal_thumb(opcode
, address
, instruction
);
2156 /* Load/Store register offset */
2157 if ((opcode
& 0xf000) == 0x5000)
2159 return evaluate_load_store_reg_thumb(opcode
, address
, instruction
);
2162 /* Load/Store immediate offset */
2163 if (((opcode
& 0xe000) == 0x6000)
2164 ||((opcode
& 0xf000) == 0x8000))
2166 return evaluate_load_store_imm_thumb(opcode
, address
, instruction
);
2169 /* Load/Store from/to stack */
2170 if ((opcode
& 0xf000) == 0x9000)
2172 return evaluate_load_store_stack_thumb(opcode
, address
, instruction
);
2176 if ((opcode
& 0xf000) == 0xa000)
2178 return evaluate_add_sp_pc_thumb(opcode
, address
, instruction
);
2182 if ((opcode
& 0xf000) == 0xb000)
2184 switch ((opcode
>> 8) & 0x0f) {
2186 return evaluate_adjust_stack_thumb(opcode
, address
, instruction
);
2191 return evaluate_cb_thumb(opcode
, address
, instruction
);
2193 return evaluate_extend_thumb(opcode
, address
, instruction
);
2198 return evaluate_load_store_multiple_thumb(opcode
, address
,
2201 return evaluate_cps_thumb(opcode
, address
, instruction
);
2203 if ((opcode
& 0x00c0) == 0x0080)
2205 return evaluate_byterev_thumb(opcode
, address
, instruction
);
2207 return evaluate_breakpoint_thumb(opcode
, address
, instruction
);
2209 if (opcode
& 0x000f)
2210 return evaluate_ifthen_thumb(opcode
, address
,
2213 return evaluate_hint_thumb(opcode
, address
,
2217 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2218 snprintf(instruction
->text
, 128,
2219 "0x%8.8" PRIx32
"\t0x%4.4x\tUNDEFINED INSTRUCTION",
2224 /* Load/Store multiple */
2225 if ((opcode
& 0xf000) == 0xc000)
2227 return evaluate_load_store_multiple_thumb(opcode
, address
, instruction
);
2230 /* Conditional branch + SWI */
2231 if ((opcode
& 0xf000) == 0xd000)
2233 return evaluate_cond_branch_thumb(opcode
, address
, instruction
);
2236 if ((opcode
& 0xe000) == 0xe000)
2238 /* Undefined instructions */
2239 if ((opcode
& 0xf801) == 0xe801)
2241 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2242 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8x\tUNDEFINED INSTRUCTION", address
, opcode
);
2246 { /* Branch to offset */
2247 return evaluate_b_bl_blx_thumb(opcode
, address
, instruction
);
2251 LOG_ERROR("should never reach this point (opcode=%04x)",opcode
);
2256 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2257 * always set. That means eventual arm_simulate_step() support for Thumb2
2258 * will need work in this area.
2260 int thumb2_opcode(target_t
*target
, uint32_t address
, arm_instruction_t
*instruction
)
2266 /* clear low bit ... it's set on function pointers */
2269 /* clear fields, to avoid confusion */
2270 memset(instruction
, 0, sizeof(arm_instruction_t
));
2272 /* read first halfword, see if this is the only one */
2273 retval
= target_read_u16(target
, address
, &op
);
2274 if (retval
!= ERROR_OK
)
2277 switch (op
& 0xf800) {
2281 /* 32-bit instructions */
2282 instruction
->instruction_size
= 4;
2284 retval
= target_read_u16(target
, address
+ 2, &op
);
2285 if (retval
!= ERROR_OK
)
2288 instruction
->opcode
= opcode
;
2291 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2292 return thumb_evaluate_opcode(op
, address
, instruction
);
2295 /* FIXME decode the 32-bit instructions */
2297 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode
);
2299 snprintf(instruction
->text
, 128,
2300 "0x%8.8" PRIx32
"\t0x%8.8x\t... 32-bit Thumb2 ...",
2305 int arm_access_size(arm_instruction_t
*instruction
)
2307 if ((instruction
->type
== ARM_LDRB
)
2308 || (instruction
->type
== ARM_LDRBT
)
2309 || (instruction
->type
== ARM_LDRSB
)
2310 || (instruction
->type
== ARM_STRB
)
2311 || (instruction
->type
== ARM_STRBT
))
2315 else if ((instruction
->type
== ARM_LDRH
)
2316 || (instruction
->type
== ARM_LDRSH
)
2317 || (instruction
->type
== ARM_STRH
))
2321 else if ((instruction
->type
== ARM_LDR
)
2322 || (instruction
->type
== ARM_LDRT
)
2323 || (instruction
->type
== ARM_STR
)
2324 || (instruction
->type
== ARM_STRT
))
2328 else if ((instruction
->type
== ARM_LDRD
)
2329 || (instruction
->type
== ARM_STRD
))
2335 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)