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 for (i = 0; i < 37; i++)
282 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
283 arch_info[i].target = target;
284 arch_info[i].armv4_5_common = armv4_5_common;
285 reg_list[i].name = armv4_5_core_reg_list[i];
286 reg_list[i].size = 32;
287 reg_list[i].value = calloc(1, 4);
288 reg_list[i].dirty = 0;
289 reg_list[i].valid = 0;
290 reg_list[i].bitfield_desc = NULL;
291 reg_list[i].num_bitfields = 0;
292 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
293 reg_list[i].arch_info = &arch_info[i];
299 int armv4_5_arch_state(struct target_s *target)
301 armv4_5_common_t *armv4_5 = target->arch_info;
303 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
305 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
309 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
310 armv4_5_state_strings[armv4_5->core_state],
311 Jim_Nvp_value2name_simple( nvp_target_debug_reason, target->debug_reason )->name,
312 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
313 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
314 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
319 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
324 target_t *target = get_current_target(cmd_ctx);
325 armv4_5_common_t *armv4_5 = target->arch_info;
327 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
329 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
333 if (target->state != TARGET_HALTED)
335 command_print(cmd_ctx, "error: target must be halted for register accesses");
339 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
342 for (num = 0; num <= 15; num++)
345 for (mode = 0; mode < 6; mode++)
347 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
349 armv4_5->full_context(target);
351 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
352 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
354 command_print(cmd_ctx, output);
356 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",
357 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
358 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
359 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
360 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
361 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
362 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
367 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
369 target_t *target = get_current_target(cmd_ctx);
370 armv4_5_common_t *armv4_5 = target->arch_info;
372 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
374 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
380 if (strcmp(args[0], "arm") == 0)
382 armv4_5->core_state = ARMV4_5_STATE_ARM;
384 if (strcmp(args[0], "thumb") == 0)
386 armv4_5->core_state = ARMV4_5_STATE_THUMB;
390 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
395 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
397 target_t *target = get_current_target(cmd_ctx);
398 armv4_5_common_t *armv4_5 = target->arch_info;
402 arm_instruction_t cur_instruction;
406 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
408 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
414 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
418 address = strtoul(args[0], NULL, 0);
419 count = strtoul(args[1], NULL, 0);
422 if (strcmp(args[2], "thumb") == 0)
425 for (i = 0; i < count; i++)
427 target_read_u32(target, address, &opcode);
428 arm_evaluate_opcode(opcode, address, &cur_instruction);
429 command_print(cmd_ctx, "%s", cur_instruction.text);
430 address += (thumb) ? 2 : 4;
436 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
438 command_t *armv4_5_cmd;
440 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
442 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
443 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
445 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
449 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
451 armv4_5_common_t *armv4_5 = target->arch_info;
454 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
458 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
460 for (i = 0; i < 16; i++)
462 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
465 for (i = 16; i < 24; i++)
467 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
470 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
471 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
476 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)
478 armv4_5_common_t *armv4_5 = target->arch_info;
479 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
480 enum armv4_5_state core_state = armv4_5->core_state;
481 enum armv4_5_mode core_mode = armv4_5->core_mode;
484 int exit_breakpoint_size = 0;
486 int retval = ERROR_OK;
487 LOG_DEBUG("Running algorithm");
489 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
491 LOG_ERROR("current target isn't an ARMV4/5 target");
492 return ERROR_TARGET_INVALID;
495 if (target->state != TARGET_HALTED)
497 LOG_WARNING("target not halted");
498 return ERROR_TARGET_NOT_HALTED;
501 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
504 for (i = 0; i <= 16; i++)
506 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
507 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
508 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
510 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
512 for (i = 0; i < num_mem_params; i++)
514 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
517 for (i = 0; i < num_reg_params; i++)
519 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
522 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
526 if (reg->size != reg_params[i].size)
528 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
532 armv4_5_set_core_reg(reg, reg_params[i].value);
535 armv4_5->core_state = armv4_5_algorithm_info->core_state;
536 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
537 exit_breakpoint_size = 4;
538 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
539 exit_breakpoint_size = 2;
542 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
546 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
548 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
549 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
550 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
551 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
554 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
556 LOG_ERROR("can't add breakpoint to finish algorithm execution");
557 return ERROR_TARGET_FAILURE;
560 target_resume(target, 0, entry_point, 1, 1);
562 target_wait_state(target, TARGET_HALTED, timeout_ms);
563 if (target->state != TARGET_HALTED)
565 if ((retval=target_halt(target))!=ERROR_OK)
567 if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK)
571 return ERROR_TARGET_TIMEOUT;
574 if (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point)
576 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
577 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
578 return ERROR_TARGET_TIMEOUT;
581 breakpoint_remove(target, exit_point);
583 for (i = 0; i < num_mem_params; i++)
585 if (mem_params[i].direction != PARAM_OUT)
586 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
589 for (i = 0; i < num_reg_params; i++)
591 if (reg_params[i].direction != PARAM_OUT)
594 reg_t *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 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
611 for (i = 0; i <= 16; i++)
613 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]);
614 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
615 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
616 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
618 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
619 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
620 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
622 armv4_5->core_state = core_state;
623 armv4_5->core_mode = core_mode;
628 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
630 target->arch_info = armv4_5;
632 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
633 armv4_5->core_state = ARMV4_5_STATE_ARM;
634 armv4_5->core_mode = ARMV4_5_MODE_USR;