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"
37 char* armv4_5_core_reg_list[] =
39 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
41 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
51 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
54 char * armv4_5_mode_strings_list[] =
56 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
59 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
60 char** armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
62 char* armv4_5_state_strings[] =
64 "ARM", "Thumb", "Jazelle"
67 int armv4_5_core_reg_arch_type = -1;
69 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
71 {0, ARMV4_5_MODE_ANY, NULL, NULL},
72 {1, ARMV4_5_MODE_ANY, NULL, NULL},
73 {2, ARMV4_5_MODE_ANY, NULL, NULL},
74 {3, ARMV4_5_MODE_ANY, NULL, NULL},
75 {4, ARMV4_5_MODE_ANY, NULL, NULL},
76 {5, ARMV4_5_MODE_ANY, NULL, NULL},
77 {6, ARMV4_5_MODE_ANY, NULL, NULL},
78 {7, ARMV4_5_MODE_ANY, NULL, NULL},
79 {8, ARMV4_5_MODE_ANY, NULL, NULL},
80 {9, ARMV4_5_MODE_ANY, NULL, NULL},
81 {10, ARMV4_5_MODE_ANY, NULL, NULL},
82 {11, ARMV4_5_MODE_ANY, NULL, NULL},
83 {12, ARMV4_5_MODE_ANY, NULL, NULL},
84 {13, ARMV4_5_MODE_USR, NULL, NULL},
85 {14, ARMV4_5_MODE_USR, NULL, NULL},
86 {15, ARMV4_5_MODE_ANY, NULL, NULL},
88 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
89 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
90 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
91 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
92 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
93 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
94 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
96 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
97 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
99 {13, ARMV4_5_MODE_SVC, NULL, NULL},
100 {14, ARMV4_5_MODE_SVC, NULL, NULL},
102 {13, ARMV4_5_MODE_ABT, NULL, NULL},
103 {14, ARMV4_5_MODE_ABT, NULL, NULL},
105 {13, ARMV4_5_MODE_UND, NULL, NULL},
106 {14, ARMV4_5_MODE_UND, NULL, NULL},
108 {16, ARMV4_5_MODE_ANY, NULL, NULL},
109 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
110 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
111 {16, ARMV4_5_MODE_SVC, NULL, NULL},
112 {16, ARMV4_5_MODE_ABT, NULL, NULL},
113 {16, ARMV4_5_MODE_UND, NULL, NULL}
116 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
117 int armv4_5_core_reg_map[7][17] =
120 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
123 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
126 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
129 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
132 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
135 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
138 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
142 uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
144 struct reg armv4_5_gdb_dummy_fp_reg =
146 .name = "GDB dummy floating-point register",
147 .value = armv4_5_gdb_dummy_fp_value,
155 uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
157 struct reg armv4_5_gdb_dummy_fps_reg =
159 .name = "GDB dummy floating-point status register",
160 .value = armv4_5_gdb_dummy_fps_value,
168 int armv4_5_get_core_reg(struct reg *reg)
171 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
172 struct target *target = armv4_5->target;
174 if (target->state != TARGET_HALTED)
176 LOG_ERROR("Target not halted");
177 return ERROR_TARGET_NOT_HALTED;
180 /* retval = armv4_5->armv4_5_common->full_context(target); */
181 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
186 int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
188 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
189 struct target *target = armv4_5->target;
190 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
191 uint32_t value = buf_get_u32(buf, 0, 32);
193 if (target->state != TARGET_HALTED)
195 return ERROR_TARGET_NOT_HALTED;
198 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
202 /* T bit should be set */
203 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
205 /* change state to Thumb */
206 LOG_DEBUG("changing to Thumb state");
207 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
212 /* T bit should be cleared */
213 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
215 /* change state to ARM */
216 LOG_DEBUG("changing to ARM state");
217 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
221 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
223 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
224 armv4_5_target->core_mode = value & 0x1f;
225 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
229 buf_set_u32(reg->value, 0, 32, value);
236 int armv4_5_invalidate_core_regs(struct target *target)
238 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
241 for (i = 0; i < 37; i++)
243 armv4_5->core_cache->reg_list[i].valid = 0;
244 armv4_5->core_cache->reg_list[i].dirty = 0;
250 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
253 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
254 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
255 struct armv4_5_core_reg *arch_info = malloc(sizeof(struct armv4_5_core_reg) * num_regs);
258 cache->name = "arm v4/5 registers";
260 cache->reg_list = reg_list;
261 cache->num_regs = num_regs;
263 if (armv4_5_core_reg_arch_type == -1)
264 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
266 register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
267 register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
269 for (i = 0; i < 37; i++)
271 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
272 arch_info[i].target = target;
273 arch_info[i].armv4_5_common = armv4_5_common;
274 reg_list[i].name = armv4_5_core_reg_list[i];
275 reg_list[i].size = 32;
276 reg_list[i].value = calloc(1, 4);
277 reg_list[i].dirty = 0;
278 reg_list[i].valid = 0;
279 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
280 reg_list[i].arch_info = &arch_info[i];
286 int armv4_5_arch_state(struct target *target)
288 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
290 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
292 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
296 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
297 armv4_5_state_strings[armv4_5->core_state],
298 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
299 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
300 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
301 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
306 COMMAND_HANDLER(handle_armv4_5_reg_command)
311 struct target *target = get_current_target(cmd_ctx);
312 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
314 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
316 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
320 if (target->state != TARGET_HALTED)
322 command_print(cmd_ctx, "error: target must be halted for register accesses");
326 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
329 for (num = 0; num <= 15; num++)
332 for (mode = 0; mode < 6; mode++)
334 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
336 armv4_5->full_context(target);
338 output_len += snprintf(output + output_len,
340 "%8s: %8.8" PRIx32 " ",
341 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
342 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
344 command_print(cmd_ctx, "%s", output);
346 command_print(cmd_ctx,
347 " 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 "",
348 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
349 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
352 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
353 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
358 COMMAND_HANDLER(handle_armv4_5_core_state_command)
360 struct target *target = get_current_target(cmd_ctx);
361 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
363 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
365 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
371 if (strcmp(args[0], "arm") == 0)
373 armv4_5->core_state = ARMV4_5_STATE_ARM;
375 if (strcmp(args[0], "thumb") == 0)
377 armv4_5->core_state = ARMV4_5_STATE_THUMB;
381 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
386 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
388 int retval = ERROR_OK;
389 struct target *target = get_current_target(cmd_ctx);
390 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
394 struct arm_instruction cur_instruction;
396 uint16_t thumb_opcode;
399 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
401 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
407 if (strcmp(args[2], "thumb") != 0)
412 COMMAND_PARSE_NUMBER(int, args[1], count);
415 COMMAND_PARSE_NUMBER(u32, args[0], address);
416 if (address & 0x01) {
418 command_print(cmd_ctx, "Disassemble as Thumb");
426 command_print(cmd_ctx,
427 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
431 for (i = 0; i < count; i++)
435 if ((retval = target_read_u16(target, address, &thumb_opcode)) != ERROR_OK)
439 if ((retval = thumb_evaluate_opcode(thumb_opcode, address, &cur_instruction)) != ERROR_OK)
445 if ((retval = target_read_u32(target, address, &opcode)) != ERROR_OK)
449 if ((retval = arm_evaluate_opcode(opcode, address, &cur_instruction)) != ERROR_OK)
454 command_print(cmd_ctx, "%s", cur_instruction.text);
455 address += (thumb) ? 2 : 4;
461 int armv4_5_register_commands(struct command_context *cmd_ctx)
463 struct command *armv4_5_cmd;
465 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5",
467 "armv4/5 specific commands");
469 register_command(cmd_ctx, armv4_5_cmd, "reg",
470 handle_armv4_5_reg_command, COMMAND_EXEC,
471 "display ARM core registers");
472 register_command(cmd_ctx, armv4_5_cmd, "core_state",
473 handle_armv4_5_core_state_command, COMMAND_EXEC,
474 "display/change ARM core state <arm | thumb>");
475 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
476 handle_armv4_5_disassemble_command, COMMAND_EXEC,
477 "disassemble instructions <address> [<count> ['thumb']]");
482 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
484 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
487 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
491 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
493 for (i = 0; i < 16; i++)
495 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
498 for (i = 16; i < 24; i++)
500 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
503 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
504 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
509 /* wait for execution to complete and check exit point */
510 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
513 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
515 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
519 if (target->state != TARGET_HALTED)
521 if ((retval = target_halt(target)) != ERROR_OK)
523 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
527 return ERROR_TARGET_TIMEOUT;
530 /* fast exit: ARMv5+ code can use BKPT */
531 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
532 0, 32) != exit_point)
534 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
535 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
536 return ERROR_TARGET_TIMEOUT;
542 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))
544 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
545 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
546 enum armv4_5_state core_state = armv4_5->core_state;
547 enum armv4_5_mode core_mode = armv4_5->core_mode;
548 uint32_t context[17];
550 int exit_breakpoint_size = 0;
552 int retval = ERROR_OK;
553 LOG_DEBUG("Running algorithm");
555 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
557 LOG_ERROR("current target isn't an ARMV4/5 target");
558 return ERROR_TARGET_INVALID;
561 if (target->state != TARGET_HALTED)
563 LOG_WARNING("target not halted");
564 return ERROR_TARGET_NOT_HALTED;
567 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
570 /* armv5 and later can terminate with BKPT instruction; less overhead */
571 if (!exit_point && armv4_5->is_armv4)
573 LOG_ERROR("ARMv4 target needs HW breakpoint location");
577 for (i = 0; i <= 16; i++)
579 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
580 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
581 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
583 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
585 for (i = 0; i < num_mem_params; i++)
587 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
593 for (i = 0; i < num_reg_params; i++)
595 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
598 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
602 if (reg->size != reg_params[i].size)
604 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
608 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
614 armv4_5->core_state = armv4_5_algorithm_info->core_state;
615 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
616 exit_breakpoint_size = 4;
617 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
618 exit_breakpoint_size = 2;
621 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
625 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
627 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
628 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
629 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
630 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
633 /* terminate using a hardware or (ARMv5+) software breakpoint */
634 if (exit_point && (retval = breakpoint_add(target, exit_point,
635 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
637 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
638 return ERROR_TARGET_FAILURE;
641 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
646 retval = run_it(target, exit_point, timeout_ms, arch_info);
649 breakpoint_remove(target, exit_point);
651 if (retval != ERROR_OK)
654 for (i = 0; i < num_mem_params; i++)
656 if (mem_params[i].direction != PARAM_OUT)
657 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
663 for (i = 0; i < num_reg_params; i++)
665 if (reg_params[i].direction != PARAM_OUT)
668 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
671 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
675 if (reg->size != reg_params[i].size)
677 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
681 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
685 for (i = 0; i <= 16; i++)
688 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
689 if (regvalue != context[i])
691 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]);
692 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
693 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
694 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
697 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
698 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
699 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
701 armv4_5->core_state = core_state;
702 armv4_5->core_mode = core_mode;
707 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)
709 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);
713 * Runs ARM code in the target to calculate a CRC32 checksum.
715 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
717 int arm_checksum_memory(struct target *target,
718 uint32_t address, uint32_t count, uint32_t *checksum)
720 struct working_area *crc_algorithm;
721 struct armv4_5_algorithm armv4_5_info;
722 struct reg_param reg_params[2];
726 static const uint32_t arm_crc_code[] = {
727 0xE1A02000, /* mov r2, r0 */
728 0xE3E00000, /* mov r0, #0xffffffff */
729 0xE1A03001, /* mov r3, r1 */
730 0xE3A04000, /* mov r4, #0 */
731 0xEA00000B, /* b ncomp */
733 0xE7D21004, /* ldrb r1, [r2, r4] */
734 0xE59F7030, /* ldr r7, CRC32XOR */
735 0xE0200C01, /* eor r0, r0, r1, asl 24 */
736 0xE3A05000, /* mov r5, #0 */
738 0xE3500000, /* cmp r0, #0 */
739 0xE1A06080, /* mov r6, r0, asl #1 */
740 0xE2855001, /* add r5, r5, #1 */
741 0xE1A00006, /* mov r0, r6 */
742 0xB0260007, /* eorlt r0, r6, r7 */
743 0xE3550008, /* cmp r5, #8 */
744 0x1AFFFFF8, /* bne loop */
745 0xE2844001, /* add r4, r4, #1 */
747 0xE1540003, /* cmp r4, r3 */
748 0x1AFFFFF1, /* bne nbyte */
750 0xEAFFFFFE, /* b end */
752 0x04C11DB7 /* .word 0x04C11DB7 */
755 retval = target_alloc_working_area(target,
756 sizeof(arm_crc_code), &crc_algorithm);
757 if (retval != ERROR_OK)
760 /* convert code into a buffer in target endianness */
761 for (i = 0; i < DIM(arm_crc_code); i++) {
762 retval = target_write_u32(target,
763 crc_algorithm->address + i * sizeof(uint32_t),
765 if (retval != ERROR_OK)
769 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
770 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
771 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
773 init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
774 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
776 buf_set_u32(reg_params[0].value, 0, 32, address);
777 buf_set_u32(reg_params[1].value, 0, 32, count);
779 /* 20 second timeout/megabyte */
780 int timeout = 20000 * (1 + (count / (1024 * 1024)));
782 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
783 crc_algorithm->address,
784 crc_algorithm->address + sizeof(arm_crc_code) - 8,
785 timeout, &armv4_5_info);
786 if (retval != ERROR_OK) {
787 LOG_ERROR("error executing ARM crc algorithm");
788 destroy_reg_param(®_params[0]);
789 destroy_reg_param(®_params[1]);
790 target_free_working_area(target, crc_algorithm);
794 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
796 destroy_reg_param(®_params[0]);
797 destroy_reg_param(®_params[1]);
799 target_free_working_area(target, crc_algorithm);
805 * Runs ARM code in the target to check whether a memory block holds
806 * all ones. NOR flash which has been erased, and thus may be written,
809 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
811 int arm_blank_check_memory(struct target *target,
812 uint32_t address, uint32_t count, uint32_t *blank)
814 struct working_area *check_algorithm;
815 struct reg_param reg_params[3];
816 struct armv4_5_algorithm armv4_5_info;
820 static const uint32_t check_code[] = {
822 0xe4d03001, /* ldrb r3, [r0], #1 */
823 0xe0022003, /* and r2, r2, r3 */
824 0xe2511001, /* subs r1, r1, #1 */
825 0x1afffffb, /* bne loop */
827 0xeafffffe /* b end */
830 /* make sure we have a working area */
831 retval = target_alloc_working_area(target,
832 sizeof(check_code), &check_algorithm);
833 if (retval != ERROR_OK)
836 /* convert code into a buffer in target endianness */
837 for (i = 0; i < DIM(check_code); i++) {
838 retval = target_write_u32(target,
839 check_algorithm->address
840 + i * sizeof(uint32_t),
842 if (retval != ERROR_OK)
846 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
847 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
848 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
850 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
851 buf_set_u32(reg_params[0].value, 0, 32, address);
853 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
854 buf_set_u32(reg_params[1].value, 0, 32, count);
856 init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
857 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
859 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
860 check_algorithm->address,
861 check_algorithm->address + sizeof(check_code) - 4,
862 10000, &armv4_5_info);
863 if (retval != ERROR_OK) {
864 destroy_reg_param(®_params[0]);
865 destroy_reg_param(®_params[1]);
866 destroy_reg_param(®_params[2]);
867 target_free_working_area(target, check_algorithm);
871 *blank = buf_get_u32(reg_params[2].value, 0, 32);
873 destroy_reg_param(®_params[0]);
874 destroy_reg_param(®_params[1]);
875 destroy_reg_param(®_params[2]);
877 target_free_working_area(target, check_algorithm);
882 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
884 target->arch_info = armv4_5;
886 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
887 armv4_5->core_state = ARMV4_5_STATE_ARM;
888 armv4_5->core_mode = ARMV4_5_MODE_USR;