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 char* armv4_5_core_reg_list[] =
41 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
43 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
53 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
56 char * armv4_5_mode_strings_list[] =
58 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
61 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
62 char** armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
64 char* armv4_5_state_strings[] =
66 "ARM", "Thumb", "Jazelle"
69 int armv4_5_core_reg_arch_type = -1;
71 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
73 {0, ARMV4_5_MODE_ANY, NULL, NULL},
74 {1, ARMV4_5_MODE_ANY, NULL, NULL},
75 {2, ARMV4_5_MODE_ANY, NULL, NULL},
76 {3, ARMV4_5_MODE_ANY, NULL, NULL},
77 {4, ARMV4_5_MODE_ANY, NULL, NULL},
78 {5, ARMV4_5_MODE_ANY, NULL, NULL},
79 {6, ARMV4_5_MODE_ANY, NULL, NULL},
80 {7, ARMV4_5_MODE_ANY, NULL, NULL},
81 {8, ARMV4_5_MODE_ANY, NULL, NULL},
82 {9, ARMV4_5_MODE_ANY, NULL, NULL},
83 {10, ARMV4_5_MODE_ANY, NULL, NULL},
84 {11, ARMV4_5_MODE_ANY, NULL, NULL},
85 {12, ARMV4_5_MODE_ANY, NULL, NULL},
86 {13, ARMV4_5_MODE_USR, NULL, NULL},
87 {14, ARMV4_5_MODE_USR, NULL, NULL},
88 {15, ARMV4_5_MODE_ANY, NULL, NULL},
90 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
91 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
92 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
93 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
94 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
95 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
96 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
98 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
99 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
101 {13, ARMV4_5_MODE_SVC, NULL, NULL},
102 {14, ARMV4_5_MODE_SVC, NULL, NULL},
104 {13, ARMV4_5_MODE_ABT, NULL, NULL},
105 {14, ARMV4_5_MODE_ABT, NULL, NULL},
107 {13, ARMV4_5_MODE_UND, NULL, NULL},
108 {14, ARMV4_5_MODE_UND, NULL, NULL},
110 {16, ARMV4_5_MODE_ANY, NULL, NULL},
111 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
112 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
113 {16, ARMV4_5_MODE_SVC, NULL, NULL},
114 {16, ARMV4_5_MODE_ABT, NULL, NULL},
115 {16, ARMV4_5_MODE_UND, NULL, NULL}
118 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
119 int armv4_5_core_reg_map[7][17] =
122 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
125 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
128 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
131 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
140 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
144 uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
146 struct reg armv4_5_gdb_dummy_fp_reg =
148 .name = "GDB dummy floating-point register",
149 .value = armv4_5_gdb_dummy_fp_value,
157 uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
159 struct reg armv4_5_gdb_dummy_fps_reg =
161 .name = "GDB dummy floating-point status register",
162 .value = armv4_5_gdb_dummy_fps_value,
170 int armv4_5_get_core_reg(struct reg *reg)
173 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
174 struct target *target = armv4_5->target;
176 if (target->state != TARGET_HALTED)
178 LOG_ERROR("Target not halted");
179 return ERROR_TARGET_NOT_HALTED;
182 /* retval = armv4_5->armv4_5_common->full_context(target); */
183 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
188 int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
190 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
191 struct target *target = armv4_5->target;
192 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
193 uint32_t value = buf_get_u32(buf, 0, 32);
195 if (target->state != TARGET_HALTED)
197 return ERROR_TARGET_NOT_HALTED;
200 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
204 /* T bit should be set */
205 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
207 /* change state to Thumb */
208 LOG_DEBUG("changing to Thumb state");
209 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
214 /* T bit should be cleared */
215 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
217 /* change state to ARM */
218 LOG_DEBUG("changing to ARM state");
219 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
223 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
225 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
226 armv4_5_target->core_mode = value & 0x1f;
227 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
231 buf_set_u32(reg->value, 0, 32, value);
238 int armv4_5_invalidate_core_regs(struct target *target)
240 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
243 for (i = 0; i < 37; i++)
245 armv4_5->core_cache->reg_list[i].valid = 0;
246 armv4_5->core_cache->reg_list[i].dirty = 0;
252 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
255 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
256 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
257 struct armv4_5_core_reg *arch_info = malloc(sizeof(struct armv4_5_core_reg) * num_regs);
260 cache->name = "arm v4/5 registers";
262 cache->reg_list = reg_list;
263 cache->num_regs = num_regs;
265 if (armv4_5_core_reg_arch_type == -1)
266 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
268 register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
269 register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
271 for (i = 0; i < 37; i++)
273 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
274 arch_info[i].target = target;
275 arch_info[i].armv4_5_common = armv4_5_common;
276 reg_list[i].name = armv4_5_core_reg_list[i];
277 reg_list[i].size = 32;
278 reg_list[i].value = calloc(1, 4);
279 reg_list[i].dirty = 0;
280 reg_list[i].valid = 0;
281 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
282 reg_list[i].arch_info = &arch_info[i];
288 int armv4_5_arch_state(struct target *target)
290 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
292 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
294 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
298 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
299 armv4_5_state_strings[armv4_5->core_state],
300 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
301 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
302 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
303 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
308 COMMAND_HANDLER(handle_armv4_5_reg_command)
313 struct target *target = get_current_target(cmd_ctx);
314 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
316 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
318 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
322 if (target->state != TARGET_HALTED)
324 command_print(cmd_ctx, "error: target must be halted for register accesses");
328 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
331 for (num = 0; num <= 15; num++)
334 for (mode = 0; mode < 6; mode++)
336 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
338 armv4_5->full_context(target);
340 output_len += snprintf(output + output_len,
342 "%8s: %8.8" PRIx32 " ",
343 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
344 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
346 command_print(cmd_ctx, "%s", output);
348 command_print(cmd_ctx,
349 " 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 "",
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
352 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
353 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
354 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
355 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
360 COMMAND_HANDLER(handle_armv4_5_core_state_command)
362 struct target *target = get_current_target(cmd_ctx);
363 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
365 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
367 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
373 if (strcmp(args[0], "arm") == 0)
375 armv4_5->core_state = ARMV4_5_STATE_ARM;
377 if (strcmp(args[0], "thumb") == 0)
379 armv4_5->core_state = ARMV4_5_STATE_THUMB;
383 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
388 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
390 int retval = ERROR_OK;
391 struct target *target = get_current_target(cmd_ctx);
392 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
396 struct arm_instruction cur_instruction;
398 uint16_t thumb_opcode;
401 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
403 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
409 if (strcmp(args[2], "thumb") != 0)
414 COMMAND_PARSE_NUMBER(int, args[1], count);
417 COMMAND_PARSE_NUMBER(u32, args[0], address);
418 if (address & 0x01) {
420 command_print(cmd_ctx, "Disassemble as Thumb");
428 command_print(cmd_ctx,
429 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
433 for (i = 0; i < count; i++)
437 if ((retval = target_read_u16(target, address, &thumb_opcode)) != ERROR_OK)
441 if ((retval = thumb_evaluate_opcode(thumb_opcode, address, &cur_instruction)) != ERROR_OK)
447 if ((retval = target_read_u32(target, address, &opcode)) != ERROR_OK)
451 if ((retval = arm_evaluate_opcode(opcode, address, &cur_instruction)) != ERROR_OK)
456 command_print(cmd_ctx, "%s", cur_instruction.text);
457 address += (thumb) ? 2 : 4;
463 int armv4_5_register_commands(struct command_context *cmd_ctx)
465 struct command *armv4_5_cmd;
467 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5",
469 "armv4/5 specific commands");
471 register_command(cmd_ctx, armv4_5_cmd, "reg",
472 handle_armv4_5_reg_command, COMMAND_EXEC,
473 "display ARM core registers");
474 register_command(cmd_ctx, armv4_5_cmd, "core_state",
475 handle_armv4_5_core_state_command, COMMAND_EXEC,
476 "display/change ARM core state <arm | thumb>");
477 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
478 handle_armv4_5_disassemble_command, COMMAND_EXEC,
479 "disassemble instructions <address> [<count> ['thumb']]");
484 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
486 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
489 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
493 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
495 for (i = 0; i < 16; i++)
497 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
500 for (i = 16; i < 24; i++)
502 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
505 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
506 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
511 /* wait for execution to complete and check exit point */
512 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
515 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
517 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
521 if (target->state != TARGET_HALTED)
523 if ((retval = target_halt(target)) != ERROR_OK)
525 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
529 return ERROR_TARGET_TIMEOUT;
532 /* fast exit: ARMv5+ code can use BKPT */
533 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
534 0, 32) != exit_point)
536 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
537 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
538 return ERROR_TARGET_TIMEOUT;
544 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))
546 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
547 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
548 enum armv4_5_state core_state = armv4_5->core_state;
549 enum armv4_5_mode core_mode = armv4_5->core_mode;
550 uint32_t context[17];
552 int exit_breakpoint_size = 0;
554 int retval = ERROR_OK;
555 LOG_DEBUG("Running algorithm");
557 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
559 LOG_ERROR("current target isn't an ARMV4/5 target");
560 return ERROR_TARGET_INVALID;
563 if (target->state != TARGET_HALTED)
565 LOG_WARNING("target not halted");
566 return ERROR_TARGET_NOT_HALTED;
569 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
572 /* armv5 and later can terminate with BKPT instruction; less overhead */
573 if (!exit_point && armv4_5->is_armv4)
575 LOG_ERROR("ARMv4 target needs HW breakpoint location");
579 for (i = 0; i <= 16; i++)
581 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
582 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
583 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
585 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
587 for (i = 0; i < num_mem_params; i++)
589 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
595 for (i = 0; i < num_reg_params; i++)
597 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
600 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
604 if (reg->size != reg_params[i].size)
606 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
610 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
616 armv4_5->core_state = armv4_5_algorithm_info->core_state;
617 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
618 exit_breakpoint_size = 4;
619 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
620 exit_breakpoint_size = 2;
623 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
627 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
629 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
630 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
631 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
632 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
635 /* terminate using a hardware or (ARMv5+) software breakpoint */
636 if (exit_point && (retval = breakpoint_add(target, exit_point,
637 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
639 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
640 return ERROR_TARGET_FAILURE;
643 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
648 retval = run_it(target, exit_point, timeout_ms, arch_info);
651 breakpoint_remove(target, exit_point);
653 if (retval != ERROR_OK)
656 for (i = 0; i < num_mem_params; i++)
658 if (mem_params[i].direction != PARAM_OUT)
659 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
665 for (i = 0; i < num_reg_params; i++)
667 if (reg_params[i].direction != PARAM_OUT)
670 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
673 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
677 if (reg->size != reg_params[i].size)
679 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
683 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
687 for (i = 0; i <= 16; i++)
690 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
691 if (regvalue != context[i])
693 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]);
694 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
695 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
696 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
699 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
700 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
701 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
703 armv4_5->core_state = core_state;
704 armv4_5->core_mode = core_mode;
709 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)
711 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);
715 * Runs ARM code in the target to calculate a CRC32 checksum.
717 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
719 int arm_checksum_memory(struct target *target,
720 uint32_t address, uint32_t count, uint32_t *checksum)
722 struct working_area *crc_algorithm;
723 struct armv4_5_algorithm armv4_5_info;
724 struct reg_param reg_params[2];
728 static const uint32_t arm_crc_code[] = {
729 0xE1A02000, /* mov r2, r0 */
730 0xE3E00000, /* mov r0, #0xffffffff */
731 0xE1A03001, /* mov r3, r1 */
732 0xE3A04000, /* mov r4, #0 */
733 0xEA00000B, /* b ncomp */
735 0xE7D21004, /* ldrb r1, [r2, r4] */
736 0xE59F7030, /* ldr r7, CRC32XOR */
737 0xE0200C01, /* eor r0, r0, r1, asl 24 */
738 0xE3A05000, /* mov r5, #0 */
740 0xE3500000, /* cmp r0, #0 */
741 0xE1A06080, /* mov r6, r0, asl #1 */
742 0xE2855001, /* add r5, r5, #1 */
743 0xE1A00006, /* mov r0, r6 */
744 0xB0260007, /* eorlt r0, r6, r7 */
745 0xE3550008, /* cmp r5, #8 */
746 0x1AFFFFF8, /* bne loop */
747 0xE2844001, /* add r4, r4, #1 */
749 0xE1540003, /* cmp r4, r3 */
750 0x1AFFFFF1, /* bne nbyte */
752 0xEAFFFFFE, /* b end */
754 0x04C11DB7 /* .word 0x04C11DB7 */
757 retval = target_alloc_working_area(target,
758 sizeof(arm_crc_code), &crc_algorithm);
759 if (retval != ERROR_OK)
762 /* convert code into a buffer in target endianness */
763 for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) {
764 retval = target_write_u32(target,
765 crc_algorithm->address + i * sizeof(uint32_t),
767 if (retval != ERROR_OK)
771 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
772 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
773 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
775 init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
776 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
778 buf_set_u32(reg_params[0].value, 0, 32, address);
779 buf_set_u32(reg_params[1].value, 0, 32, count);
781 /* 20 second timeout/megabyte */
782 int timeout = 20000 * (1 + (count / (1024 * 1024)));
784 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
785 crc_algorithm->address,
786 crc_algorithm->address + sizeof(arm_crc_code) - 8,
787 timeout, &armv4_5_info);
788 if (retval != ERROR_OK) {
789 LOG_ERROR("error executing ARM crc algorithm");
790 destroy_reg_param(®_params[0]);
791 destroy_reg_param(®_params[1]);
792 target_free_working_area(target, crc_algorithm);
796 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
798 destroy_reg_param(®_params[0]);
799 destroy_reg_param(®_params[1]);
801 target_free_working_area(target, crc_algorithm);
807 * Runs ARM code in the target to check whether a memory block holds
808 * all ones. NOR flash which has been erased, and thus may be written,
811 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
813 int arm_blank_check_memory(struct target *target,
814 uint32_t address, uint32_t count, uint32_t *blank)
816 struct working_area *check_algorithm;
817 struct reg_param reg_params[3];
818 struct armv4_5_algorithm armv4_5_info;
822 static const uint32_t check_code[] = {
824 0xe4d03001, /* ldrb r3, [r0], #1 */
825 0xe0022003, /* and r2, r2, r3 */
826 0xe2511001, /* subs r1, r1, #1 */
827 0x1afffffb, /* bne loop */
829 0xeafffffe /* b end */
832 /* make sure we have a working area */
833 retval = target_alloc_working_area(target,
834 sizeof(check_code), &check_algorithm);
835 if (retval != ERROR_OK)
838 /* convert code into a buffer in target endianness */
839 for (i = 0; i < ARRAY_SIZE(check_code); i++) {
840 retval = target_write_u32(target,
841 check_algorithm->address
842 + i * sizeof(uint32_t),
844 if (retval != ERROR_OK)
848 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
849 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
850 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
852 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
853 buf_set_u32(reg_params[0].value, 0, 32, address);
855 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
856 buf_set_u32(reg_params[1].value, 0, 32, count);
858 init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
859 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
861 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
862 check_algorithm->address,
863 check_algorithm->address + sizeof(check_code) - 4,
864 10000, &armv4_5_info);
865 if (retval != ERROR_OK) {
866 destroy_reg_param(®_params[0]);
867 destroy_reg_param(®_params[1]);
868 destroy_reg_param(®_params[2]);
869 target_free_working_area(target, check_algorithm);
873 *blank = buf_get_u32(reg_params[2].value, 0, 32);
875 destroy_reg_param(®_params[0]);
876 destroy_reg_param(®_params[1]);
877 destroy_reg_param(®_params[2]);
879 target_free_working_area(target, check_algorithm);
884 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
886 target->arch_info = armv4_5;
888 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
889 armv4_5->core_state = ARMV4_5_STATE_ARM;
890 armv4_5->core_mode = ARMV4_5_MODE_USR;