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 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
27 #include "replacements.h"
29 #include "arm_disassembler.h"
36 #include "binarybuffer.h"
43 bitfield_desc_t armv4_5_psr_bitfield_desc[] =
59 char* armv4_5_core_reg_list[] =
61 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
63 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
73 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
76 char * armv4_5_mode_strings_list[] =
78 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
81 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
82 char** armv4_5_mode_strings = armv4_5_mode_strings_list+1;
84 char* armv4_5_state_strings[] =
86 "ARM", "Thumb", "Jazelle"
89 int armv4_5_core_reg_arch_type = -1;
91 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
93 {0, ARMV4_5_MODE_ANY, NULL, NULL},
94 {1, ARMV4_5_MODE_ANY, NULL, NULL},
95 {2, ARMV4_5_MODE_ANY, NULL, NULL},
96 {3, ARMV4_5_MODE_ANY, NULL, NULL},
97 {4, ARMV4_5_MODE_ANY, NULL, NULL},
98 {5, ARMV4_5_MODE_ANY, NULL, NULL},
99 {6, ARMV4_5_MODE_ANY, NULL, NULL},
100 {7, ARMV4_5_MODE_ANY, NULL, NULL},
101 {8, ARMV4_5_MODE_ANY, NULL, NULL},
102 {9, ARMV4_5_MODE_ANY, NULL, NULL},
103 {10, ARMV4_5_MODE_ANY, NULL, NULL},
104 {11, ARMV4_5_MODE_ANY, NULL, NULL},
105 {12, ARMV4_5_MODE_ANY, NULL, NULL},
106 {13, ARMV4_5_MODE_USR, NULL, NULL},
107 {14, ARMV4_5_MODE_USR, NULL, NULL},
108 {15, ARMV4_5_MODE_ANY, NULL, NULL},
110 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
111 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
112 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
113 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
114 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
115 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
116 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
118 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
119 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
121 {13, ARMV4_5_MODE_SVC, NULL, NULL},
122 {14, ARMV4_5_MODE_SVC, NULL, NULL},
124 {13, ARMV4_5_MODE_ABT, NULL, NULL},
125 {14, ARMV4_5_MODE_ABT, NULL, NULL},
127 {13, ARMV4_5_MODE_UND, NULL, NULL},
128 {14, ARMV4_5_MODE_UND, NULL, NULL},
130 {16, ARMV4_5_MODE_ANY, NULL, NULL},
131 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
132 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
133 {16, ARMV4_5_MODE_SVC, NULL, NULL},
134 {16, ARMV4_5_MODE_ABT, NULL, NULL},
135 {16, ARMV4_5_MODE_UND, NULL, NULL}
138 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
139 int armv4_5_core_reg_map[7][17] =
142 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
145 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
151 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
154 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
157 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
160 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
164 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
166 reg_t armv4_5_gdb_dummy_fp_reg =
168 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
171 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
173 reg_t armv4_5_gdb_dummy_fps_reg =
175 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
179 int armv4_5_get_core_reg(reg_t *reg)
182 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
183 target_t *target = armv4_5->target;
185 if (target->state != TARGET_HALTED)
187 LOG_ERROR("Target not halted");
188 return ERROR_TARGET_NOT_HALTED;
191 /* retval = armv4_5->armv4_5_common->full_context(target); */
192 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
197 int armv4_5_set_core_reg(reg_t *reg, u8 *buf)
199 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
200 target_t *target = armv4_5->target;
201 armv4_5_common_t *armv4_5_target = target->arch_info;
202 u32 value = buf_get_u32(buf, 0, 32);
204 if (target->state != TARGET_HALTED)
206 return ERROR_TARGET_NOT_HALTED;
209 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
213 /* T bit should be set */
214 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
216 /* change state to Thumb */
217 LOG_DEBUG("changing to Thumb state");
218 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
223 /* T bit should be cleared */
224 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
226 /* change state to ARM */
227 LOG_DEBUG("changing to ARM state");
228 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
232 if (armv4_5_target->core_mode != (value & 0x1f))
234 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
235 armv4_5_target->core_mode = value & 0x1f;
236 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
240 buf_set_u32(reg->value, 0, 32, value);
247 int armv4_5_invalidate_core_regs(target_t *target)
249 armv4_5_common_t *armv4_5 = target->arch_info;
252 for (i = 0; i < 37; i++)
254 armv4_5->core_cache->reg_list[i].valid = 0;
255 armv4_5->core_cache->reg_list[i].dirty = 0;
261 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
264 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
265 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
266 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
269 cache->name = "arm v4/5 registers";
271 cache->reg_list = reg_list;
272 cache->num_regs = num_regs;
274 if (armv4_5_core_reg_arch_type == -1)
275 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
277 for (i = 0; i < 37; i++)
279 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
280 arch_info[i].target = target;
281 arch_info[i].armv4_5_common = armv4_5_common;
282 reg_list[i].name = armv4_5_core_reg_list[i];
283 reg_list[i].size = 32;
284 reg_list[i].value = calloc(1, 4);
285 reg_list[i].dirty = 0;
286 reg_list[i].valid = 0;
287 reg_list[i].bitfield_desc = NULL;
288 reg_list[i].num_bitfields = 0;
289 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
290 reg_list[i].arch_info = &arch_info[i];
296 int armv4_5_arch_state(struct target_s *target)
298 armv4_5_common_t *armv4_5 = target->arch_info;
300 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
302 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
306 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
307 armv4_5_state_strings[armv4_5->core_state],
308 Jim_Nvp_value2name_simple( nvp_target_debug_reason, target->debug_reason )->name,
309 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
310 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
311 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
316 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
321 target_t *target = get_current_target(cmd_ctx);
322 armv4_5_common_t *armv4_5 = target->arch_info;
324 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
326 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
330 if (target->state != TARGET_HALTED)
332 command_print(cmd_ctx, "error: target must be halted for register accesses");
336 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
339 for (num = 0; num <= 15; num++)
342 for (mode = 0; mode < 6; mode++)
344 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
346 armv4_5->full_context(target);
348 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
349 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
351 command_print(cmd_ctx, output);
353 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",
354 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
355 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
356 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
357 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
358 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
359 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
364 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
366 target_t *target = get_current_target(cmd_ctx);
367 armv4_5_common_t *armv4_5 = target->arch_info;
369 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
371 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
377 if (strcmp(args[0], "arm") == 0)
379 armv4_5->core_state = ARMV4_5_STATE_ARM;
381 if (strcmp(args[0], "thumb") == 0)
383 armv4_5->core_state = ARMV4_5_STATE_THUMB;
387 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
392 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
394 target_t *target = get_current_target(cmd_ctx);
395 armv4_5_common_t *armv4_5 = target->arch_info;
399 arm_instruction_t cur_instruction;
403 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
405 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
411 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
415 address = strtoul(args[0], NULL, 0);
416 count = strtoul(args[1], NULL, 0);
419 if (strcmp(args[2], "thumb") == 0)
422 for (i = 0; i < count; i++)
424 target_read_u32(target, address, &opcode);
425 arm_evaluate_opcode(opcode, address, &cur_instruction);
426 command_print(cmd_ctx, "%s", cur_instruction.text);
427 address += (thumb) ? 2 : 4;
433 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
435 command_t *armv4_5_cmd;
437 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
439 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
440 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
442 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
446 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
448 armv4_5_common_t *armv4_5 = target->arch_info;
451 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
455 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
457 for (i = 0; i < 16; i++)
459 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
462 for (i = 16; i < 24; i++)
464 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
467 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
468 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
473 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)
475 armv4_5_common_t *armv4_5 = target->arch_info;
476 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
477 enum armv4_5_state core_state = armv4_5->core_state;
478 enum armv4_5_mode core_mode = armv4_5->core_mode;
481 int exit_breakpoint_size = 0;
483 int retval = ERROR_OK;
484 LOG_DEBUG("Running algorithm");
486 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
488 LOG_ERROR("current target isn't an ARMV4/5 target");
489 return ERROR_TARGET_INVALID;
492 if (target->state != TARGET_HALTED)
494 LOG_WARNING("target not halted");
495 return ERROR_TARGET_NOT_HALTED;
498 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
501 for (i = 0; i <= 16; i++)
503 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
504 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
505 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
507 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
509 for (i = 0; i < num_mem_params; i++)
511 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
514 for (i = 0; i < num_reg_params; i++)
516 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
519 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
523 if (reg->size != reg_params[i].size)
525 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
529 armv4_5_set_core_reg(reg, reg_params[i].value);
532 armv4_5->core_state = armv4_5_algorithm_info->core_state;
533 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
534 exit_breakpoint_size = 4;
535 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
536 exit_breakpoint_size = 2;
539 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
543 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
545 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
546 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
547 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
548 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
551 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
553 LOG_ERROR("can't add breakpoint to finish algorithm execution");
554 return ERROR_TARGET_FAILURE;
557 target_resume(target, 0, entry_point, 1, 1);
559 target_wait_state(target, TARGET_HALTED, timeout_ms);
560 if (target->state != TARGET_HALTED)
562 if ((retval=target_halt(target))!=ERROR_OK)
564 if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK)
568 return ERROR_TARGET_TIMEOUT;
571 if (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point)
573 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
574 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
575 return ERROR_TARGET_TIMEOUT;
578 breakpoint_remove(target, exit_point);
580 for (i = 0; i < num_mem_params; i++)
582 if (mem_params[i].direction != PARAM_OUT)
583 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
586 for (i = 0; i < num_reg_params; i++)
588 if (reg_params[i].direction != PARAM_OUT)
591 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
594 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
598 if (reg->size != reg_params[i].size)
600 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
604 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
608 for (i = 0; i <= 16; i++)
610 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]);
611 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
612 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
613 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
615 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
616 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
617 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
619 armv4_5->core_state = core_state;
620 armv4_5->core_mode = core_mode;
625 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
627 target->arch_info = armv4_5;
629 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
630 armv4_5->core_state = ARMV4_5_STATE_ARM;
631 armv4_5->core_mode = ARMV4_5_MODE_USR;