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", "sp_usr", "lr_usr", "pc",
44 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "sp_fiq", "lr_fiq",
54 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
56 "sp_mon", "lr_mon", "spsr_mon",
59 static const uint8_t arm_usr_indices
[17] = {
60 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ARMV4_5_CPSR
,
63 static const uint8_t arm_fiq_indices
[8] = {
64 16, 17, 18, 19, 20, 21, 22, ARMV4_5_SPSR_FIQ
,
67 static const uint8_t arm_irq_indices
[3] = {
68 23, 24, ARMV4_5_SPSR_IRQ
,
71 static const uint8_t arm_svc_indices
[3] = {
72 25, 26, ARMV4_5_SPSR_SVC
,
75 static const uint8_t arm_abt_indices
[3] = {
76 27, 28, ARMV4_5_SPSR_ABT
,
79 static const uint8_t arm_und_indices
[3] = {
80 29, 30, ARMV4_5_SPSR_UND
,
83 static const uint8_t arm_mon_indices
[3] = {
90 /* For user and system modes, these list indices for all registers.
91 * otherwise they're just indices for the shadow registers and SPSR.
93 unsigned short n_indices
;
94 const uint8_t *indices
;
96 /* Seven modes are standard from ARM7 on. "System" and "User" share
97 * the same registers; other modes shadow from 3 to 8 registers.
101 .psr
= ARMV4_5_MODE_USR
,
102 .n_indices
= ARRAY_SIZE(arm_usr_indices
),
103 .indices
= arm_usr_indices
,
107 .psr
= ARMV4_5_MODE_FIQ
,
108 .n_indices
= ARRAY_SIZE(arm_fiq_indices
),
109 .indices
= arm_fiq_indices
,
112 .name
= "Supervisor",
113 .psr
= ARMV4_5_MODE_SVC
,
114 .n_indices
= ARRAY_SIZE(arm_svc_indices
),
115 .indices
= arm_svc_indices
,
119 .psr
= ARMV4_5_MODE_ABT
,
120 .n_indices
= ARRAY_SIZE(arm_abt_indices
),
121 .indices
= arm_abt_indices
,
125 .psr
= ARMV4_5_MODE_IRQ
,
126 .n_indices
= ARRAY_SIZE(arm_irq_indices
),
127 .indices
= arm_irq_indices
,
130 .name
= "Undefined instruction",
131 .psr
= ARMV4_5_MODE_UND
,
132 .n_indices
= ARRAY_SIZE(arm_und_indices
),
133 .indices
= arm_und_indices
,
137 .psr
= ARMV4_5_MODE_SYS
,
138 .n_indices
= ARRAY_SIZE(arm_usr_indices
),
139 .indices
= arm_usr_indices
,
141 /* TrustZone "Security Extensions" add a secure monitor mode.
142 * This is distinct from a "debug monitor" which can support
143 * non-halting debug, in conjunction with some debuggers.
146 .name
= "Secure Monitor",
148 .n_indices
= ARRAY_SIZE(arm_mon_indices
),
149 .indices
= arm_mon_indices
,
153 /** Map PSR mode bits to the name of an ARM processor operating mode. */
154 const char *arm_mode_name(unsigned psr_mode
)
156 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
157 if (arm_mode_data
[i
].psr
== psr_mode
)
158 return arm_mode_data
[i
].name
;
160 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
161 return "UNRECOGNIZED";
164 /** Return true iff the parameter denotes a valid ARM processor mode. */
165 bool is_arm_mode(unsigned psr_mode
)
167 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
168 if (arm_mode_data
[i
].psr
== psr_mode
)
174 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
175 int armv4_5_mode_to_number(enum armv4_5_mode mode
)
178 case ARMV4_5_MODE_ANY
:
179 /* map MODE_ANY to user mode */
180 case ARMV4_5_MODE_USR
:
182 case ARMV4_5_MODE_FIQ
:
184 case ARMV4_5_MODE_IRQ
:
186 case ARMV4_5_MODE_SVC
:
188 case ARMV4_5_MODE_ABT
:
190 case ARMV4_5_MODE_UND
:
192 case ARMV4_5_MODE_SYS
:
197 LOG_ERROR("invalid mode value encountered %d", mode
);
202 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
203 enum armv4_5_mode
armv4_5_number_to_mode(int number
)
207 return ARMV4_5_MODE_USR
;
209 return ARMV4_5_MODE_FIQ
;
211 return ARMV4_5_MODE_IRQ
;
213 return ARMV4_5_MODE_SVC
;
215 return ARMV4_5_MODE_ABT
;
217 return ARMV4_5_MODE_UND
;
219 return ARMV4_5_MODE_SYS
;
223 LOG_ERROR("mode index out of bounds %d", number
);
224 return ARMV4_5_MODE_ANY
;
228 char* armv4_5_state_strings
[] =
230 "ARM", "Thumb", "Jazelle"
233 static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
235 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
236 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
237 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
238 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
239 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
240 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
241 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
242 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
243 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
244 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
245 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
246 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
247 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
248 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
249 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
250 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
252 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
253 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
254 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
255 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
256 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
257 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
258 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
260 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
261 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
263 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
264 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
266 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
267 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
269 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
270 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
272 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
273 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
274 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
275 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
276 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
277 {16, ARMV4_5_MODE_UND
, NULL
, NULL
},
279 {13, ARM_MODE_MON
, NULL
, NULL
},
280 {14, ARM_MODE_MON
, NULL
, NULL
},
281 {16, ARM_MODE_MON
, NULL
, NULL
},
284 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
285 const int armv4_5_core_reg_map
[8][17] =
288 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
290 { /* FIQ (8 shadows of USR, vs normal 3) */
291 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
294 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
297 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
300 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
303 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
305 { /* SYS (same registers as USR) */
306 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
309 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
313 static const uint8_t arm_gdb_dummy_fp_value
[12];
316 * Dummy FPA registers are required to support GDB on ARM.
317 * Register packets require eight obsolete FPA register values.
318 * Modern ARM cores use Vector Floating Point (VFP), if they
319 * have any floating point support. VFP is not FPA-compatible.
321 struct reg arm_gdb_dummy_fp_reg
=
323 .name
= "GDB dummy FPA register",
324 .value
= (uint8_t *) arm_gdb_dummy_fp_value
,
329 static const uint8_t arm_gdb_dummy_fps_value
[4];
332 * Dummy FPA status registers are required to support GDB on ARM.
333 * Register packets require an obsolete FPA status register.
335 struct reg arm_gdb_dummy_fps_reg
=
337 .name
= "GDB dummy FPA status register",
338 .value
= (uint8_t *) arm_gdb_dummy_fps_value
,
343 static void arm_gdb_dummy_init(void) __attribute__ ((constructor
));
345 static void arm_gdb_dummy_init(void)
347 register_init_dummy(&arm_gdb_dummy_fp_reg
);
348 register_init_dummy(&arm_gdb_dummy_fps_reg
);
351 static int armv4_5_get_core_reg(struct reg
*reg
)
354 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
355 struct target
*target
= armv4_5
->target
;
357 if (target
->state
!= TARGET_HALTED
)
359 LOG_ERROR("Target not halted");
360 return ERROR_TARGET_NOT_HALTED
;
363 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
364 if (retval
== ERROR_OK
)
370 static int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
372 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
373 struct target
*target
= armv4_5
->target
;
374 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
375 uint32_t value
= buf_get_u32(buf
, 0, 32);
377 if (target
->state
!= TARGET_HALTED
)
379 LOG_ERROR("Target not halted");
380 return ERROR_TARGET_NOT_HALTED
;
383 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
387 /* T bit should be set */
388 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
390 /* change state to Thumb */
391 LOG_DEBUG("changing to Thumb state");
392 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
397 /* T bit should be cleared */
398 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
400 /* change state to ARM */
401 LOG_DEBUG("changing to ARM state");
402 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
406 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
408 LOG_DEBUG("changing ARM core mode to '%s'",
409 arm_mode_name(value
& 0x1f));
410 armv4_5_target
->core_mode
= value
& 0x1f;
411 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
415 buf_set_u32(reg
->value
, 0, 32, value
);
422 static const struct reg_arch_type arm_reg_type
= {
423 .get
= armv4_5_get_core_reg
,
424 .set
= armv4_5_set_core_reg
,
427 /** Marks the contents of the register cache as invalid (and clean). */
428 int armv4_5_invalidate_core_regs(struct target
*target
)
430 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
431 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
432 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
434 for (unsigned i
= 0; i
< num_regs
; i
++, reg
++) {
439 /* FIXME don't bother returning a value then */
443 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
445 int num_regs
= ARRAY_SIZE(armv4_5_core_reg_list_arch_info
);
446 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
447 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
448 struct armv4_5_core_reg
*arch_info
= calloc(num_regs
,
449 sizeof(struct armv4_5_core_reg
));
452 if (!cache
|| !reg_list
|| !arch_info
) {
459 cache
->name
= "ARM registers";
461 cache
->reg_list
= reg_list
;
464 for (i
= 0; i
< num_regs
; i
++)
466 /* Skip registers this core doesn't expose */
467 if (armv4_5_core_reg_list_arch_info
[i
].mode
== ARM_MODE_MON
468 && armv4_5_common
->core_type
!= ARM_MODE_MON
)
471 /* REVISIT handle Cortex-M, which only shadows R13/SP */
473 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
474 arch_info
[i
].target
= target
;
475 arch_info
[i
].armv4_5_common
= armv4_5_common
;
476 reg_list
[i
].name
= (char *) armv4_5_core_reg_list
[i
];
477 reg_list
[i
].size
= 32;
478 reg_list
[i
].value
= calloc(1, 4);
479 reg_list
[i
].type
= &arm_reg_type
;
480 reg_list
[i
].arch_info
= &arch_info
[i
];
488 int armv4_5_arch_state(struct target
*target
)
490 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
492 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
494 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
498 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
499 armv4_5_state_strings
[armv4_5
->core_state
],
500 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
501 arm_mode_name(armv4_5
->core_mode
),
502 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
503 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
508 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
509 cache->reg_list[armv4_5_core_reg_map[mode][num]]
511 COMMAND_HANDLER(handle_armv4_5_reg_command
)
513 struct target
*target
= get_current_target(CMD_CTX
);
514 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
518 if (!is_arm(armv4_5
))
520 command_print(CMD_CTX
, "current target isn't an ARM");
524 if (target
->state
!= TARGET_HALTED
)
526 command_print(CMD_CTX
, "error: target must be halted for register accesses");
530 if (!is_arm_mode(armv4_5
->core_mode
))
533 if (!armv4_5
->full_context
) {
534 command_print(CMD_CTX
, "error: target doesn't support %s",
539 num_regs
= armv4_5
->core_cache
->num_regs
;
540 regs
= armv4_5
->core_cache
->reg_list
;
542 for (unsigned mode
= 0; mode
< ARRAY_SIZE(arm_mode_data
); mode
++) {
547 /* label this bank of registers (or shadows) */
548 switch (arm_mode_data
[mode
].psr
) {
549 case ARMV4_5_MODE_SYS
:
551 case ARMV4_5_MODE_USR
:
552 name
= "System and User";
556 if (armv4_5
->core_type
!= ARM_MODE_MON
)
560 name
= arm_mode_data
[mode
].name
;
564 command_print(CMD_CTX
, "%s%s mode %sregisters",
567 /* display N rows of up to 4 registers each */
568 for (unsigned i
= 0; i
< arm_mode_data
[mode
].n_indices
;) {
572 for (unsigned j
= 0; j
< 4; j
++, i
++) {
574 struct reg
*reg
= regs
;
576 if (i
>= arm_mode_data
[mode
].n_indices
)
579 reg
+= arm_mode_data
[mode
].indices
[i
];
581 /* REVISIT be smarter about faults... */
583 armv4_5
->full_context(target
);
585 value
= buf_get_u32(reg
->value
, 0, 32);
586 output_len
+= snprintf(output
+ output_len
,
587 sizeof(output
) - output_len
,
588 "%8s: %8.8" PRIx32
" ",
591 command_print(CMD_CTX
, "%s", output
);
598 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
600 struct target
*target
= get_current_target(CMD_CTX
);
601 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
603 if (!is_arm(armv4_5
))
605 command_print(CMD_CTX
, "current target isn't an ARM");
611 if (strcmp(CMD_ARGV
[0], "arm") == 0)
613 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
615 if (strcmp(CMD_ARGV
[0], "thumb") == 0)
617 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
621 command_print(CMD_CTX
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
626 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
628 int retval
= ERROR_OK
;
629 struct target
*target
= get_current_target(CMD_CTX
);
630 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
636 command_print(CMD_CTX
, "current target isn't an ARM");
642 if (strcmp(CMD_ARGV
[2], "thumb") != 0)
647 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], count
);
650 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
651 if (address
& 0x01) {
653 command_print(CMD_CTX
, "Disassemble as Thumb");
661 command_print(CMD_CTX
,
662 "usage: arm disassemble <address> [<count> ['thumb']]");
667 while (count
-- > 0) {
668 struct arm_instruction cur_instruction
;
671 /* Always use Thumb2 disassembly for best handling
672 * of 32-bit BL/BLX, and to work with newer cores
673 * (some ARMv6, all ARMv7) that use Thumb2.
675 retval
= thumb2_opcode(target
, address
,
677 if (retval
!= ERROR_OK
)
682 retval
= target_read_u32(target
, address
, &opcode
);
683 if (retval
!= ERROR_OK
)
685 retval
= arm_evaluate_opcode(opcode
, address
,
686 &cur_instruction
) != ERROR_OK
;
687 if (retval
!= ERROR_OK
)
690 command_print(CMD_CTX
, "%s", cur_instruction
.text
);
691 address
+= cur_instruction
.instruction_size
;
697 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
699 struct command
*armv4_5_cmd
;
701 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
703 "generic ARM commands");
705 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
706 handle_armv4_5_reg_command
, COMMAND_EXEC
,
707 "display ARM core registers");
708 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
709 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
710 "display/change ARM core state <arm | thumb>");
711 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
712 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
713 "disassemble instructions "
714 "<address> [<count> ['thumb']]");
719 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
721 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
724 if (!is_arm_mode(armv4_5
->core_mode
))
728 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
730 for (i
= 0; i
< 16; i
++)
732 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
735 for (i
= 16; i
< 24; i
++)
737 (*reg_list
)[i
] = &arm_gdb_dummy_fp_reg
;
740 (*reg_list
)[24] = &arm_gdb_dummy_fps_reg
;
741 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
746 /* wait for execution to complete and check exit point */
747 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
750 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
752 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
756 if (target
->state
!= TARGET_HALTED
)
758 if ((retval
= target_halt(target
)) != ERROR_OK
)
760 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
764 return ERROR_TARGET_TIMEOUT
;
767 /* fast exit: ARMv5+ code can use BKPT */
768 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
769 0, 32) != exit_point
)
771 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
772 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
773 return ERROR_TARGET_TIMEOUT
;
779 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
))
781 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
782 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
783 enum armv4_5_state core_state
= armv4_5
->core_state
;
784 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
785 uint32_t context
[17];
787 int exit_breakpoint_size
= 0;
789 int retval
= ERROR_OK
;
790 LOG_DEBUG("Running algorithm");
792 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
794 LOG_ERROR("current target isn't an ARMV4/5 target");
795 return ERROR_TARGET_INVALID
;
798 if (target
->state
!= TARGET_HALTED
)
800 LOG_WARNING("target not halted");
801 return ERROR_TARGET_NOT_HALTED
;
804 if (!is_arm_mode(armv4_5
->core_mode
))
807 /* armv5 and later can terminate with BKPT instruction; less overhead */
808 if (!exit_point
&& armv4_5
->is_armv4
)
810 LOG_ERROR("ARMv4 target needs HW breakpoint location");
814 for (i
= 0; i
<= 16; i
++)
816 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
817 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
818 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
820 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
822 for (i
= 0; i
< num_mem_params
; i
++)
824 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
830 for (i
= 0; i
< num_reg_params
; i
++)
832 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
835 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
836 return ERROR_INVALID_ARGUMENTS
;
839 if (reg
->size
!= reg_params
[i
].size
)
841 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
842 return ERROR_INVALID_ARGUMENTS
;
845 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
851 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
852 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
853 exit_breakpoint_size
= 4;
854 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
855 exit_breakpoint_size
= 2;
858 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
859 return ERROR_INVALID_ARGUMENTS
;
862 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
864 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
865 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
866 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
867 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
870 /* terminate using a hardware or (ARMv5+) software breakpoint */
871 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
872 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
874 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
875 return ERROR_TARGET_FAILURE
;
878 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
883 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
886 breakpoint_remove(target
, exit_point
);
888 if (retval
!= ERROR_OK
)
891 for (i
= 0; i
< num_mem_params
; i
++)
893 if (mem_params
[i
].direction
!= PARAM_OUT
)
894 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
900 for (i
= 0; i
< num_reg_params
; i
++)
902 if (reg_params
[i
].direction
!= PARAM_OUT
)
905 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
908 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
909 retval
= ERROR_INVALID_ARGUMENTS
;
913 if (reg
->size
!= reg_params
[i
].size
)
915 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
916 retval
= ERROR_INVALID_ARGUMENTS
;
920 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
924 for (i
= 0; i
<= 16; i
++)
927 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
928 if (regvalue
!= context
[i
])
930 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
]);
931 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
932 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
933 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
936 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
937 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
938 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
940 armv4_5
->core_state
= core_state
;
941 armv4_5
->core_mode
= core_mode
;
946 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
)
948 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
);
952 * Runs ARM code in the target to calculate a CRC32 checksum.
954 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
956 int arm_checksum_memory(struct target
*target
,
957 uint32_t address
, uint32_t count
, uint32_t *checksum
)
959 struct working_area
*crc_algorithm
;
960 struct armv4_5_algorithm armv4_5_info
;
961 struct reg_param reg_params
[2];
965 static const uint32_t arm_crc_code
[] = {
966 0xE1A02000, /* mov r2, r0 */
967 0xE3E00000, /* mov r0, #0xffffffff */
968 0xE1A03001, /* mov r3, r1 */
969 0xE3A04000, /* mov r4, #0 */
970 0xEA00000B, /* b ncomp */
972 0xE7D21004, /* ldrb r1, [r2, r4] */
973 0xE59F7030, /* ldr r7, CRC32XOR */
974 0xE0200C01, /* eor r0, r0, r1, asl 24 */
975 0xE3A05000, /* mov r5, #0 */
977 0xE3500000, /* cmp r0, #0 */
978 0xE1A06080, /* mov r6, r0, asl #1 */
979 0xE2855001, /* add r5, r5, #1 */
980 0xE1A00006, /* mov r0, r6 */
981 0xB0260007, /* eorlt r0, r6, r7 */
982 0xE3550008, /* cmp r5, #8 */
983 0x1AFFFFF8, /* bne loop */
984 0xE2844001, /* add r4, r4, #1 */
986 0xE1540003, /* cmp r4, r3 */
987 0x1AFFFFF1, /* bne nbyte */
989 0xEAFFFFFE, /* b end */
991 0x04C11DB7 /* .word 0x04C11DB7 */
994 retval
= target_alloc_working_area(target
,
995 sizeof(arm_crc_code
), &crc_algorithm
);
996 if (retval
!= ERROR_OK
)
999 /* convert code into a buffer in target endianness */
1000 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
1001 retval
= target_write_u32(target
,
1002 crc_algorithm
->address
+ i
* sizeof(uint32_t),
1004 if (retval
!= ERROR_OK
)
1008 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1009 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1010 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1012 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
1013 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1015 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1016 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1018 /* 20 second timeout/megabyte */
1019 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
1021 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
1022 crc_algorithm
->address
,
1023 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
1024 timeout
, &armv4_5_info
);
1025 if (retval
!= ERROR_OK
) {
1026 LOG_ERROR("error executing ARM crc algorithm");
1027 destroy_reg_param(®_params
[0]);
1028 destroy_reg_param(®_params
[1]);
1029 target_free_working_area(target
, crc_algorithm
);
1033 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
1035 destroy_reg_param(®_params
[0]);
1036 destroy_reg_param(®_params
[1]);
1038 target_free_working_area(target
, crc_algorithm
);
1044 * Runs ARM code in the target to check whether a memory block holds
1045 * all ones. NOR flash which has been erased, and thus may be written,
1048 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
1050 int arm_blank_check_memory(struct target
*target
,
1051 uint32_t address
, uint32_t count
, uint32_t *blank
)
1053 struct working_area
*check_algorithm
;
1054 struct reg_param reg_params
[3];
1055 struct armv4_5_algorithm armv4_5_info
;
1059 static const uint32_t check_code
[] = {
1061 0xe4d03001, /* ldrb r3, [r0], #1 */
1062 0xe0022003, /* and r2, r2, r3 */
1063 0xe2511001, /* subs r1, r1, #1 */
1064 0x1afffffb, /* bne loop */
1066 0xeafffffe /* b end */
1069 /* make sure we have a working area */
1070 retval
= target_alloc_working_area(target
,
1071 sizeof(check_code
), &check_algorithm
);
1072 if (retval
!= ERROR_OK
)
1075 /* convert code into a buffer in target endianness */
1076 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
1077 retval
= target_write_u32(target
,
1078 check_algorithm
->address
1079 + i
* sizeof(uint32_t),
1081 if (retval
!= ERROR_OK
)
1085 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1086 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1087 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1089 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1090 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1092 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1093 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1095 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1096 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1098 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1099 check_algorithm
->address
,
1100 check_algorithm
->address
+ sizeof(check_code
) - 4,
1101 10000, &armv4_5_info
);
1102 if (retval
!= ERROR_OK
) {
1103 destroy_reg_param(®_params
[0]);
1104 destroy_reg_param(®_params
[1]);
1105 destroy_reg_param(®_params
[2]);
1106 target_free_working_area(target
, check_algorithm
);
1110 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
1112 destroy_reg_param(®_params
[0]);
1113 destroy_reg_param(®_params
[1]);
1114 destroy_reg_param(®_params
[2]);
1116 target_free_working_area(target
, check_algorithm
);
1121 static int arm_full_context(struct target
*target
)
1123 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
1124 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
1125 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
1126 int retval
= ERROR_OK
;
1128 for (; num_regs
&& retval
== ERROR_OK
; num_regs
--, reg
++) {
1131 retval
= armv4_5_get_core_reg(reg
);
1136 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
1138 target
->arch_info
= armv4_5
;
1140 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
1141 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
1142 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
1144 /* core_type may be overridden by subtype logic */
1145 armv4_5
->core_type
= ARMV4_5_MODE_ANY
;
1147 /* default full_context() has no core-specific optimizations */
1148 if (!armv4_5
->full_context
&& armv4_5
->read_core_reg
)
1149 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)