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 ***************************************************************************/
31 #include "breakpoints.h"
32 #include "arm_disassembler.h"
33 #include "binarybuffer.h"
36 char* armv4_5_core_reg_list
[] =
38 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
40 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
50 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
53 char * armv4_5_mode_strings_list
[] =
55 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
58 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
59 char** armv4_5_mode_strings
= armv4_5_mode_strings_list
+ 1;
61 char* armv4_5_state_strings
[] =
63 "ARM", "Thumb", "Jazelle"
66 int armv4_5_core_reg_arch_type
= -1;
68 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
70 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
71 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
72 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
73 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
74 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
75 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
76 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
77 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
78 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
79 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
80 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
81 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
82 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
83 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
84 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
85 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
87 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
88 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
89 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
90 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
91 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
92 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
93 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
95 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
96 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
98 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
99 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
101 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
102 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
104 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
105 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
107 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
108 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
109 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
110 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
111 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
112 {16, ARMV4_5_MODE_UND
, NULL
, NULL
}
115 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
116 int armv4_5_core_reg_map
[7][17] =
119 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
122 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
128 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
131 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
141 uint8_t armv4_5_gdb_dummy_fp_value
[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
143 struct reg armv4_5_gdb_dummy_fp_reg
=
145 .name
= "GDB dummy floating-point register",
146 .value
= armv4_5_gdb_dummy_fp_value
,
154 uint8_t armv4_5_gdb_dummy_fps_value
[] = {0, 0, 0, 0};
156 struct reg armv4_5_gdb_dummy_fps_reg
=
158 .name
= "GDB dummy floating-point status register",
159 .value
= armv4_5_gdb_dummy_fps_value
,
167 int armv4_5_get_core_reg(struct reg
*reg
)
170 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
171 struct target
*target
= armv4_5
->target
;
173 if (target
->state
!= TARGET_HALTED
)
175 LOG_ERROR("Target not halted");
176 return ERROR_TARGET_NOT_HALTED
;
179 /* retval = armv4_5->armv4_5_common->full_context(target); */
180 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
185 int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
187 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
188 struct target
*target
= armv4_5
->target
;
189 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
190 uint32_t value
= buf_get_u32(buf
, 0, 32);
192 if (target
->state
!= TARGET_HALTED
)
194 return ERROR_TARGET_NOT_HALTED
;
197 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
201 /* T bit should be set */
202 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
204 /* change state to Thumb */
205 LOG_DEBUG("changing to Thumb state");
206 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
211 /* T bit should be cleared */
212 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
214 /* change state to ARM */
215 LOG_DEBUG("changing to ARM state");
216 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
220 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
222 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings
[armv4_5_mode_to_number(value
& 0x1f)]);
223 armv4_5_target
->core_mode
= value
& 0x1f;
224 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
228 buf_set_u32(reg
->value
, 0, 32, value
);
235 int armv4_5_invalidate_core_regs(struct target
*target
)
237 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
240 for (i
= 0; i
< 37; i
++)
242 armv4_5
->core_cache
->reg_list
[i
].valid
= 0;
243 armv4_5
->core_cache
->reg_list
[i
].dirty
= 0;
249 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
252 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
253 struct reg
*reg_list
= malloc(sizeof(struct reg
) * num_regs
);
254 struct armv4_5_core_reg
*arch_info
= malloc(sizeof(struct armv4_5_core_reg
) * num_regs
);
257 cache
->name
= "arm v4/5 registers";
259 cache
->reg_list
= reg_list
;
260 cache
->num_regs
= num_regs
;
262 if (armv4_5_core_reg_arch_type
== -1)
263 armv4_5_core_reg_arch_type
= register_reg_arch_type(armv4_5_get_core_reg
, armv4_5_set_core_reg
);
265 register_init_dummy(&armv4_5_gdb_dummy_fp_reg
);
266 register_init_dummy(&armv4_5_gdb_dummy_fps_reg
);
268 for (i
= 0; i
< 37; i
++)
270 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
271 arch_info
[i
].target
= target
;
272 arch_info
[i
].armv4_5_common
= armv4_5_common
;
273 reg_list
[i
].name
= armv4_5_core_reg_list
[i
];
274 reg_list
[i
].size
= 32;
275 reg_list
[i
].value
= calloc(1, 4);
276 reg_list
[i
].dirty
= 0;
277 reg_list
[i
].valid
= 0;
278 reg_list
[i
].arch_type
= armv4_5_core_reg_arch_type
;
279 reg_list
[i
].arch_info
= &arch_info
[i
];
285 int armv4_5_arch_state(struct target
*target
)
287 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
289 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
291 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
295 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
296 armv4_5_state_strings
[armv4_5
->core_state
],
297 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
298 armv4_5_mode_strings
[armv4_5_mode_to_number(armv4_5
->core_mode
)],
299 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
300 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
305 COMMAND_HANDLER(handle_armv4_5_reg_command
)
310 struct target
*target
= get_current_target(cmd_ctx
);
311 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
313 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
315 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
319 if (target
->state
!= TARGET_HALTED
)
321 command_print(cmd_ctx
, "error: target must be halted for register accesses");
325 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
328 for (num
= 0; num
<= 15; num
++)
331 for (mode
= 0; mode
< 6; mode
++)
333 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
335 armv4_5
->full_context(target
);
337 output_len
+= snprintf(output
+ output_len
,
339 "%8s: %8.8" PRIx32
" ",
340 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
341 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
343 command_print(cmd_ctx
, "%s", output
);
345 command_print(cmd_ctx
,
346 " 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
"",
347 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
348 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
349 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
350 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
351 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
352 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
357 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
359 struct target
*target
= get_current_target(cmd_ctx
);
360 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
362 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
364 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
370 if (strcmp(args
[0], "arm") == 0)
372 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
374 if (strcmp(args
[0], "thumb") == 0)
376 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
380 command_print(cmd_ctx
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
385 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
387 int retval
= ERROR_OK
;
388 struct target
*target
= get_current_target(cmd_ctx
);
389 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
393 struct arm_instruction cur_instruction
;
395 uint16_t thumb_opcode
;
398 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
400 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
406 if (strcmp(args
[2], "thumb") != 0)
411 COMMAND_PARSE_NUMBER(int, args
[1], count
);
414 COMMAND_PARSE_NUMBER(u32
, args
[0], address
);
415 if (address
& 0x01) {
417 command_print(cmd_ctx
, "Disassemble as Thumb");
425 command_print(cmd_ctx
,
426 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
430 for (i
= 0; i
< count
; i
++)
434 if ((retval
= target_read_u16(target
, address
, &thumb_opcode
)) != ERROR_OK
)
438 if ((retval
= thumb_evaluate_opcode(thumb_opcode
, address
, &cur_instruction
)) != ERROR_OK
)
444 if ((retval
= target_read_u32(target
, address
, &opcode
)) != ERROR_OK
)
448 if ((retval
= arm_evaluate_opcode(opcode
, address
, &cur_instruction
)) != ERROR_OK
)
453 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
454 address
+= (thumb
) ? 2 : 4;
460 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
462 struct command
*armv4_5_cmd
;
464 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "armv4_5",
466 "armv4/5 specific commands");
468 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
469 handle_armv4_5_reg_command
, COMMAND_EXEC
,
470 "display ARM core registers");
471 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
472 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
473 "display/change ARM core state <arm | thumb>");
474 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
475 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
476 "disassemble instructions <address> [<count> ['thumb']]");
481 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
483 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
486 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
490 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
492 for (i
= 0; i
< 16; i
++)
494 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
497 for (i
= 16; i
< 24; i
++)
499 (*reg_list
)[i
] = &armv4_5_gdb_dummy_fp_reg
;
502 (*reg_list
)[24] = &armv4_5_gdb_dummy_fps_reg
;
503 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
508 /* wait for execution to complete and check exit point */
509 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
512 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
514 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
518 if (target
->state
!= TARGET_HALTED
)
520 if ((retval
= target_halt(target
)) != ERROR_OK
)
522 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
526 return ERROR_TARGET_TIMEOUT
;
529 /* fast exit: ARMv5+ code can use BKPT */
530 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
531 0, 32) != exit_point
)
533 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
534 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
535 return ERROR_TARGET_TIMEOUT
;
541 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
))
543 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
544 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
545 enum armv4_5_state core_state
= armv4_5
->core_state
;
546 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
547 uint32_t context
[17];
549 int exit_breakpoint_size
= 0;
551 int retval
= ERROR_OK
;
552 LOG_DEBUG("Running algorithm");
554 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
556 LOG_ERROR("current target isn't an ARMV4/5 target");
557 return ERROR_TARGET_INVALID
;
560 if (target
->state
!= TARGET_HALTED
)
562 LOG_WARNING("target not halted");
563 return ERROR_TARGET_NOT_HALTED
;
566 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
569 /* armv5 and later can terminate with BKPT instruction; less overhead */
570 if (!exit_point
&& armv4_5
->is_armv4
)
572 LOG_ERROR("ARMv4 target needs HW breakpoint location");
576 for (i
= 0; i
<= 16; i
++)
578 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
579 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
580 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
582 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
584 for (i
= 0; i
< num_mem_params
; i
++)
586 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
592 for (i
= 0; i
< num_reg_params
; i
++)
594 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
597 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
601 if (reg
->size
!= reg_params
[i
].size
)
603 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
607 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
613 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
614 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
615 exit_breakpoint_size
= 4;
616 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
617 exit_breakpoint_size
= 2;
620 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
624 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
626 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
627 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
628 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
629 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
632 /* terminate using a hardware or (ARMv5+) software breakpoint */
633 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
634 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
636 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
637 return ERROR_TARGET_FAILURE
;
640 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
645 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
648 breakpoint_remove(target
, exit_point
);
650 if (retval
!= ERROR_OK
)
653 for (i
= 0; i
< num_mem_params
; i
++)
655 if (mem_params
[i
].direction
!= PARAM_OUT
)
656 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
662 for (i
= 0; i
< num_reg_params
; i
++)
664 if (reg_params
[i
].direction
!= PARAM_OUT
)
667 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
670 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
674 if (reg
->size
!= reg_params
[i
].size
)
676 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
680 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
684 for (i
= 0; i
<= 16; i
++)
687 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
688 if (regvalue
!= context
[i
])
690 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
]);
691 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
692 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
693 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
696 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
697 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
698 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
700 armv4_5
->core_state
= core_state
;
701 armv4_5
->core_mode
= core_mode
;
706 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
)
708 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
);
712 * Runs ARM code in the target to calculate a CRC32 checksum.
714 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
716 int arm_checksum_memory(struct target
*target
,
717 uint32_t address
, uint32_t count
, uint32_t *checksum
)
719 struct working_area
*crc_algorithm
;
720 struct armv4_5_algorithm armv4_5_info
;
721 struct reg_param reg_params
[2];
725 static const uint32_t arm_crc_code
[] = {
726 0xE1A02000, /* mov r2, r0 */
727 0xE3E00000, /* mov r0, #0xffffffff */
728 0xE1A03001, /* mov r3, r1 */
729 0xE3A04000, /* mov r4, #0 */
730 0xEA00000B, /* b ncomp */
732 0xE7D21004, /* ldrb r1, [r2, r4] */
733 0xE59F7030, /* ldr r7, CRC32XOR */
734 0xE0200C01, /* eor r0, r0, r1, asl 24 */
735 0xE3A05000, /* mov r5, #0 */
737 0xE3500000, /* cmp r0, #0 */
738 0xE1A06080, /* mov r6, r0, asl #1 */
739 0xE2855001, /* add r5, r5, #1 */
740 0xE1A00006, /* mov r0, r6 */
741 0xB0260007, /* eorlt r0, r6, r7 */
742 0xE3550008, /* cmp r5, #8 */
743 0x1AFFFFF8, /* bne loop */
744 0xE2844001, /* add r4, r4, #1 */
746 0xE1540003, /* cmp r4, r3 */
747 0x1AFFFFF1, /* bne nbyte */
749 0xEAFFFFFE, /* b end */
751 0x04C11DB7 /* .word 0x04C11DB7 */
754 retval
= target_alloc_working_area(target
,
755 sizeof(arm_crc_code
), &crc_algorithm
);
756 if (retval
!= ERROR_OK
)
759 /* convert code into a buffer in target endianness */
760 for (i
= 0; i
< DIM(arm_crc_code
); i
++) {
761 retval
= target_write_u32(target
,
762 crc_algorithm
->address
+ i
* sizeof(uint32_t),
764 if (retval
!= ERROR_OK
)
768 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
769 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
770 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
772 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
773 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
775 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
776 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
778 /* 20 second timeout/megabyte */
779 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
781 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
782 crc_algorithm
->address
,
783 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
784 timeout
, &armv4_5_info
);
785 if (retval
!= ERROR_OK
) {
786 LOG_ERROR("error executing ARM crc algorithm");
787 destroy_reg_param(®_params
[0]);
788 destroy_reg_param(®_params
[1]);
789 target_free_working_area(target
, crc_algorithm
);
793 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
795 destroy_reg_param(®_params
[0]);
796 destroy_reg_param(®_params
[1]);
798 target_free_working_area(target
, crc_algorithm
);
804 * Runs ARM code in the target to check whether a memory block holds
805 * all ones. NOR flash which has been erased, and thus may be written,
808 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
810 int arm_blank_check_memory(struct target
*target
,
811 uint32_t address
, uint32_t count
, uint32_t *blank
)
813 struct working_area
*check_algorithm
;
814 struct reg_param reg_params
[3];
815 struct armv4_5_algorithm armv4_5_info
;
819 static const uint32_t check_code
[] = {
821 0xe4d03001, /* ldrb r3, [r0], #1 */
822 0xe0022003, /* and r2, r2, r3 */
823 0xe2511001, /* subs r1, r1, #1 */
824 0x1afffffb, /* bne loop */
826 0xeafffffe /* b end */
829 /* make sure we have a working area */
830 retval
= target_alloc_working_area(target
,
831 sizeof(check_code
), &check_algorithm
);
832 if (retval
!= ERROR_OK
)
835 /* convert code into a buffer in target endianness */
836 for (i
= 0; i
< DIM(check_code
); i
++) {
837 retval
= target_write_u32(target
,
838 check_algorithm
->address
839 + i
* sizeof(uint32_t),
841 if (retval
!= ERROR_OK
)
845 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
846 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
847 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
849 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
850 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
852 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
853 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
855 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
856 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
858 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
859 check_algorithm
->address
,
860 check_algorithm
->address
+ sizeof(check_code
) - 4,
861 10000, &armv4_5_info
);
862 if (retval
!= ERROR_OK
) {
863 destroy_reg_param(®_params
[0]);
864 destroy_reg_param(®_params
[1]);
865 destroy_reg_param(®_params
[2]);
866 target_free_working_area(target
, check_algorithm
);
870 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
872 destroy_reg_param(®_params
[0]);
873 destroy_reg_param(®_params
[1]);
874 destroy_reg_param(®_params
[2]);
876 target_free_working_area(target
, check_algorithm
);
881 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
883 target
->arch_info
= armv4_5
;
885 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
886 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
887 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
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)