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_list[] =
75 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
78 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
79 char** armv4_5_mode_strings = armv4_5_mode_strings_list+1;
81 char* armv4_5_state_strings[] =
83 "ARM", "Thumb", "Jazelle"
86 int armv4_5_core_reg_arch_type = -1;
88 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
90 {0, ARMV4_5_MODE_ANY, NULL, NULL},
91 {1, ARMV4_5_MODE_ANY, NULL, NULL},
92 {2, ARMV4_5_MODE_ANY, NULL, NULL},
93 {3, ARMV4_5_MODE_ANY, NULL, NULL},
94 {4, ARMV4_5_MODE_ANY, NULL, NULL},
95 {5, ARMV4_5_MODE_ANY, NULL, NULL},
96 {6, ARMV4_5_MODE_ANY, NULL, NULL},
97 {7, ARMV4_5_MODE_ANY, NULL, NULL},
98 {8, ARMV4_5_MODE_ANY, NULL, NULL},
99 {9, ARMV4_5_MODE_ANY, NULL, NULL},
100 {10, ARMV4_5_MODE_ANY, NULL, NULL},
101 {11, ARMV4_5_MODE_ANY, NULL, NULL},
102 {12, ARMV4_5_MODE_ANY, NULL, NULL},
103 {13, ARMV4_5_MODE_USR, NULL, NULL},
104 {14, ARMV4_5_MODE_USR, NULL, NULL},
105 {15, ARMV4_5_MODE_ANY, NULL, NULL},
107 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
108 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
109 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
110 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
111 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
112 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
113 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
115 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
116 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
118 {13, ARMV4_5_MODE_SVC, NULL, NULL},
119 {14, ARMV4_5_MODE_SVC, NULL, NULL},
121 {13, ARMV4_5_MODE_ABT, NULL, NULL},
122 {14, ARMV4_5_MODE_ABT, NULL, NULL},
124 {13, ARMV4_5_MODE_UND, NULL, NULL},
125 {14, ARMV4_5_MODE_UND, NULL, NULL},
127 {16, ARMV4_5_MODE_ANY, NULL, NULL},
128 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
129 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
130 {16, ARMV4_5_MODE_SVC, NULL, NULL},
131 {16, ARMV4_5_MODE_ABT, NULL, NULL},
132 {16, ARMV4_5_MODE_UND, NULL, NULL}
135 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
136 int armv4_5_core_reg_map[7][17] =
139 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
142 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
145 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
151 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
154 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
157 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
161 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
163 reg_t armv4_5_gdb_dummy_fp_reg =
165 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
168 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
170 reg_t armv4_5_gdb_dummy_fps_reg =
172 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
176 int armv4_5_get_core_reg(reg_t *reg)
179 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
180 target_t *target = armv4_5->target;
182 if (target->state != TARGET_HALTED)
184 return ERROR_TARGET_NOT_HALTED;
187 /* retval = armv4_5->armv4_5_common->full_context(target); */
188 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
193 int armv4_5_set_core_reg(reg_t *reg, u8 *buf)
195 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
196 target_t *target = armv4_5->target;
197 armv4_5_common_t *armv4_5_target = target->arch_info;
198 u32 value = buf_get_u32(buf, 0, 32);
200 if (target->state != TARGET_HALTED)
202 return ERROR_TARGET_NOT_HALTED;
205 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
209 /* T bit should be set */
210 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
212 /* change state to Thumb */
213 LOG_DEBUG("changing to Thumb state");
214 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
219 /* T bit should be cleared */
220 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
222 /* change state to ARM */
223 LOG_DEBUG("changing to ARM state");
224 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
228 if (armv4_5_target->core_mode != (value & 0x1f))
230 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
231 armv4_5_target->core_mode = value & 0x1f;
232 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
236 buf_set_u32(reg->value, 0, 32, value);
243 int armv4_5_invalidate_core_regs(target_t *target)
245 armv4_5_common_t *armv4_5 = target->arch_info;
248 for (i = 0; i < 37; i++)
250 armv4_5->core_cache->reg_list[i].valid = 0;
251 armv4_5->core_cache->reg_list[i].dirty = 0;
257 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
260 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
261 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
262 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
265 cache->name = "arm v4/5 registers";
267 cache->reg_list = reg_list;
268 cache->num_regs = num_regs;
270 if (armv4_5_core_reg_arch_type == -1)
271 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
273 for (i = 0; i < 37; i++)
275 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
276 arch_info[i].target = target;
277 arch_info[i].armv4_5_common = armv4_5_common;
278 reg_list[i].name = armv4_5_core_reg_list[i];
279 reg_list[i].size = 32;
280 reg_list[i].value = calloc(1, 4);
281 reg_list[i].dirty = 0;
282 reg_list[i].valid = 0;
283 reg_list[i].bitfield_desc = NULL;
284 reg_list[i].num_bitfields = 0;
285 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
286 reg_list[i].arch_info = &arch_info[i];
292 int armv4_5_arch_state(struct target_s *target)
294 armv4_5_common_t *armv4_5 = target->arch_info;
296 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
298 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
302 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
303 armv4_5_state_strings[armv4_5->core_state],
304 target_debug_reason_strings[target->debug_reason],
305 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
306 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
307 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
312 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
317 target_t *target = get_current_target(cmd_ctx);
318 armv4_5_common_t *armv4_5 = target->arch_info;
320 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
322 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
326 if (target->state != TARGET_HALTED)
328 command_print(cmd_ctx, "error: target must be halted for register accesses");
332 for (num = 0; num <= 15; num++)
335 for (mode = 0; mode < 6; mode++)
337 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
339 armv4_5->full_context(target);
341 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
342 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
344 command_print(cmd_ctx, output);
346 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",
347 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
348 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
349 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
352 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
357 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
359 target_t *target = get_current_target(cmd_ctx);
360 armv4_5_common_t *armv4_5 = target->arch_info;
362 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
364 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
370 if (strcmp(args[0], "arm") == 0)
372 armv4_5->core_state = ARMV4_5_STATE_ARM;
374 if (strcmp(args[0], "thumb") == 0)
376 armv4_5->core_state = ARMV4_5_STATE_THUMB;
380 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
385 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
387 target_t *target = get_current_target(cmd_ctx);
388 armv4_5_common_t *armv4_5 = target->arch_info;
392 arm_instruction_t cur_instruction;
396 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
398 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
404 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
408 address = strtoul(args[0], NULL, 0);
409 count = strtoul(args[1], NULL, 0);
412 if (strcmp(args[2], "thumb") == 0)
415 for (i = 0; i < count; i++)
417 target_read_u32(target, address, &opcode);
418 arm_evaluate_opcode(opcode, address, &cur_instruction);
419 command_print(cmd_ctx, "%s", cur_instruction.text);
420 address += (thumb) ? 2 : 4;
426 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
428 command_t *armv4_5_cmd;
430 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
432 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
433 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
435 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
439 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
441 armv4_5_common_t *armv4_5 = target->arch_info;
445 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
447 for (i = 0; i < 16; i++)
449 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
452 for (i = 16; i < 24; i++)
454 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
457 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
458 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
463 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)
465 armv4_5_common_t *armv4_5 = target->arch_info;
466 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
467 enum armv4_5_state core_state = armv4_5->core_state;
468 enum armv4_5_mode core_mode = armv4_5->core_mode;
471 int exit_breakpoint_size = 0;
473 int retval = ERROR_OK;
474 LOG_DEBUG("Running algorithm");
476 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
478 LOG_ERROR("current target isn't an ARMV4/5 target");
479 return ERROR_TARGET_INVALID;
482 if (target->state != TARGET_HALTED)
484 LOG_WARNING("target not halted");
485 return ERROR_TARGET_NOT_HALTED;
488 for (i = 0; i <= 16; i++)
490 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
491 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
492 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
494 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
496 for (i = 0; i < num_mem_params; i++)
498 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
501 for (i = 0; i < num_reg_params; i++)
503 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
506 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
510 if (reg->size != reg_params[i].size)
512 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
516 armv4_5_set_core_reg(reg, reg_params[i].value);
519 armv4_5->core_state = armv4_5_algorithm_info->core_state;
520 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
521 exit_breakpoint_size = 4;
522 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
523 exit_breakpoint_size = 2;
526 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
530 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
532 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
533 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
534 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
535 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
538 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
540 LOG_ERROR("can't add breakpoint to finish algorithm execution");
541 return ERROR_TARGET_FAILURE;
544 target_resume(target, 0, entry_point, 1, 1);
547 while (target->state != TARGET_HALTED)
551 if ((timeout_ms -= 10) <= 0)
553 LOG_ERROR("timeout waiting for algorithm to complete, trying to halt target");
556 while (target->state != TARGET_HALTED)
560 if ((timeout_ms -= 10) <= 0)
562 LOG_ERROR("target didn't reenter debug state, exiting");
566 retval = ERROR_TARGET_TIMEOUT;
570 if ((retval != ERROR_TARGET_TIMEOUT) &&
571 (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));
577 breakpoint_remove(target, exit_point);
579 for (i = 0; i < num_mem_params; i++)
581 if (mem_params[i].direction != PARAM_OUT)
582 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
585 for (i = 0; i < num_reg_params; i++)
587 if (reg_params[i].direction != PARAM_OUT)
590 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
593 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
597 if (reg->size != reg_params[i].size)
599 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
603 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
607 for (i = 0; i <= 16; i++)
609 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]);
610 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
611 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
612 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
614 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
615 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
616 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
618 armv4_5->core_state = core_state;
619 armv4_5->core_mode = core_mode;
624 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
626 target->arch_info = armv4_5;
628 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
629 armv4_5->core_state = ARMV4_5_STATE_ARM;
630 armv4_5->core_mode = ARMV4_5_MODE_USR;