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"
34 #include "algorithm.h"
38 char* armv4_5_core_reg_list[] =
40 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
42 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
52 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
55 char * armv4_5_mode_strings_list[] =
57 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
60 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
61 char** armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
63 char* armv4_5_state_strings[] =
65 "ARM", "Thumb", "Jazelle"
68 int armv4_5_core_reg_arch_type = -1;
70 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
72 {0, ARMV4_5_MODE_ANY, NULL, NULL},
73 {1, ARMV4_5_MODE_ANY, NULL, NULL},
74 {2, ARMV4_5_MODE_ANY, NULL, NULL},
75 {3, ARMV4_5_MODE_ANY, NULL, NULL},
76 {4, ARMV4_5_MODE_ANY, NULL, NULL},
77 {5, ARMV4_5_MODE_ANY, NULL, NULL},
78 {6, ARMV4_5_MODE_ANY, NULL, NULL},
79 {7, ARMV4_5_MODE_ANY, NULL, NULL},
80 {8, ARMV4_5_MODE_ANY, NULL, NULL},
81 {9, ARMV4_5_MODE_ANY, NULL, NULL},
82 {10, ARMV4_5_MODE_ANY, NULL, NULL},
83 {11, ARMV4_5_MODE_ANY, NULL, NULL},
84 {12, ARMV4_5_MODE_ANY, NULL, NULL},
85 {13, ARMV4_5_MODE_USR, NULL, NULL},
86 {14, ARMV4_5_MODE_USR, NULL, NULL},
87 {15, ARMV4_5_MODE_ANY, NULL, NULL},
89 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
90 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
91 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
92 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
93 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
94 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
95 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
97 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
98 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
100 {13, ARMV4_5_MODE_SVC, NULL, NULL},
101 {14, ARMV4_5_MODE_SVC, NULL, NULL},
103 {13, ARMV4_5_MODE_ABT, NULL, NULL},
104 {14, ARMV4_5_MODE_ABT, NULL, NULL},
106 {13, ARMV4_5_MODE_UND, NULL, NULL},
107 {14, ARMV4_5_MODE_UND, NULL, NULL},
109 {16, ARMV4_5_MODE_ANY, NULL, NULL},
110 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
111 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
112 {16, ARMV4_5_MODE_SVC, NULL, NULL},
113 {16, ARMV4_5_MODE_ABT, NULL, NULL},
114 {16, ARMV4_5_MODE_UND, NULL, NULL}
117 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
118 int armv4_5_core_reg_map[7][17] =
121 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
124 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
127 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
130 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
133 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
136 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
139 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
143 uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
145 struct reg armv4_5_gdb_dummy_fp_reg =
147 .name = "GDB dummy floating-point register",
148 .value = armv4_5_gdb_dummy_fp_value,
156 uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
158 struct reg armv4_5_gdb_dummy_fps_reg =
160 .name = "GDB dummy floating-point status register",
161 .value = armv4_5_gdb_dummy_fps_value,
169 int armv4_5_get_core_reg(struct reg *reg)
172 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
173 struct target *target = armv4_5->target;
175 if (target->state != TARGET_HALTED)
177 LOG_ERROR("Target not halted");
178 return ERROR_TARGET_NOT_HALTED;
181 /* retval = armv4_5->armv4_5_common->full_context(target); */
182 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
187 int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
189 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
190 struct target *target = armv4_5->target;
191 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
192 uint32_t value = buf_get_u32(buf, 0, 32);
194 if (target->state != TARGET_HALTED)
196 return ERROR_TARGET_NOT_HALTED;
199 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
203 /* T bit should be set */
204 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
206 /* change state to Thumb */
207 LOG_DEBUG("changing to Thumb state");
208 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
213 /* T bit should be cleared */
214 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
216 /* change state to ARM */
217 LOG_DEBUG("changing to ARM state");
218 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
222 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
224 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
225 armv4_5_target->core_mode = value & 0x1f;
226 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
230 buf_set_u32(reg->value, 0, 32, value);
237 int armv4_5_invalidate_core_regs(struct target *target)
239 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
242 for (i = 0; i < 37; i++)
244 armv4_5->core_cache->reg_list[i].valid = 0;
245 armv4_5->core_cache->reg_list[i].dirty = 0;
251 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
254 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
255 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
256 struct armv4_5_core_reg *arch_info = malloc(sizeof(struct armv4_5_core_reg) * num_regs);
259 cache->name = "arm v4/5 registers";
261 cache->reg_list = reg_list;
262 cache->num_regs = num_regs;
264 if (armv4_5_core_reg_arch_type == -1)
265 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
267 register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
268 register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
270 for (i = 0; i < 37; i++)
272 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
273 arch_info[i].target = target;
274 arch_info[i].armv4_5_common = armv4_5_common;
275 reg_list[i].name = armv4_5_core_reg_list[i];
276 reg_list[i].size = 32;
277 reg_list[i].value = calloc(1, 4);
278 reg_list[i].dirty = 0;
279 reg_list[i].valid = 0;
280 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
281 reg_list[i].arch_info = &arch_info[i];
287 int armv4_5_arch_state(struct target *target)
289 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
291 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
293 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
297 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
298 armv4_5_state_strings[armv4_5->core_state],
299 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
300 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
301 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
302 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
307 COMMAND_HANDLER(handle_armv4_5_reg_command)
312 struct target *target = get_current_target(cmd_ctx);
313 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
315 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
317 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
321 if (target->state != TARGET_HALTED)
323 command_print(cmd_ctx, "error: target must be halted for register accesses");
327 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
330 for (num = 0; num <= 15; num++)
333 for (mode = 0; mode < 6; mode++)
335 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
337 armv4_5->full_context(target);
339 output_len += snprintf(output + output_len,
341 "%8s: %8.8" PRIx32 " ",
342 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
343 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
345 command_print(cmd_ctx, "%s", output);
347 command_print(cmd_ctx,
348 " 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 "",
349 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
352 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
353 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
354 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
359 COMMAND_HANDLER(handle_armv4_5_core_state_command)
361 struct target *target = get_current_target(cmd_ctx);
362 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
364 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
366 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
372 if (strcmp(args[0], "arm") == 0)
374 armv4_5->core_state = ARMV4_5_STATE_ARM;
376 if (strcmp(args[0], "thumb") == 0)
378 armv4_5->core_state = ARMV4_5_STATE_THUMB;
382 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
387 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
389 int retval = ERROR_OK;
390 struct target *target = get_current_target(cmd_ctx);
391 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
395 struct arm_instruction cur_instruction;
397 uint16_t thumb_opcode;
400 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
402 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
408 if (strcmp(args[2], "thumb") != 0)
413 COMMAND_PARSE_NUMBER(int, args[1], count);
416 COMMAND_PARSE_NUMBER(u32, args[0], address);
417 if (address & 0x01) {
419 command_print(cmd_ctx, "Disassemble as Thumb");
427 command_print(cmd_ctx,
428 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
432 for (i = 0; i < count; i++)
436 if ((retval = target_read_u16(target, address, &thumb_opcode)) != ERROR_OK)
440 if ((retval = thumb_evaluate_opcode(thumb_opcode, address, &cur_instruction)) != ERROR_OK)
446 if ((retval = target_read_u32(target, address, &opcode)) != ERROR_OK)
450 if ((retval = arm_evaluate_opcode(opcode, address, &cur_instruction)) != ERROR_OK)
455 command_print(cmd_ctx, "%s", cur_instruction.text);
456 address += (thumb) ? 2 : 4;
462 int armv4_5_register_commands(struct command_context *cmd_ctx)
464 struct command *armv4_5_cmd;
466 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5",
468 "armv4/5 specific commands");
470 register_command(cmd_ctx, armv4_5_cmd, "reg",
471 handle_armv4_5_reg_command, COMMAND_EXEC,
472 "display ARM core registers");
473 register_command(cmd_ctx, armv4_5_cmd, "core_state",
474 handle_armv4_5_core_state_command, COMMAND_EXEC,
475 "display/change ARM core state <arm | thumb>");
476 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
477 handle_armv4_5_disassemble_command, COMMAND_EXEC,
478 "disassemble instructions <address> [<count> ['thumb']]");
483 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
485 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
488 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
492 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
494 for (i = 0; i < 16; i++)
496 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
499 for (i = 16; i < 24; i++)
501 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
504 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
505 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
510 /* wait for execution to complete and check exit point */
511 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
514 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
516 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
520 if (target->state != TARGET_HALTED)
522 if ((retval = target_halt(target)) != ERROR_OK)
524 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
528 return ERROR_TARGET_TIMEOUT;
531 /* fast exit: ARMv5+ code can use BKPT */
532 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
533 0, 32) != exit_point)
535 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
536 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
537 return ERROR_TARGET_TIMEOUT;
543 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))
545 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
546 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
547 enum armv4_5_state core_state = armv4_5->core_state;
548 enum armv4_5_mode core_mode = armv4_5->core_mode;
549 uint32_t context[17];
551 int exit_breakpoint_size = 0;
553 int retval = ERROR_OK;
554 LOG_DEBUG("Running algorithm");
556 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
558 LOG_ERROR("current target isn't an ARMV4/5 target");
559 return ERROR_TARGET_INVALID;
562 if (target->state != TARGET_HALTED)
564 LOG_WARNING("target not halted");
565 return ERROR_TARGET_NOT_HALTED;
568 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
571 /* armv5 and later can terminate with BKPT instruction; less overhead */
572 if (!exit_point && armv4_5->is_armv4)
574 LOG_ERROR("ARMv4 target needs HW breakpoint location");
578 for (i = 0; i <= 16; i++)
580 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
581 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
582 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
584 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
586 for (i = 0; i < num_mem_params; i++)
588 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
594 for (i = 0; i < num_reg_params; i++)
596 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
599 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
603 if (reg->size != reg_params[i].size)
605 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
609 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
615 armv4_5->core_state = armv4_5_algorithm_info->core_state;
616 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
617 exit_breakpoint_size = 4;
618 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
619 exit_breakpoint_size = 2;
622 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
626 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
628 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
629 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
630 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
631 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
634 /* terminate using a hardware or (ARMv5+) software breakpoint */
635 if (exit_point && (retval = breakpoint_add(target, exit_point,
636 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
638 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
639 return ERROR_TARGET_FAILURE;
642 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
647 retval = run_it(target, exit_point, timeout_ms, arch_info);
650 breakpoint_remove(target, exit_point);
652 if (retval != ERROR_OK)
655 for (i = 0; i < num_mem_params; i++)
657 if (mem_params[i].direction != PARAM_OUT)
658 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
664 for (i = 0; i < num_reg_params; i++)
666 if (reg_params[i].direction != PARAM_OUT)
669 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
672 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
676 if (reg->size != reg_params[i].size)
678 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
682 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
686 for (i = 0; i <= 16; i++)
689 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
690 if (regvalue != context[i])
692 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]);
693 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
694 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
695 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
698 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
699 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
700 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
702 armv4_5->core_state = core_state;
703 armv4_5->core_mode = core_mode;
708 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)
710 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);
714 * Runs ARM code in the target to calculate a CRC32 checksum.
716 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
718 int arm_checksum_memory(struct target *target,
719 uint32_t address, uint32_t count, uint32_t *checksum)
721 struct working_area *crc_algorithm;
722 struct armv4_5_algorithm armv4_5_info;
723 struct reg_param reg_params[2];
727 static const uint32_t arm_crc_code[] = {
728 0xE1A02000, /* mov r2, r0 */
729 0xE3E00000, /* mov r0, #0xffffffff */
730 0xE1A03001, /* mov r3, r1 */
731 0xE3A04000, /* mov r4, #0 */
732 0xEA00000B, /* b ncomp */
734 0xE7D21004, /* ldrb r1, [r2, r4] */
735 0xE59F7030, /* ldr r7, CRC32XOR */
736 0xE0200C01, /* eor r0, r0, r1, asl 24 */
737 0xE3A05000, /* mov r5, #0 */
739 0xE3500000, /* cmp r0, #0 */
740 0xE1A06080, /* mov r6, r0, asl #1 */
741 0xE2855001, /* add r5, r5, #1 */
742 0xE1A00006, /* mov r0, r6 */
743 0xB0260007, /* eorlt r0, r6, r7 */
744 0xE3550008, /* cmp r5, #8 */
745 0x1AFFFFF8, /* bne loop */
746 0xE2844001, /* add r4, r4, #1 */
748 0xE1540003, /* cmp r4, r3 */
749 0x1AFFFFF1, /* bne nbyte */
751 0xEAFFFFFE, /* b end */
753 0x04C11DB7 /* .word 0x04C11DB7 */
756 retval = target_alloc_working_area(target,
757 sizeof(arm_crc_code), &crc_algorithm);
758 if (retval != ERROR_OK)
761 /* convert code into a buffer in target endianness */
762 for (i = 0; i < DIM(arm_crc_code); i++) {
763 retval = target_write_u32(target,
764 crc_algorithm->address + i * sizeof(uint32_t),
766 if (retval != ERROR_OK)
770 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
771 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
772 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
774 init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
775 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
777 buf_set_u32(reg_params[0].value, 0, 32, address);
778 buf_set_u32(reg_params[1].value, 0, 32, count);
780 /* 20 second timeout/megabyte */
781 int timeout = 20000 * (1 + (count / (1024 * 1024)));
783 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
784 crc_algorithm->address,
785 crc_algorithm->address + sizeof(arm_crc_code) - 8,
786 timeout, &armv4_5_info);
787 if (retval != ERROR_OK) {
788 LOG_ERROR("error executing ARM crc algorithm");
789 destroy_reg_param(®_params[0]);
790 destroy_reg_param(®_params[1]);
791 target_free_working_area(target, crc_algorithm);
795 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
797 destroy_reg_param(®_params[0]);
798 destroy_reg_param(®_params[1]);
800 target_free_working_area(target, crc_algorithm);
806 * Runs ARM code in the target to check whether a memory block holds
807 * all ones. NOR flash which has been erased, and thus may be written,
810 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
812 int arm_blank_check_memory(struct target *target,
813 uint32_t address, uint32_t count, uint32_t *blank)
815 struct working_area *check_algorithm;
816 struct reg_param reg_params[3];
817 struct armv4_5_algorithm armv4_5_info;
821 static const uint32_t check_code[] = {
823 0xe4d03001, /* ldrb r3, [r0], #1 */
824 0xe0022003, /* and r2, r2, r3 */
825 0xe2511001, /* subs r1, r1, #1 */
826 0x1afffffb, /* bne loop */
828 0xeafffffe /* b end */
831 /* make sure we have a working area */
832 retval = target_alloc_working_area(target,
833 sizeof(check_code), &check_algorithm);
834 if (retval != ERROR_OK)
837 /* convert code into a buffer in target endianness */
838 for (i = 0; i < DIM(check_code); i++) {
839 retval = target_write_u32(target,
840 check_algorithm->address
841 + i * sizeof(uint32_t),
843 if (retval != ERROR_OK)
847 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
848 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
849 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
851 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
852 buf_set_u32(reg_params[0].value, 0, 32, address);
854 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
855 buf_set_u32(reg_params[1].value, 0, 32, count);
857 init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
858 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
860 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
861 check_algorithm->address,
862 check_algorithm->address + sizeof(check_code) - 4,
863 10000, &armv4_5_info);
864 if (retval != ERROR_OK) {
865 destroy_reg_param(®_params[0]);
866 destroy_reg_param(®_params[1]);
867 destroy_reg_param(®_params[2]);
868 target_free_working_area(target, check_algorithm);
872 *blank = buf_get_u32(reg_params[2].value, 0, 32);
874 destroy_reg_param(®_params[0]);
875 destroy_reg_param(®_params[1]);
876 destroy_reg_param(®_params[2]);
878 target_free_working_area(target, check_algorithm);
883 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
885 target->arch_info = armv4_5;
887 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
888 armv4_5->core_state = ARMV4_5_STATE_ARM;
889 armv4_5->core_mode = ARMV4_5_MODE_USR;