1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 #include "replacements.h"
26 #include "arm_disassembler.h"
33 #include "binarybuffer.h"
40 bitfield_desc_t armv4_5_psr_bitfield_desc[] =
56 char* armv4_5_core_reg_list[] =
58 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
60 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
70 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
73 char* armv4_5_mode_strings[] =
75 "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
78 char* armv4_5_state_strings[] =
80 "ARM", "Thumb", "Jazelle"
83 int armv4_5_core_reg_arch_type = -1;
85 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
87 {0, ARMV4_5_MODE_ANY, NULL, NULL},
88 {1, ARMV4_5_MODE_ANY, NULL, NULL},
89 {2, ARMV4_5_MODE_ANY, NULL, NULL},
90 {3, ARMV4_5_MODE_ANY, NULL, NULL},
91 {4, ARMV4_5_MODE_ANY, NULL, NULL},
92 {5, ARMV4_5_MODE_ANY, NULL, NULL},
93 {6, ARMV4_5_MODE_ANY, NULL, NULL},
94 {7, ARMV4_5_MODE_ANY, NULL, NULL},
95 {8, ARMV4_5_MODE_ANY, NULL, NULL},
96 {9, ARMV4_5_MODE_ANY, NULL, NULL},
97 {10, ARMV4_5_MODE_ANY, NULL, NULL},
98 {11, ARMV4_5_MODE_ANY, NULL, NULL},
99 {12, ARMV4_5_MODE_ANY, NULL, NULL},
100 {13, ARMV4_5_MODE_USR, NULL, NULL},
101 {14, ARMV4_5_MODE_USR, NULL, NULL},
102 {15, ARMV4_5_MODE_ANY, NULL, NULL},
104 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
105 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
106 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
107 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
108 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
109 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
110 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
112 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
113 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
115 {13, ARMV4_5_MODE_SVC, NULL, NULL},
116 {14, ARMV4_5_MODE_SVC, NULL, NULL},
118 {13, ARMV4_5_MODE_ABT, NULL, NULL},
119 {14, ARMV4_5_MODE_ABT, NULL, NULL},
121 {13, ARMV4_5_MODE_UND, NULL, NULL},
122 {14, ARMV4_5_MODE_UND, NULL, NULL},
124 {16, ARMV4_5_MODE_ANY, NULL, NULL},
125 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
126 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
127 {16, ARMV4_5_MODE_SVC, NULL, NULL},
128 {16, ARMV4_5_MODE_ABT, NULL, NULL},
129 {16, ARMV4_5_MODE_UND, NULL, NULL}
132 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
133 int armv4_5_core_reg_map[7][17] =
136 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
139 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
142 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
145 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
151 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
154 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
158 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
160 reg_t armv4_5_gdb_dummy_fp_reg =
162 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
165 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
167 reg_t armv4_5_gdb_dummy_fps_reg =
169 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
173 int armv4_5_get_core_reg(reg_t *reg)
176 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
177 target_t *target = armv4_5->target;
179 if (target->state != TARGET_HALTED)
181 return ERROR_TARGET_NOT_HALTED;
184 /* retval = armv4_5->armv4_5_common->full_context(target); */
185 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
190 int armv4_5_set_core_reg(reg_t *reg, u8 *buf)
192 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
193 target_t *target = armv4_5->target;
194 armv4_5_common_t *armv4_5_target = target->arch_info;
195 u32 value = buf_get_u32(buf, 0, 32);
197 if (target->state != TARGET_HALTED)
199 return ERROR_TARGET_NOT_HALTED;
202 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
206 /* T bit should be set */
207 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
209 /* change state to Thumb */
210 LOG_DEBUG("changing to Thumb state");
211 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
216 /* T bit should be cleared */
217 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
219 /* change state to ARM */
220 LOG_DEBUG("changing to ARM state");
221 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
225 if (armv4_5_target->core_mode != (value & 0x1f))
227 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
228 armv4_5_target->core_mode = value & 0x1f;
229 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
233 buf_set_u32(reg->value, 0, 32, value);
240 int armv4_5_invalidate_core_regs(target_t *target)
242 armv4_5_common_t *armv4_5 = target->arch_info;
245 for (i = 0; i < 37; i++)
247 armv4_5->core_cache->reg_list[i].valid = 0;
248 armv4_5->core_cache->reg_list[i].dirty = 0;
254 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
257 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
258 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
259 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
262 cache->name = "arm v4/5 registers";
264 cache->reg_list = reg_list;
265 cache->num_regs = num_regs;
267 if (armv4_5_core_reg_arch_type == -1)
268 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
270 for (i = 0; i < 37; i++)
272 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
273 arch_info[i].target = target;
274 arch_info[i].armv4_5_common = armv4_5_common;
275 reg_list[i].name = armv4_5_core_reg_list[i];
276 reg_list[i].size = 32;
277 reg_list[i].value = calloc(1, 4);
278 reg_list[i].dirty = 0;
279 reg_list[i].valid = 0;
280 reg_list[i].bitfield_desc = NULL;
281 reg_list[i].num_bitfields = 0;
282 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
283 reg_list[i].arch_info = &arch_info[i];
289 int armv4_5_arch_state(struct target_s *target)
291 armv4_5_common_t *armv4_5 = target->arch_info;
293 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
295 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
299 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
300 armv4_5_state_strings[armv4_5->core_state],
301 target_debug_reason_strings[target->debug_reason],
302 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
303 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
304 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
309 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
314 target_t *target = get_current_target(cmd_ctx);
315 armv4_5_common_t *armv4_5 = target->arch_info;
317 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
319 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
323 if (target->state != TARGET_HALTED)
325 command_print(cmd_ctx, "error: target must be halted for register accesses");
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, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
339 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
341 command_print(cmd_ctx, output);
343 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",
344 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
345 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
346 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
347 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
348 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
349 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
354 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
356 target_t *target = get_current_target(cmd_ctx);
357 armv4_5_common_t *armv4_5 = target->arch_info;
359 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
361 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
367 if (strcmp(args[0], "arm") == 0)
369 armv4_5->core_state = ARMV4_5_STATE_ARM;
371 if (strcmp(args[0], "thumb") == 0)
373 armv4_5->core_state = ARMV4_5_STATE_THUMB;
377 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
382 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
384 target_t *target = get_current_target(cmd_ctx);
385 armv4_5_common_t *armv4_5 = target->arch_info;
389 arm_instruction_t cur_instruction;
393 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
395 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
401 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
405 address = strtoul(args[0], NULL, 0);
406 count = strtoul(args[1], NULL, 0);
409 if (strcmp(args[2], "thumb") == 0)
412 for (i = 0; i < count; i++)
414 target_read_u32(target, address, &opcode);
415 arm_evaluate_opcode(opcode, address, &cur_instruction);
416 command_print(cmd_ctx, "%s", cur_instruction.text);
417 address += (thumb) ? 2 : 4;
423 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
425 command_t *armv4_5_cmd;
427 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
429 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
430 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
432 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
436 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
438 armv4_5_common_t *armv4_5 = target->arch_info;
442 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
444 for (i = 0; i < 16; i++)
446 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
449 for (i = 16; i < 24; i++)
451 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
454 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
455 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
460 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)
462 armv4_5_common_t *armv4_5 = target->arch_info;
463 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
464 enum armv4_5_state core_state = armv4_5->core_state;
465 enum armv4_5_mode core_mode = armv4_5->core_mode;
468 int exit_breakpoint_size = 0;
470 int retval = ERROR_OK;
471 LOG_DEBUG("Running algorithm");
473 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
475 LOG_ERROR("current target isn't an ARMV4/5 target");
476 return ERROR_TARGET_INVALID;
479 if (target->state != TARGET_HALTED)
481 LOG_WARNING("target not halted");
482 return ERROR_TARGET_NOT_HALTED;
485 for (i = 0; i <= 16; i++)
487 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
488 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
489 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
491 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
493 for (i = 0; i < num_mem_params; i++)
495 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
498 for (i = 0; i < num_reg_params; i++)
500 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
503 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
507 if (reg->size != reg_params[i].size)
509 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
513 armv4_5_set_core_reg(reg, reg_params[i].value);
516 armv4_5->core_state = armv4_5_algorithm_info->core_state;
517 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
518 exit_breakpoint_size = 4;
519 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
520 exit_breakpoint_size = 2;
523 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
527 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
529 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
530 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
531 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
532 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
535 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
537 LOG_ERROR("can't add breakpoint to finish algorithm execution");
538 return ERROR_TARGET_FAILURE;
541 target_resume(target, 0, entry_point, 1, 1);
544 while (target->state != TARGET_HALTED)
548 if ((timeout_ms -= 10) <= 0)
550 LOG_ERROR("timeout waiting for algorithm to complete, trying to halt target");
553 while (target->state != TARGET_HALTED)
557 if ((timeout_ms -= 10) <= 0)
559 LOG_ERROR("target didn't reenter debug state, exiting");
563 retval = ERROR_TARGET_TIMEOUT;
567 if ((retval != ERROR_TARGET_TIMEOUT) &&
568 (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point))
570 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
571 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
574 breakpoint_remove(target, exit_point);
576 for (i = 0; i < num_mem_params; i++)
578 if (mem_params[i].direction != PARAM_OUT)
579 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
582 for (i = 0; i < num_reg_params; i++)
584 if (reg_params[i].direction != PARAM_OUT)
587 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
590 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
594 if (reg->size != reg_params[i].size)
596 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
600 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
604 for (i = 0; i <= 16; i++)
606 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]);
607 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
608 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
609 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
611 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
612 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
613 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
615 armv4_5->core_state = core_state;
616 armv4_5->core_mode = core_mode;
621 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
623 target->arch_info = armv4_5;
625 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
626 armv4_5->core_state = ARMV4_5_STATE_ARM;
627 armv4_5->core_mode = ARMV4_5_MODE_USR;