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 char *armv4_5_core_reg_list
[] =
41 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
42 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
44 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
54 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
56 "r13_mon", "lr_mon", "spsr_mon",
63 /* Seven modes are standard from ARM7 on. "System" and "User" share
64 * the same registers; other modes shadow from 3 to 8 registers.
68 .psr
= ARMV4_5_MODE_USR
,
72 .psr
= ARMV4_5_MODE_FIQ
,
76 .psr
= ARMV4_5_MODE_SVC
,
80 .psr
= ARMV4_5_MODE_ABT
,
84 .psr
= ARMV4_5_MODE_IRQ
,
87 .name
= "Undefined" /* instruction */,
88 .psr
= ARMV4_5_MODE_UND
,
92 .psr
= ARMV4_5_MODE_SYS
,
94 /* TrustZone "Security Extensions" add a secure monitor mode.
95 * This is distinct from a "debug monitor" which can support
96 * non-halting debug, in conjunction with some debuggers.
99 .name
= "Secure Monitor",
104 /** Map PSR mode bits to the name of an ARM processor operating mode. */
105 const char *arm_mode_name(unsigned psr_mode
)
107 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
108 if (arm_mode_data
[i
].psr
== psr_mode
)
109 return arm_mode_data
[i
].name
;
111 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
112 return "UNRECOGNIZED";
115 /** Return true iff the parameter denotes a valid ARM processor mode. */
116 bool is_arm_mode(unsigned psr_mode
)
118 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
119 if (arm_mode_data
[i
].psr
== psr_mode
)
125 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
126 int armv4_5_mode_to_number(enum armv4_5_mode mode
)
129 case ARMV4_5_MODE_ANY
:
130 /* map MODE_ANY to user mode */
131 case ARMV4_5_MODE_USR
:
133 case ARMV4_5_MODE_FIQ
:
135 case ARMV4_5_MODE_IRQ
:
137 case ARMV4_5_MODE_SVC
:
139 case ARMV4_5_MODE_ABT
:
141 case ARMV4_5_MODE_UND
:
143 case ARMV4_5_MODE_SYS
:
148 LOG_ERROR("invalid mode value encountered %d", mode
);
153 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
154 enum armv4_5_mode
armv4_5_number_to_mode(int number
)
158 return ARMV4_5_MODE_USR
;
160 return ARMV4_5_MODE_FIQ
;
162 return ARMV4_5_MODE_IRQ
;
164 return ARMV4_5_MODE_SVC
;
166 return ARMV4_5_MODE_ABT
;
168 return ARMV4_5_MODE_UND
;
170 return ARMV4_5_MODE_SYS
;
174 LOG_ERROR("mode index out of bounds %d", number
);
175 return ARMV4_5_MODE_ANY
;
179 char* armv4_5_state_strings
[] =
181 "ARM", "Thumb", "Jazelle"
184 static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
186 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
187 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
188 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
189 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
190 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
191 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
192 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
193 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
194 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
195 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
196 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
197 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
198 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
199 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
200 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
201 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
203 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
204 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
205 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
206 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
207 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
208 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
209 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
211 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
212 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
214 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
215 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
217 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
218 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
220 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
221 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
223 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
224 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
225 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
226 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
227 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
228 {16, ARMV4_5_MODE_UND
, NULL
, NULL
},
230 {13, ARM_MODE_MON
, NULL
, NULL
},
231 {14, ARM_MODE_MON
, NULL
, NULL
},
232 {16, ARM_MODE_MON
, NULL
, NULL
},
235 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
236 const int armv4_5_core_reg_map
[8][17] =
239 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
241 { /* FIQ (8 shadows of USR, vs normal 3) */
242 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
245 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
248 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
251 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
254 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
256 { /* SYS (same registers as USR) */
257 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
260 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
264 static const uint8_t arm_gdb_dummy_fp_value
[12];
267 * Dummy FPA registers are required to support GDB on ARM.
268 * Register packets require eight obsolete FPA register values.
269 * Modern ARM cores use Vector Floating Point (VFP), if they
270 * have any floating point support. VFP is not FPA-compatible.
272 struct reg arm_gdb_dummy_fp_reg
=
274 .name
= "GDB dummy FPA register",
275 .value
= (uint8_t *) arm_gdb_dummy_fp_value
,
280 static const uint8_t arm_gdb_dummy_fps_value
[4];
283 * Dummy FPA status registers are required to support GDB on ARM.
284 * Register packets require an obsolete FPA status register.
286 struct reg arm_gdb_dummy_fps_reg
=
288 .name
= "GDB dummy FPA status register",
289 .value
= (uint8_t *) arm_gdb_dummy_fps_value
,
294 static void arm_gdb_dummy_init(void) __attribute__ ((constructor
));
296 static void arm_gdb_dummy_init(void)
298 register_init_dummy(&arm_gdb_dummy_fp_reg
);
299 register_init_dummy(&arm_gdb_dummy_fps_reg
);
302 int armv4_5_get_core_reg(struct reg
*reg
)
305 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
306 struct target
*target
= armv4_5
->target
;
308 if (target
->state
!= TARGET_HALTED
)
310 LOG_ERROR("Target not halted");
311 return ERROR_TARGET_NOT_HALTED
;
314 /* retval = armv4_5->armv4_5_common->full_context(target); */
315 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
320 int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
322 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
323 struct target
*target
= armv4_5
->target
;
324 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
325 uint32_t value
= buf_get_u32(buf
, 0, 32);
327 if (target
->state
!= TARGET_HALTED
)
329 return ERROR_TARGET_NOT_HALTED
;
332 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
336 /* T bit should be set */
337 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
339 /* change state to Thumb */
340 LOG_DEBUG("changing to Thumb state");
341 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
346 /* T bit should be cleared */
347 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
349 /* change state to ARM */
350 LOG_DEBUG("changing to ARM state");
351 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
355 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
357 LOG_DEBUG("changing ARM core mode to '%s'",
358 arm_mode_name(value
& 0x1f));
359 armv4_5_target
->core_mode
= value
& 0x1f;
360 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
364 buf_set_u32(reg
->value
, 0, 32, value
);
371 static const struct reg_arch_type arm_reg_type
= {
372 .get
= armv4_5_get_core_reg
,
373 .set
= armv4_5_set_core_reg
,
376 /** Marks the contents of the register cache as invalid (and clean). */
377 int armv4_5_invalidate_core_regs(struct target
*target
)
379 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
380 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
381 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
383 for (unsigned i
= 0; i
< num_regs
; i
++, reg
++) {
388 /* FIXME don't bother returning a value then */
392 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
394 int num_regs
= ARRAY_SIZE(armv4_5_core_reg_list_arch_info
);
395 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
396 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
397 struct armv4_5_core_reg
*arch_info
= calloc(num_regs
,
398 sizeof(struct armv4_5_core_reg
));
401 if (!cache
|| !reg_list
|| !arch_info
) {
408 cache
->name
= "ARM registers";
410 cache
->reg_list
= reg_list
;
413 for (i
= 0; i
< num_regs
; i
++)
415 /* Skip registers this core doesn't expose */
416 if (armv4_5_core_reg_list_arch_info
[i
].mode
== ARM_MODE_MON
417 && armv4_5_common
->core_type
!= ARM_MODE_MON
)
420 /* REVISIT handle Cortex-M, which only shadows R13/SP */
422 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
423 arch_info
[i
].target
= target
;
424 arch_info
[i
].armv4_5_common
= armv4_5_common
;
425 reg_list
[i
].name
= (char *) armv4_5_core_reg_list
[i
];
426 reg_list
[i
].size
= 32;
427 reg_list
[i
].value
= calloc(1, 4);
428 reg_list
[i
].type
= &arm_reg_type
;
429 reg_list
[i
].arch_info
= &arch_info
[i
];
437 int armv4_5_arch_state(struct target
*target
)
439 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
441 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
443 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
447 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
448 armv4_5_state_strings
[armv4_5
->core_state
],
449 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
450 arm_mode_name(armv4_5
->core_mode
),
451 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
452 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
457 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
458 cache->reg_list[armv4_5_core_reg_map[mode][num]]
460 COMMAND_HANDLER(handle_armv4_5_reg_command
)
465 struct target
*target
= get_current_target(CMD_CTX
);
466 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
468 if (!is_arm(armv4_5
))
470 command_print(CMD_CTX
, "current target isn't an ARM");
474 if (target
->state
!= TARGET_HALTED
)
476 command_print(CMD_CTX
, "error: target must be halted for register accesses");
480 if (!is_arm_mode(armv4_5
->core_mode
))
483 if (!armv4_5
->full_context
) {
484 command_print(CMD_CTX
, "error: target doesn't support %s",
489 for (num
= 0; num
<= 15; num
++)
492 for (mode
= 0; mode
< 6; mode
++)
494 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
496 armv4_5
->full_context(target
);
498 output_len
+= snprintf(output
+ output_len
,
500 "%8s: %8.8" PRIx32
" ",
501 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
502 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
504 command_print(CMD_CTX
, "%s", output
);
506 command_print(CMD_CTX
,
507 " cpsr: %8.8" PRIx32
" spsr_fiq: %8.8" PRIx32
" spsr_irq: %8.8" PRIx32
" spsr_svc: %8.8" PRIx32
" spsr_abt: %8.8" PRIx32
" spsr_und: %8.8" PRIx32
"",
508 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
509 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
510 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
511 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
512 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
513 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
518 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
520 struct target
*target
= get_current_target(CMD_CTX
);
521 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
523 if (!is_arm(armv4_5
))
525 command_print(CMD_CTX
, "current target isn't an ARM");
531 if (strcmp(CMD_ARGV
[0], "arm") == 0)
533 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
535 if (strcmp(CMD_ARGV
[0], "thumb") == 0)
537 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
541 command_print(CMD_CTX
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
546 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
548 int retval
= ERROR_OK
;
549 struct target
*target
= get_current_target(CMD_CTX
);
550 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
556 command_print(CMD_CTX
, "current target isn't an ARM");
562 if (strcmp(CMD_ARGV
[2], "thumb") != 0)
567 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], count
);
570 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
571 if (address
& 0x01) {
573 command_print(CMD_CTX
, "Disassemble as Thumb");
581 command_print(CMD_CTX
,
582 "usage: arm disassemble <address> [<count> ['thumb']]");
587 while (count
-- > 0) {
588 struct arm_instruction cur_instruction
;
591 /* Always use Thumb2 disassembly for best handling
592 * of 32-bit BL/BLX, and to work with newer cores
593 * (some ARMv6, all ARMv7) that use Thumb2.
595 retval
= thumb2_opcode(target
, address
,
597 if (retval
!= ERROR_OK
)
602 retval
= target_read_u32(target
, address
, &opcode
);
603 if (retval
!= ERROR_OK
)
605 retval
= arm_evaluate_opcode(opcode
, address
,
606 &cur_instruction
) != ERROR_OK
;
607 if (retval
!= ERROR_OK
)
610 command_print(CMD_CTX
, "%s", cur_instruction
.text
);
611 address
+= cur_instruction
.instruction_size
;
617 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
619 struct command
*armv4_5_cmd
;
621 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
623 "generic ARM commands");
625 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
626 handle_armv4_5_reg_command
, COMMAND_EXEC
,
627 "display ARM core registers");
628 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
629 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
630 "display/change ARM core state <arm | thumb>");
631 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
632 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
633 "disassemble instructions "
634 "<address> [<count> ['thumb']]");
639 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
641 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
644 if (!is_arm_mode(armv4_5
->core_mode
))
648 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
650 for (i
= 0; i
< 16; i
++)
652 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
655 for (i
= 16; i
< 24; i
++)
657 (*reg_list
)[i
] = &arm_gdb_dummy_fp_reg
;
660 (*reg_list
)[24] = &arm_gdb_dummy_fps_reg
;
661 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
666 /* wait for execution to complete and check exit point */
667 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
670 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
672 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
676 if (target
->state
!= TARGET_HALTED
)
678 if ((retval
= target_halt(target
)) != ERROR_OK
)
680 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
684 return ERROR_TARGET_TIMEOUT
;
687 /* fast exit: ARMv5+ code can use BKPT */
688 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
689 0, 32) != exit_point
)
691 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
692 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
693 return ERROR_TARGET_TIMEOUT
;
699 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
))
701 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
702 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
703 enum armv4_5_state core_state
= armv4_5
->core_state
;
704 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
705 uint32_t context
[17];
707 int exit_breakpoint_size
= 0;
709 int retval
= ERROR_OK
;
710 LOG_DEBUG("Running algorithm");
712 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
714 LOG_ERROR("current target isn't an ARMV4/5 target");
715 return ERROR_TARGET_INVALID
;
718 if (target
->state
!= TARGET_HALTED
)
720 LOG_WARNING("target not halted");
721 return ERROR_TARGET_NOT_HALTED
;
724 if (!is_arm_mode(armv4_5
->core_mode
))
727 /* armv5 and later can terminate with BKPT instruction; less overhead */
728 if (!exit_point
&& armv4_5
->is_armv4
)
730 LOG_ERROR("ARMv4 target needs HW breakpoint location");
734 for (i
= 0; i
<= 16; i
++)
736 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
737 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
738 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
740 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
742 for (i
= 0; i
< num_mem_params
; i
++)
744 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
750 for (i
= 0; i
< num_reg_params
; i
++)
752 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
755 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
756 return ERROR_INVALID_ARGUMENTS
;
759 if (reg
->size
!= reg_params
[i
].size
)
761 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
762 return ERROR_INVALID_ARGUMENTS
;
765 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
771 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
772 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
773 exit_breakpoint_size
= 4;
774 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
775 exit_breakpoint_size
= 2;
778 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
779 return ERROR_INVALID_ARGUMENTS
;
782 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
784 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
785 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
786 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
787 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
790 /* terminate using a hardware or (ARMv5+) software breakpoint */
791 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
792 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
794 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
795 return ERROR_TARGET_FAILURE
;
798 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
803 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
806 breakpoint_remove(target
, exit_point
);
808 if (retval
!= ERROR_OK
)
811 for (i
= 0; i
< num_mem_params
; i
++)
813 if (mem_params
[i
].direction
!= PARAM_OUT
)
814 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
820 for (i
= 0; i
< num_reg_params
; i
++)
822 if (reg_params
[i
].direction
!= PARAM_OUT
)
825 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
828 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
829 retval
= ERROR_INVALID_ARGUMENTS
;
833 if (reg
->size
!= reg_params
[i
].size
)
835 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
836 retval
= ERROR_INVALID_ARGUMENTS
;
840 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
844 for (i
= 0; i
<= 16; i
++)
847 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
848 if (regvalue
!= context
[i
])
850 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
]);
851 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
852 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
853 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
856 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
857 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
858 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
860 armv4_5
->core_state
= core_state
;
861 armv4_5
->core_mode
= core_mode
;
866 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
)
868 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
);
872 * Runs ARM code in the target to calculate a CRC32 checksum.
874 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
876 int arm_checksum_memory(struct target
*target
,
877 uint32_t address
, uint32_t count
, uint32_t *checksum
)
879 struct working_area
*crc_algorithm
;
880 struct armv4_5_algorithm armv4_5_info
;
881 struct reg_param reg_params
[2];
885 static const uint32_t arm_crc_code
[] = {
886 0xE1A02000, /* mov r2, r0 */
887 0xE3E00000, /* mov r0, #0xffffffff */
888 0xE1A03001, /* mov r3, r1 */
889 0xE3A04000, /* mov r4, #0 */
890 0xEA00000B, /* b ncomp */
892 0xE7D21004, /* ldrb r1, [r2, r4] */
893 0xE59F7030, /* ldr r7, CRC32XOR */
894 0xE0200C01, /* eor r0, r0, r1, asl 24 */
895 0xE3A05000, /* mov r5, #0 */
897 0xE3500000, /* cmp r0, #0 */
898 0xE1A06080, /* mov r6, r0, asl #1 */
899 0xE2855001, /* add r5, r5, #1 */
900 0xE1A00006, /* mov r0, r6 */
901 0xB0260007, /* eorlt r0, r6, r7 */
902 0xE3550008, /* cmp r5, #8 */
903 0x1AFFFFF8, /* bne loop */
904 0xE2844001, /* add r4, r4, #1 */
906 0xE1540003, /* cmp r4, r3 */
907 0x1AFFFFF1, /* bne nbyte */
909 0xEAFFFFFE, /* b end */
911 0x04C11DB7 /* .word 0x04C11DB7 */
914 retval
= target_alloc_working_area(target
,
915 sizeof(arm_crc_code
), &crc_algorithm
);
916 if (retval
!= ERROR_OK
)
919 /* convert code into a buffer in target endianness */
920 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
921 retval
= target_write_u32(target
,
922 crc_algorithm
->address
+ i
* sizeof(uint32_t),
924 if (retval
!= ERROR_OK
)
928 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
929 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
930 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
932 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
933 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
935 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
936 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
938 /* 20 second timeout/megabyte */
939 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
941 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
942 crc_algorithm
->address
,
943 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
944 timeout
, &armv4_5_info
);
945 if (retval
!= ERROR_OK
) {
946 LOG_ERROR("error executing ARM crc algorithm");
947 destroy_reg_param(®_params
[0]);
948 destroy_reg_param(®_params
[1]);
949 target_free_working_area(target
, crc_algorithm
);
953 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
955 destroy_reg_param(®_params
[0]);
956 destroy_reg_param(®_params
[1]);
958 target_free_working_area(target
, crc_algorithm
);
964 * Runs ARM code in the target to check whether a memory block holds
965 * all ones. NOR flash which has been erased, and thus may be written,
968 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
970 int arm_blank_check_memory(struct target
*target
,
971 uint32_t address
, uint32_t count
, uint32_t *blank
)
973 struct working_area
*check_algorithm
;
974 struct reg_param reg_params
[3];
975 struct armv4_5_algorithm armv4_5_info
;
979 static const uint32_t check_code
[] = {
981 0xe4d03001, /* ldrb r3, [r0], #1 */
982 0xe0022003, /* and r2, r2, r3 */
983 0xe2511001, /* subs r1, r1, #1 */
984 0x1afffffb, /* bne loop */
986 0xeafffffe /* b end */
989 /* make sure we have a working area */
990 retval
= target_alloc_working_area(target
,
991 sizeof(check_code
), &check_algorithm
);
992 if (retval
!= ERROR_OK
)
995 /* convert code into a buffer in target endianness */
996 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
997 retval
= target_write_u32(target
,
998 check_algorithm
->address
999 + i
* sizeof(uint32_t),
1001 if (retval
!= ERROR_OK
)
1005 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1006 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1007 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1009 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1010 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1012 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1013 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1015 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1016 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1018 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1019 check_algorithm
->address
,
1020 check_algorithm
->address
+ sizeof(check_code
) - 4,
1021 10000, &armv4_5_info
);
1022 if (retval
!= ERROR_OK
) {
1023 destroy_reg_param(®_params
[0]);
1024 destroy_reg_param(®_params
[1]);
1025 destroy_reg_param(®_params
[2]);
1026 target_free_working_area(target
, check_algorithm
);
1030 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
1032 destroy_reg_param(®_params
[0]);
1033 destroy_reg_param(®_params
[1]);
1034 destroy_reg_param(®_params
[2]);
1036 target_free_working_area(target
, check_algorithm
);
1041 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
1043 target
->arch_info
= armv4_5
;
1045 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
1046 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
1047 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
1049 /* core_type may be overridden by subtype logic */
1050 armv4_5
->core_type
= ARMV4_5_MODE_ANY
;
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)