1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include "breakpoints.h"
33 #include "arm_disassembler.h"
34 #include "binarybuffer.h"
35 #include "algorithm.h"
39 static const uint8_t arm_usr_indices
[17] = {
40 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ARMV4_5_CPSR
,
43 static const uint8_t arm_fiq_indices
[8] = {
44 16, 17, 18, 19, 20, 21, 22, ARMV4_5_SPSR_FIQ
,
47 static const uint8_t arm_irq_indices
[3] = {
48 23, 24, ARMV4_5_SPSR_IRQ
,
51 static const uint8_t arm_svc_indices
[3] = {
52 25, 26, ARMV4_5_SPSR_SVC
,
55 static const uint8_t arm_abt_indices
[3] = {
56 27, 28, ARMV4_5_SPSR_ABT
,
59 static const uint8_t arm_und_indices
[3] = {
60 29, 30, ARMV4_5_SPSR_UND
,
63 static const uint8_t arm_mon_indices
[3] = {
70 /* For user and system modes, these list indices for all registers.
71 * otherwise they're just indices for the shadow registers and SPSR.
73 unsigned short n_indices
;
74 const uint8_t *indices
;
76 /* Seven modes are standard from ARM7 on. "System" and "User" share
77 * the same registers; other modes shadow from 3 to 8 registers.
81 .psr
= ARMV4_5_MODE_USR
,
82 .n_indices
= ARRAY_SIZE(arm_usr_indices
),
83 .indices
= arm_usr_indices
,
87 .psr
= ARMV4_5_MODE_FIQ
,
88 .n_indices
= ARRAY_SIZE(arm_fiq_indices
),
89 .indices
= arm_fiq_indices
,
93 .psr
= ARMV4_5_MODE_SVC
,
94 .n_indices
= ARRAY_SIZE(arm_svc_indices
),
95 .indices
= arm_svc_indices
,
99 .psr
= ARMV4_5_MODE_ABT
,
100 .n_indices
= ARRAY_SIZE(arm_abt_indices
),
101 .indices
= arm_abt_indices
,
105 .psr
= ARMV4_5_MODE_IRQ
,
106 .n_indices
= ARRAY_SIZE(arm_irq_indices
),
107 .indices
= arm_irq_indices
,
110 .name
= "Undefined instruction",
111 .psr
= ARMV4_5_MODE_UND
,
112 .n_indices
= ARRAY_SIZE(arm_und_indices
),
113 .indices
= arm_und_indices
,
117 .psr
= ARMV4_5_MODE_SYS
,
118 .n_indices
= ARRAY_SIZE(arm_usr_indices
),
119 .indices
= arm_usr_indices
,
121 /* TrustZone "Security Extensions" add a secure monitor mode.
122 * This is distinct from a "debug monitor" which can support
123 * non-halting debug, in conjunction with some debuggers.
126 .name
= "Secure Monitor",
128 .n_indices
= ARRAY_SIZE(arm_mon_indices
),
129 .indices
= arm_mon_indices
,
133 /** Map PSR mode bits to the name of an ARM processor operating mode. */
134 const char *arm_mode_name(unsigned psr_mode
)
136 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
137 if (arm_mode_data
[i
].psr
== psr_mode
)
138 return arm_mode_data
[i
].name
;
140 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
141 return "UNRECOGNIZED";
144 /** Return true iff the parameter denotes a valid ARM processor mode. */
145 bool is_arm_mode(unsigned psr_mode
)
147 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
148 if (arm_mode_data
[i
].psr
== psr_mode
)
154 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
155 int armv4_5_mode_to_number(enum armv4_5_mode mode
)
158 case ARMV4_5_MODE_ANY
:
159 /* map MODE_ANY to user mode */
160 case ARMV4_5_MODE_USR
:
162 case ARMV4_5_MODE_FIQ
:
164 case ARMV4_5_MODE_IRQ
:
166 case ARMV4_5_MODE_SVC
:
168 case ARMV4_5_MODE_ABT
:
170 case ARMV4_5_MODE_UND
:
172 case ARMV4_5_MODE_SYS
:
177 LOG_ERROR("invalid mode value encountered %d", mode
);
182 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
183 enum armv4_5_mode
armv4_5_number_to_mode(int number
)
187 return ARMV4_5_MODE_USR
;
189 return ARMV4_5_MODE_FIQ
;
191 return ARMV4_5_MODE_IRQ
;
193 return ARMV4_5_MODE_SVC
;
195 return ARMV4_5_MODE_ABT
;
197 return ARMV4_5_MODE_UND
;
199 return ARMV4_5_MODE_SYS
;
203 LOG_ERROR("mode index out of bounds %d", number
);
204 return ARMV4_5_MODE_ANY
;
208 char* armv4_5_state_strings
[] =
210 "ARM", "Thumb", "Jazelle", "ThumbEE",
213 /* Templates for ARM core registers.
215 * NOTE: offsets in this table are coupled to the arm_mode_data
216 * table above, the armv4_5_core_reg_map array below, and also to
217 * the ARMV4_5_*PSR* symols.
219 static const struct {
220 /* The name is used for e.g. the "regs" command. */
223 /* The {cookie, mode} tuple uniquely identifies one register.
224 * In a given mode, cookies 0..15 map to registers R0..R15,
225 * with R13..R15 usually called SP, LR, PC.
227 * MODE_ANY is used as *input* to the mapping, and indicates
228 * various special cases (sigh) and errors.
230 * Cookie 16 is (currently) confusing, since it indicates
231 * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY.
232 * (Exception modes have both CPSR and SPSR registers ...)
235 enum armv4_5_mode mode
;
236 } arm_core_regs
[] = {
237 { .name
= "r0", .cookie
= 0, .mode
= ARMV4_5_MODE_ANY
, },
238 { .name
= "r1", .cookie
= 1, .mode
= ARMV4_5_MODE_ANY
, },
239 { .name
= "r2", .cookie
= 2, .mode
= ARMV4_5_MODE_ANY
, },
240 { .name
= "r3", .cookie
= 3, .mode
= ARMV4_5_MODE_ANY
, },
241 { .name
= "r4", .cookie
= 4, .mode
= ARMV4_5_MODE_ANY
, },
242 { .name
= "r5", .cookie
= 5, .mode
= ARMV4_5_MODE_ANY
, },
243 { .name
= "r6", .cookie
= 6, .mode
= ARMV4_5_MODE_ANY
, },
244 { .name
= "r7", .cookie
= 7, .mode
= ARMV4_5_MODE_ANY
, },
246 /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging
247 * them as MODE_ANY creates special cases.
249 { .name
= "r8", .cookie
= 8, .mode
= ARMV4_5_MODE_ANY
, },
250 { .name
= "r9", .cookie
= 9, .mode
= ARMV4_5_MODE_ANY
, },
251 { .name
= "r10", .cookie
= 10, .mode
= ARMV4_5_MODE_ANY
, },
252 { .name
= "r11", .cookie
= 11, .mode
= ARMV4_5_MODE_ANY
, },
253 { .name
= "r12", .cookie
= 12, .mode
= ARMV4_5_MODE_ANY
, },
255 /* NOTE all MODE_USR registers are equivalent to MODE_SYS ones */
256 { .name
= "sp_usr", .cookie
= 13, .mode
= ARMV4_5_MODE_USR
, },
257 { .name
= "lr_usr", .cookie
= 14, .mode
= ARMV4_5_MODE_USR
, },
259 { .name
= "pc", .cookie
= 15, .mode
= ARMV4_5_MODE_ANY
, },
261 { .name
= "r8_fiq", .cookie
= 8, .mode
= ARMV4_5_MODE_FIQ
, },
262 { .name
= "r9_fiq", .cookie
= 9, .mode
= ARMV4_5_MODE_FIQ
, },
263 { .name
= "r10_fiq", .cookie
= 10, .mode
= ARMV4_5_MODE_FIQ
, },
264 { .name
= "r11_fiq", .cookie
= 11, .mode
= ARMV4_5_MODE_FIQ
, },
265 { .name
= "r12_fiq", .cookie
= 12, .mode
= ARMV4_5_MODE_FIQ
, },
267 { .name
= "lr_fiq", .cookie
= 13, .mode
= ARMV4_5_MODE_FIQ
, },
268 { .name
= "sp_fiq", .cookie
= 14, .mode
= ARMV4_5_MODE_FIQ
, },
270 { .name
= "lr_irq", .cookie
= 13, .mode
= ARMV4_5_MODE_IRQ
, },
271 { .name
= "sp_irq", .cookie
= 14, .mode
= ARMV4_5_MODE_IRQ
, },
273 { .name
= "lr_svc", .cookie
= 13, .mode
= ARMV4_5_MODE_SVC
, },
274 { .name
= "sp_svc", .cookie
= 14, .mode
= ARMV4_5_MODE_SVC
, },
276 { .name
= "lr_abt", .cookie
= 13, .mode
= ARMV4_5_MODE_ABT
, },
277 { .name
= "sp_abt", .cookie
= 14, .mode
= ARMV4_5_MODE_ABT
, },
279 { .name
= "lr_und", .cookie
= 13, .mode
= ARMV4_5_MODE_UND
, },
280 { .name
= "sp_und", .cookie
= 14, .mode
= ARMV4_5_MODE_UND
, },
282 { .name
= "cpsr", .cookie
= 16, .mode
= ARMV4_5_MODE_ANY
, },
283 { .name
= "spsr_fiq", .cookie
= 16, .mode
= ARMV4_5_MODE_FIQ
, },
284 { .name
= "spsr_irq", .cookie
= 16, .mode
= ARMV4_5_MODE_IRQ
, },
285 { .name
= "spsr_svc", .cookie
= 16, .mode
= ARMV4_5_MODE_SVC
, },
286 { .name
= "spsr_abt", .cookie
= 16, .mode
= ARMV4_5_MODE_ABT
, },
287 { .name
= "spsr_und", .cookie
= 16, .mode
= ARMV4_5_MODE_UND
, },
289 { .name
= "lr_mon", .cookie
= 13, .mode
= ARM_MODE_MON
, },
290 { .name
= "sp_mon", .cookie
= 14, .mode
= ARM_MODE_MON
, },
291 { .name
= "spsr_mon", .cookie
= 16, .mode
= ARM_MODE_MON
, },
294 /* map core mode (USR, FIQ, ...) and register number to
295 * indices into the register cache
297 const int armv4_5_core_reg_map
[8][17] =
300 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
302 { /* FIQ (8 shadows of USR, vs normal 3) */
303 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
306 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
309 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
312 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
315 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
317 { /* SYS (same registers as USR) */
318 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
321 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
325 static const uint8_t arm_gdb_dummy_fp_value
[12];
328 * Dummy FPA registers are required to support GDB on ARM.
329 * Register packets require eight obsolete FPA register values.
330 * Modern ARM cores use Vector Floating Point (VFP), if they
331 * have any floating point support. VFP is not FPA-compatible.
333 struct reg arm_gdb_dummy_fp_reg
=
335 .name
= "GDB dummy FPA register",
336 .value
= (uint8_t *) arm_gdb_dummy_fp_value
,
341 static const uint8_t arm_gdb_dummy_fps_value
[4];
344 * Dummy FPA status registers are required to support GDB on ARM.
345 * Register packets require an obsolete FPA status register.
347 struct reg arm_gdb_dummy_fps_reg
=
349 .name
= "GDB dummy FPA status register",
350 .value
= (uint8_t *) arm_gdb_dummy_fps_value
,
355 static void arm_gdb_dummy_init(void) __attribute__ ((constructor
));
357 static void arm_gdb_dummy_init(void)
359 register_init_dummy(&arm_gdb_dummy_fp_reg
);
360 register_init_dummy(&arm_gdb_dummy_fps_reg
);
363 static int armv4_5_get_core_reg(struct reg
*reg
)
366 struct arm_reg
*armv4_5
= reg
->arch_info
;
367 struct target
*target
= armv4_5
->target
;
369 if (target
->state
!= TARGET_HALTED
)
371 LOG_ERROR("Target not halted");
372 return ERROR_TARGET_NOT_HALTED
;
375 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, reg
, armv4_5
->num
, armv4_5
->mode
);
376 if (retval
== ERROR_OK
) {
384 static int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
386 struct arm_reg
*armv4_5
= reg
->arch_info
;
387 struct target
*target
= armv4_5
->target
;
388 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
389 uint32_t value
= buf_get_u32(buf
, 0, 32);
391 if (target
->state
!= TARGET_HALTED
)
393 LOG_ERROR("Target not halted");
394 return ERROR_TARGET_NOT_HALTED
;
397 /* Except for CPSR, the "reg" command exposes a writeback model
398 * for the register cache.
400 buf_set_u32(reg
->value
, 0, 32, value
);
404 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
406 /* FIXME handle J bit too; mostly for ThumbEE, also Jazelle */
409 /* T bit should be set */
410 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
412 /* change state to Thumb */
413 LOG_DEBUG("changing to Thumb state");
414 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
419 /* T bit should be cleared */
420 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
422 /* change state to ARM */
423 LOG_DEBUG("changing to ARM state");
424 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
428 /* REVISIT Why only update core for mode change, not also
429 * for state changes? Possibly older cores need to stay
430 * in ARM mode during halt mode debug, not execute Thumb;
431 * v6/v7a/v7r seem to do that automatically...
434 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
436 LOG_DEBUG("changing ARM core mode to '%s'",
437 arm_mode_name(value
& 0x1f));
438 armv4_5_target
->core_mode
= value
& 0x1f;
439 armv4_5_target
->write_core_reg(target
, reg
,
440 16, ARMV4_5_MODE_ANY
, value
);
448 static const struct reg_arch_type arm_reg_type
= {
449 .get
= armv4_5_get_core_reg
,
450 .set
= armv4_5_set_core_reg
,
453 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
455 int num_regs
= ARRAY_SIZE(arm_core_regs
);
456 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
457 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
458 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
461 if (!cache
|| !reg_list
|| !arch_info
) {
468 cache
->name
= "ARM registers";
470 cache
->reg_list
= reg_list
;
473 for (i
= 0; i
< num_regs
; i
++)
475 /* Skip registers this core doesn't expose */
476 if (arm_core_regs
[i
].mode
== ARM_MODE_MON
477 && armv4_5_common
->core_type
!= ARM_MODE_MON
)
480 /* REVISIT handle Cortex-M, which only shadows R13/SP */
482 arch_info
[i
].num
= arm_core_regs
[i
].cookie
;
483 arch_info
[i
].mode
= arm_core_regs
[i
].mode
;
484 arch_info
[i
].target
= target
;
485 arch_info
[i
].armv4_5_common
= armv4_5_common
;
487 reg_list
[i
].name
= (char *) arm_core_regs
[i
].name
;
488 reg_list
[i
].size
= 32;
489 reg_list
[i
].value
= &arch_info
[i
].value
;
490 reg_list
[i
].type
= &arm_reg_type
;
491 reg_list
[i
].arch_info
= &arch_info
[i
];
496 armv4_5_common
->core_cache
= cache
;
500 int armv4_5_arch_state(struct target
*target
)
502 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
504 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
506 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
510 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
511 armv4_5_state_strings
[armv4_5
->core_state
],
512 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
513 arm_mode_name(armv4_5
->core_mode
),
514 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
515 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
520 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
521 cache->reg_list[armv4_5_core_reg_map[mode][num]]
523 COMMAND_HANDLER(handle_armv4_5_reg_command
)
525 struct target
*target
= get_current_target(CMD_CTX
);
526 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
530 if (!is_arm(armv4_5
))
532 command_print(CMD_CTX
, "current target isn't an ARM");
536 if (target
->state
!= TARGET_HALTED
)
538 command_print(CMD_CTX
, "error: target must be halted for register accesses");
542 if (!is_arm_mode(armv4_5
->core_mode
))
545 if (!armv4_5
->full_context
) {
546 command_print(CMD_CTX
, "error: target doesn't support %s",
551 num_regs
= armv4_5
->core_cache
->num_regs
;
552 regs
= armv4_5
->core_cache
->reg_list
;
554 for (unsigned mode
= 0; mode
< ARRAY_SIZE(arm_mode_data
); mode
++) {
559 /* label this bank of registers (or shadows) */
560 switch (arm_mode_data
[mode
].psr
) {
561 case ARMV4_5_MODE_SYS
:
563 case ARMV4_5_MODE_USR
:
564 name
= "System and User";
568 if (armv4_5
->core_type
!= ARM_MODE_MON
)
572 name
= arm_mode_data
[mode
].name
;
576 command_print(CMD_CTX
, "%s%s mode %sregisters",
579 /* display N rows of up to 4 registers each */
580 for (unsigned i
= 0; i
< arm_mode_data
[mode
].n_indices
;) {
584 for (unsigned j
= 0; j
< 4; j
++, i
++) {
586 struct reg
*reg
= regs
;
588 if (i
>= arm_mode_data
[mode
].n_indices
)
591 reg
+= arm_mode_data
[mode
].indices
[i
];
593 /* REVISIT be smarter about faults... */
595 armv4_5
->full_context(target
);
597 value
= buf_get_u32(reg
->value
, 0, 32);
598 output_len
+= snprintf(output
+ output_len
,
599 sizeof(output
) - output_len
,
600 "%8s: %8.8" PRIx32
" ",
603 command_print(CMD_CTX
, "%s", output
);
610 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
612 struct target
*target
= get_current_target(CMD_CTX
);
613 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
615 if (!is_arm(armv4_5
))
617 command_print(CMD_CTX
, "current target isn't an ARM");
623 if (strcmp(CMD_ARGV
[0], "arm") == 0)
625 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
627 if (strcmp(CMD_ARGV
[0], "thumb") == 0)
629 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
633 command_print(CMD_CTX
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
638 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
640 int retval
= ERROR_OK
;
641 struct target
*target
= get_current_target(CMD_CTX
);
642 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
648 command_print(CMD_CTX
, "current target isn't an ARM");
654 if (strcmp(CMD_ARGV
[2], "thumb") != 0)
659 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], count
);
662 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
663 if (address
& 0x01) {
665 command_print(CMD_CTX
, "Disassemble as Thumb");
673 command_print(CMD_CTX
,
674 "usage: arm disassemble <address> [<count> ['thumb']]");
679 while (count
-- > 0) {
680 struct arm_instruction cur_instruction
;
683 /* Always use Thumb2 disassembly for best handling
684 * of 32-bit BL/BLX, and to work with newer cores
685 * (some ARMv6, all ARMv7) that use Thumb2.
687 retval
= thumb2_opcode(target
, address
,
689 if (retval
!= ERROR_OK
)
694 retval
= target_read_u32(target
, address
, &opcode
);
695 if (retval
!= ERROR_OK
)
697 retval
= arm_evaluate_opcode(opcode
, address
,
698 &cur_instruction
) != ERROR_OK
;
699 if (retval
!= ERROR_OK
)
702 command_print(CMD_CTX
, "%s", cur_instruction
.text
);
703 address
+= cur_instruction
.instruction_size
;
709 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
711 struct command
*armv4_5_cmd
;
713 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
715 "generic ARM commands");
717 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
718 handle_armv4_5_reg_command
, COMMAND_EXEC
,
719 "display ARM core registers");
720 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
721 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
722 "display/change ARM core state <arm | thumb>");
723 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
724 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
725 "disassemble instructions "
726 "<address> [<count> ['thumb']]");
731 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
733 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
736 if (!is_arm_mode(armv4_5
->core_mode
))
740 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
742 for (i
= 0; i
< 16; i
++)
744 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
747 for (i
= 16; i
< 24; i
++)
749 (*reg_list
)[i
] = &arm_gdb_dummy_fp_reg
;
752 (*reg_list
)[24] = &arm_gdb_dummy_fps_reg
;
753 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
758 /* wait for execution to complete and check exit point */
759 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
762 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
764 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
768 if (target
->state
!= TARGET_HALTED
)
770 if ((retval
= target_halt(target
)) != ERROR_OK
)
772 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
776 return ERROR_TARGET_TIMEOUT
;
779 /* fast exit: ARMv5+ code can use BKPT */
780 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
781 0, 32) != exit_point
)
783 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
784 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
785 return ERROR_TARGET_TIMEOUT
;
791 int armv4_5_run_algorithm_inner(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
, int (*run_it
)(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
))
793 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
794 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
795 enum armv4_5_state core_state
= armv4_5
->core_state
;
796 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
797 uint32_t context
[17];
799 int exit_breakpoint_size
= 0;
801 int retval
= ERROR_OK
;
802 LOG_DEBUG("Running algorithm");
804 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
806 LOG_ERROR("current target isn't an ARMV4/5 target");
807 return ERROR_TARGET_INVALID
;
810 if (target
->state
!= TARGET_HALTED
)
812 LOG_WARNING("target not halted");
813 return ERROR_TARGET_NOT_HALTED
;
816 if (!is_arm_mode(armv4_5
->core_mode
))
819 /* armv5 and later can terminate with BKPT instruction; less overhead */
820 if (!exit_point
&& armv4_5
->is_armv4
)
822 LOG_ERROR("ARMv4 target needs HW breakpoint location");
826 for (i
= 0; i
<= 16; i
++)
830 r
= &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
,
831 armv4_5_algorithm_info
->core_mode
, i
);
833 armv4_5
->read_core_reg(target
, r
, i
,
834 armv4_5_algorithm_info
->core_mode
);
835 context
[i
] = buf_get_u32(r
->value
, 0, 32);
837 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
839 for (i
= 0; i
< num_mem_params
; i
++)
841 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
847 for (i
= 0; i
< num_reg_params
; i
++)
849 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
852 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
853 return ERROR_INVALID_ARGUMENTS
;
856 if (reg
->size
!= reg_params
[i
].size
)
858 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
859 return ERROR_INVALID_ARGUMENTS
;
862 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
868 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
869 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
870 exit_breakpoint_size
= 4;
871 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
872 exit_breakpoint_size
= 2;
875 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
876 return ERROR_INVALID_ARGUMENTS
;
879 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
881 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
882 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
883 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
884 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
887 /* terminate using a hardware or (ARMv5+) software breakpoint */
888 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
889 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
891 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
892 return ERROR_TARGET_FAILURE
;
895 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
900 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
903 breakpoint_remove(target
, exit_point
);
905 if (retval
!= ERROR_OK
)
908 for (i
= 0; i
< num_mem_params
; i
++)
910 if (mem_params
[i
].direction
!= PARAM_OUT
)
911 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
917 for (i
= 0; i
< num_reg_params
; i
++)
919 if (reg_params
[i
].direction
!= PARAM_OUT
)
922 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
925 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
926 retval
= ERROR_INVALID_ARGUMENTS
;
930 if (reg
->size
!= reg_params
[i
].size
)
932 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
933 retval
= ERROR_INVALID_ARGUMENTS
;
937 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
941 for (i
= 0; i
<= 16; i
++)
944 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
945 if (regvalue
!= context
[i
])
947 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
"", ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).name
, context
[i
]);
948 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
949 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
950 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
953 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
954 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
955 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
957 armv4_5
->core_state
= core_state
;
958 armv4_5
->core_mode
= core_mode
;
963 int armv4_5_run_algorithm(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
965 return armv4_5_run_algorithm_inner(target
, num_mem_params
, mem_params
, num_reg_params
, reg_params
, entry_point
, exit_point
, timeout_ms
, arch_info
, armv4_5_run_algorithm_completion
);
969 * Runs ARM code in the target to calculate a CRC32 checksum.
971 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
973 int arm_checksum_memory(struct target
*target
,
974 uint32_t address
, uint32_t count
, uint32_t *checksum
)
976 struct working_area
*crc_algorithm
;
977 struct armv4_5_algorithm armv4_5_info
;
978 struct reg_param reg_params
[2];
982 static const uint32_t arm_crc_code
[] = {
983 0xE1A02000, /* mov r2, r0 */
984 0xE3E00000, /* mov r0, #0xffffffff */
985 0xE1A03001, /* mov r3, r1 */
986 0xE3A04000, /* mov r4, #0 */
987 0xEA00000B, /* b ncomp */
989 0xE7D21004, /* ldrb r1, [r2, r4] */
990 0xE59F7030, /* ldr r7, CRC32XOR */
991 0xE0200C01, /* eor r0, r0, r1, asl 24 */
992 0xE3A05000, /* mov r5, #0 */
994 0xE3500000, /* cmp r0, #0 */
995 0xE1A06080, /* mov r6, r0, asl #1 */
996 0xE2855001, /* add r5, r5, #1 */
997 0xE1A00006, /* mov r0, r6 */
998 0xB0260007, /* eorlt r0, r6, r7 */
999 0xE3550008, /* cmp r5, #8 */
1000 0x1AFFFFF8, /* bne loop */
1001 0xE2844001, /* add r4, r4, #1 */
1003 0xE1540003, /* cmp r4, r3 */
1004 0x1AFFFFF1, /* bne nbyte */
1006 0xEAFFFFFE, /* b end */
1008 0x04C11DB7 /* .word 0x04C11DB7 */
1011 retval
= target_alloc_working_area(target
,
1012 sizeof(arm_crc_code
), &crc_algorithm
);
1013 if (retval
!= ERROR_OK
)
1016 /* convert code into a buffer in target endianness */
1017 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
1018 retval
= target_write_u32(target
,
1019 crc_algorithm
->address
+ i
* sizeof(uint32_t),
1021 if (retval
!= ERROR_OK
)
1025 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1026 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1027 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1029 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
1030 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1032 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1033 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1035 /* 20 second timeout/megabyte */
1036 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
1038 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
1039 crc_algorithm
->address
,
1040 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
1041 timeout
, &armv4_5_info
);
1042 if (retval
!= ERROR_OK
) {
1043 LOG_ERROR("error executing ARM crc algorithm");
1044 destroy_reg_param(®_params
[0]);
1045 destroy_reg_param(®_params
[1]);
1046 target_free_working_area(target
, crc_algorithm
);
1050 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
1052 destroy_reg_param(®_params
[0]);
1053 destroy_reg_param(®_params
[1]);
1055 target_free_working_area(target
, crc_algorithm
);
1061 * Runs ARM code in the target to check whether a memory block holds
1062 * all ones. NOR flash which has been erased, and thus may be written,
1065 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
1067 int arm_blank_check_memory(struct target
*target
,
1068 uint32_t address
, uint32_t count
, uint32_t *blank
)
1070 struct working_area
*check_algorithm
;
1071 struct reg_param reg_params
[3];
1072 struct armv4_5_algorithm armv4_5_info
;
1076 static const uint32_t check_code
[] = {
1078 0xe4d03001, /* ldrb r3, [r0], #1 */
1079 0xe0022003, /* and r2, r2, r3 */
1080 0xe2511001, /* subs r1, r1, #1 */
1081 0x1afffffb, /* bne loop */
1083 0xeafffffe /* b end */
1086 /* make sure we have a working area */
1087 retval
= target_alloc_working_area(target
,
1088 sizeof(check_code
), &check_algorithm
);
1089 if (retval
!= ERROR_OK
)
1092 /* convert code into a buffer in target endianness */
1093 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
1094 retval
= target_write_u32(target
,
1095 check_algorithm
->address
1096 + i
* sizeof(uint32_t),
1098 if (retval
!= ERROR_OK
)
1102 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1103 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1104 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1106 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1107 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1109 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1110 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1112 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1113 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1115 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1116 check_algorithm
->address
,
1117 check_algorithm
->address
+ sizeof(check_code
) - 4,
1118 10000, &armv4_5_info
);
1119 if (retval
!= ERROR_OK
) {
1120 destroy_reg_param(®_params
[0]);
1121 destroy_reg_param(®_params
[1]);
1122 destroy_reg_param(®_params
[2]);
1123 target_free_working_area(target
, check_algorithm
);
1127 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
1129 destroy_reg_param(®_params
[0]);
1130 destroy_reg_param(®_params
[1]);
1131 destroy_reg_param(®_params
[2]);
1133 target_free_working_area(target
, check_algorithm
);
1138 static int arm_full_context(struct target
*target
)
1140 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
1141 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
1142 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
1143 int retval
= ERROR_OK
;
1145 for (; num_regs
&& retval
== ERROR_OK
; num_regs
--, reg
++) {
1148 retval
= armv4_5_get_core_reg(reg
);
1153 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
1155 target
->arch_info
= armv4_5
;
1157 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
1158 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
1159 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
1161 /* core_type may be overridden by subtype logic */
1162 armv4_5
->core_type
= ARMV4_5_MODE_ANY
;
1164 /* default full_context() has no core-specific optimizations */
1165 if (!armv4_5
->full_context
&& armv4_5
->read_core_reg
)
1166 armv4_5
->full_context
= arm_full_context
;
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)