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 ***************************************************************************/
30 #include "replacements.h"
32 #include "arm_disassembler.h"
39 #include "binarybuffer.h"
46 bitfield_desc_t armv4_5_psr_bitfield_desc[] =
62 char* armv4_5_core_reg_list[] =
64 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
66 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
76 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
79 char * armv4_5_mode_strings_list[] =
81 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
84 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
85 char** armv4_5_mode_strings = armv4_5_mode_strings_list+1;
87 char* armv4_5_state_strings[] =
89 "ARM", "Thumb", "Jazelle"
92 int armv4_5_core_reg_arch_type = -1;
94 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
96 {0, ARMV4_5_MODE_ANY, NULL, NULL},
97 {1, ARMV4_5_MODE_ANY, NULL, NULL},
98 {2, ARMV4_5_MODE_ANY, NULL, NULL},
99 {3, ARMV4_5_MODE_ANY, NULL, NULL},
100 {4, ARMV4_5_MODE_ANY, NULL, NULL},
101 {5, ARMV4_5_MODE_ANY, NULL, NULL},
102 {6, ARMV4_5_MODE_ANY, NULL, NULL},
103 {7, ARMV4_5_MODE_ANY, NULL, NULL},
104 {8, ARMV4_5_MODE_ANY, NULL, NULL},
105 {9, ARMV4_5_MODE_ANY, NULL, NULL},
106 {10, ARMV4_5_MODE_ANY, NULL, NULL},
107 {11, ARMV4_5_MODE_ANY, NULL, NULL},
108 {12, ARMV4_5_MODE_ANY, NULL, NULL},
109 {13, ARMV4_5_MODE_USR, NULL, NULL},
110 {14, ARMV4_5_MODE_USR, NULL, NULL},
111 {15, ARMV4_5_MODE_ANY, NULL, NULL},
113 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
114 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
115 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
116 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
117 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
118 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
119 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
121 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
122 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
124 {13, ARMV4_5_MODE_SVC, NULL, NULL},
125 {14, ARMV4_5_MODE_SVC, NULL, NULL},
127 {13, ARMV4_5_MODE_ABT, NULL, NULL},
128 {14, ARMV4_5_MODE_ABT, NULL, NULL},
130 {13, ARMV4_5_MODE_UND, NULL, NULL},
131 {14, ARMV4_5_MODE_UND, NULL, NULL},
133 {16, ARMV4_5_MODE_ANY, NULL, NULL},
134 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
135 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
136 {16, ARMV4_5_MODE_SVC, NULL, NULL},
137 {16, ARMV4_5_MODE_ABT, NULL, NULL},
138 {16, ARMV4_5_MODE_UND, NULL, NULL}
141 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
142 int armv4_5_core_reg_map[7][17] =
145 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
148 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
151 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
154 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
157 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
160 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
163 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
167 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
169 reg_t armv4_5_gdb_dummy_fp_reg =
171 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
174 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
176 reg_t armv4_5_gdb_dummy_fps_reg =
178 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
182 int armv4_5_get_core_reg(reg_t *reg)
185 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
186 target_t *target = armv4_5->target;
188 if (target->state != TARGET_HALTED)
190 LOG_ERROR("Target not halted");
191 return ERROR_TARGET_NOT_HALTED;
194 /* retval = armv4_5->armv4_5_common->full_context(target); */
195 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
200 int armv4_5_set_core_reg(reg_t *reg, u8 *buf)
202 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
203 target_t *target = armv4_5->target;
204 armv4_5_common_t *armv4_5_target = target->arch_info;
205 u32 value = buf_get_u32(buf, 0, 32);
207 if (target->state != TARGET_HALTED)
209 return ERROR_TARGET_NOT_HALTED;
212 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
216 /* T bit should be set */
217 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
219 /* change state to Thumb */
220 LOG_DEBUG("changing to Thumb state");
221 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
226 /* T bit should be cleared */
227 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
229 /* change state to ARM */
230 LOG_DEBUG("changing to ARM state");
231 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
235 if (armv4_5_target->core_mode != (value & 0x1f))
237 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
238 armv4_5_target->core_mode = value & 0x1f;
239 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
243 buf_set_u32(reg->value, 0, 32, value);
250 int armv4_5_invalidate_core_regs(target_t *target)
252 armv4_5_common_t *armv4_5 = target->arch_info;
255 for (i = 0; i < 37; i++)
257 armv4_5->core_cache->reg_list[i].valid = 0;
258 armv4_5->core_cache->reg_list[i].dirty = 0;
264 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
267 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
268 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
269 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
272 cache->name = "arm v4/5 registers";
274 cache->reg_list = reg_list;
275 cache->num_regs = num_regs;
277 if (armv4_5_core_reg_arch_type == -1)
278 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
280 register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
281 register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
283 for (i = 0; i < 37; i++)
285 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
286 arch_info[i].target = target;
287 arch_info[i].armv4_5_common = armv4_5_common;
288 reg_list[i].name = armv4_5_core_reg_list[i];
289 reg_list[i].size = 32;
290 reg_list[i].value = calloc(1, 4);
291 reg_list[i].dirty = 0;
292 reg_list[i].valid = 0;
293 reg_list[i].bitfield_desc = NULL;
294 reg_list[i].num_bitfields = 0;
295 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
296 reg_list[i].arch_info = &arch_info[i];
302 int armv4_5_arch_state(struct target_s *target)
304 armv4_5_common_t *armv4_5 = target->arch_info;
306 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
308 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
312 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
313 armv4_5_state_strings[armv4_5->core_state],
314 Jim_Nvp_value2name_simple( nvp_target_debug_reason, target->debug_reason )->name,
315 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
316 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
317 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
322 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
327 target_t *target = get_current_target(cmd_ctx);
328 armv4_5_common_t *armv4_5 = target->arch_info;
330 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
332 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
336 if (target->state != TARGET_HALTED)
338 command_print(cmd_ctx, "error: target must be halted for register accesses");
342 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
345 for (num = 0; num <= 15; num++)
348 for (mode = 0; mode < 6; mode++)
350 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
352 armv4_5->full_context(target);
354 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
355 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
357 command_print(cmd_ctx, output);
359 command_print(cmd_ctx, " cpsr: %8.8x spsr_fiq: %8.8x spsr_irq: %8.8x spsr_svc: %8.8x spsr_abt: %8.8x spsr_und: %8.8x",
360 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
361 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
362 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
363 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
364 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
365 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
370 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
372 target_t *target = get_current_target(cmd_ctx);
373 armv4_5_common_t *armv4_5 = target->arch_info;
375 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
377 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
383 if (strcmp(args[0], "arm") == 0)
385 armv4_5->core_state = ARMV4_5_STATE_ARM;
387 if (strcmp(args[0], "thumb") == 0)
389 armv4_5->core_state = ARMV4_5_STATE_THUMB;
393 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
398 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
400 target_t *target = get_current_target(cmd_ctx);
401 armv4_5_common_t *armv4_5 = target->arch_info;
405 arm_instruction_t cur_instruction;
409 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
411 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
417 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
421 address = strtoul(args[0], NULL, 0);
422 count = strtoul(args[1], NULL, 0);
425 if (strcmp(args[2], "thumb") == 0)
428 for (i = 0; i < count; i++)
430 target_read_u32(target, address, &opcode);
431 arm_evaluate_opcode(opcode, address, &cur_instruction);
432 command_print(cmd_ctx, "%s", cur_instruction.text);
433 address += (thumb) ? 2 : 4;
439 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
441 command_t *armv4_5_cmd;
443 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
445 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
446 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
448 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
452 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
454 armv4_5_common_t *armv4_5 = target->arch_info;
457 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
461 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
463 for (i = 0; i < 16; i++)
465 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
468 for (i = 16; i < 24; i++)
470 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
473 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
474 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
479 /* wait for execution to complete and check exit point */
480 static int armv4_5_run_algorithm_completion(struct target_s *target, u32 exit_point, int timeout_ms, void *arch_info)
483 armv4_5_common_t *armv4_5 = target->arch_info;
485 target_wait_state(target, TARGET_HALTED, timeout_ms);
486 if (target->state != TARGET_HALTED)
488 if ((retval=target_halt(target))!=ERROR_OK)
490 if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK)
494 return ERROR_TARGET_TIMEOUT;
496 if (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point)
498 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
499 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
500 return ERROR_TARGET_TIMEOUT;
506 int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target_s *target, u32 exit_point, int timeout_ms, void *arch_info))
508 armv4_5_common_t *armv4_5 = target->arch_info;
509 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
510 enum armv4_5_state core_state = armv4_5->core_state;
511 enum armv4_5_mode core_mode = armv4_5->core_mode;
514 int exit_breakpoint_size = 0;
516 int retval = ERROR_OK;
517 LOG_DEBUG("Running algorithm");
519 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
521 LOG_ERROR("current target isn't an ARMV4/5 target");
522 return ERROR_TARGET_INVALID;
525 if (target->state != TARGET_HALTED)
527 LOG_WARNING("target not halted");
528 return ERROR_TARGET_NOT_HALTED;
531 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
534 for (i = 0; i <= 16; i++)
536 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
537 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
538 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
540 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
542 for (i = 0; i < num_mem_params; i++)
544 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
547 for (i = 0; i < num_reg_params; i++)
549 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
552 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
556 if (reg->size != reg_params[i].size)
558 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
562 armv4_5_set_core_reg(reg, reg_params[i].value);
565 armv4_5->core_state = armv4_5_algorithm_info->core_state;
566 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
567 exit_breakpoint_size = 4;
568 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
569 exit_breakpoint_size = 2;
572 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
576 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
578 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
579 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
580 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
581 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
584 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
586 LOG_ERROR("can't add breakpoint to finish algorithm execution");
587 return ERROR_TARGET_FAILURE;
590 target_resume(target, 0, entry_point, 1, 1);
592 retval=run_it(target, exit_point, timeout_ms, arch_info);
594 breakpoint_remove(target, exit_point);
596 for (i = 0; i < num_mem_params; i++)
598 if (mem_params[i].direction != PARAM_OUT)
599 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
602 for (i = 0; i < num_reg_params; i++)
604 if (reg_params[i].direction != PARAM_OUT)
607 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
610 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
614 if (reg->size != reg_params[i].size)
616 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
620 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
624 for (i = 0; i <= 16; i++)
626 LOG_DEBUG("restoring register %s with value 0x%8.8x", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]);
627 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
628 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
629 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
631 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
632 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
633 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
635 armv4_5->core_state = core_state;
636 armv4_5->core_mode = core_mode;
642 int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
644 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);
647 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
649 target->arch_info = armv4_5;
651 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
652 armv4_5->core_state = ARMV4_5_STATE_ARM;
653 armv4_5->core_mode = ARMV4_5_MODE_USR;