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
172 /* map psr mode bits to linear number */
173 int armv4_5_mode_to_number(enum armv4_5_mode mode)
177 case ARMV4_5_MODE_USR: return 0; break;
178 case ARMV4_5_MODE_FIQ: return 1; break;
179 case ARMV4_5_MODE_IRQ: return 2; break;
180 case ARMV4_5_MODE_SVC: return 3; break;
181 case ARMV4_5_MODE_ABT: return 4; break;
182 case ARMV4_5_MODE_UND: return 5; break;
183 case ARMV4_5_MODE_SYS: return 6; break;
184 case ARMV4_5_MODE_ANY: return 0; break; /* map MODE_ANY to user mode */
186 LOG_ERROR("invalid mode value encountered");
191 /* map linear number to mode bits */
192 enum armv4_5_mode armv4_5_number_to_mode(int number)
196 case 0: return ARMV4_5_MODE_USR; break;
197 case 1: return ARMV4_5_MODE_FIQ; break;
198 case 2: return ARMV4_5_MODE_IRQ; break;
199 case 3: return ARMV4_5_MODE_SVC; break;
200 case 4: return ARMV4_5_MODE_ABT; break;
201 case 5: return ARMV4_5_MODE_UND; break;
202 case 6: return ARMV4_5_MODE_SYS; break;
204 LOG_ERROR("mode index out of bounds");
209 int armv4_5_get_core_reg(reg_t *reg)
212 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
213 target_t *target = armv4_5->target;
215 if (target->state != TARGET_HALTED)
217 return ERROR_TARGET_NOT_HALTED;
220 /* retval = armv4_5->armv4_5_common->full_context(target); */
221 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
226 int armv4_5_set_core_reg(reg_t *reg, u8 *buf)
228 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
229 target_t *target = armv4_5->target;
230 armv4_5_common_t *armv4_5_target = target->arch_info;
231 u32 value = buf_get_u32(buf, 0, 32);
233 if (target->state != TARGET_HALTED)
235 return ERROR_TARGET_NOT_HALTED;
238 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
242 /* T bit should be set */
243 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
245 /* change state to Thumb */
246 LOG_DEBUG("changing to Thumb state");
247 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
252 /* T bit should be cleared */
253 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
255 /* change state to ARM */
256 LOG_DEBUG("changing to ARM state");
257 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
261 if (armv4_5_target->core_mode != (value & 0x1f))
263 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
264 armv4_5_target->core_mode = value & 0x1f;
265 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
269 buf_set_u32(reg->value, 0, 32, value);
276 int armv4_5_invalidate_core_regs(target_t *target)
278 armv4_5_common_t *armv4_5 = target->arch_info;
281 for (i = 0; i < 37; i++)
283 armv4_5->core_cache->reg_list[i].valid = 0;
284 armv4_5->core_cache->reg_list[i].dirty = 0;
290 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
293 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
294 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
295 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
298 cache->name = "arm v4/5 registers";
300 cache->reg_list = reg_list;
301 cache->num_regs = num_regs;
303 if (armv4_5_core_reg_arch_type == -1)
304 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
306 for (i = 0; i < 37; i++)
308 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
309 arch_info[i].target = target;
310 arch_info[i].armv4_5_common = armv4_5_common;
311 reg_list[i].name = armv4_5_core_reg_list[i];
312 reg_list[i].size = 32;
313 reg_list[i].value = calloc(1, 4);
314 reg_list[i].dirty = 0;
315 reg_list[i].valid = 0;
316 reg_list[i].bitfield_desc = NULL;
317 reg_list[i].num_bitfields = 0;
318 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
319 reg_list[i].arch_info = &arch_info[i];
325 int armv4_5_arch_state(struct target_s *target)
327 armv4_5_common_t *armv4_5 = target->arch_info;
329 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
331 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
335 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
336 armv4_5_state_strings[armv4_5->core_state],
337 target_debug_reason_strings[target->debug_reason],
338 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
339 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
340 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
345 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
350 target_t *target = get_current_target(cmd_ctx);
351 armv4_5_common_t *armv4_5 = target->arch_info;
353 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
355 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
359 if (target->state != TARGET_HALTED)
361 command_print(cmd_ctx, "error: target must be halted for register accesses");
365 for (num = 0; num <= 15; num++)
368 for (mode = 0; mode < 6; mode++)
370 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
372 armv4_5->full_context(target);
374 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
375 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
377 command_print(cmd_ctx, output);
379 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",
380 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
381 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
382 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
383 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
384 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
385 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
390 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
392 target_t *target = get_current_target(cmd_ctx);
393 armv4_5_common_t *armv4_5 = target->arch_info;
395 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
397 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
403 if (strcmp(args[0], "arm") == 0)
405 armv4_5->core_state = ARMV4_5_STATE_ARM;
407 if (strcmp(args[0], "thumb") == 0)
409 armv4_5->core_state = ARMV4_5_STATE_THUMB;
413 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
418 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
420 target_t *target = get_current_target(cmd_ctx);
421 armv4_5_common_t *armv4_5 = target->arch_info;
425 arm_instruction_t cur_instruction;
429 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
431 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
437 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
441 address = strtoul(args[0], NULL, 0);
442 count = strtoul(args[1], NULL, 0);
445 if (strcmp(args[2], "thumb") == 0)
448 for (i = 0; i < count; i++)
450 target_read_u32(target, address, &opcode);
451 arm_evaluate_opcode(opcode, address, &cur_instruction);
452 command_print(cmd_ctx, "%s", cur_instruction.text);
453 address += (thumb) ? 2 : 4;
459 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
461 command_t *armv4_5_cmd;
463 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
465 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
466 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
468 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
472 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
474 armv4_5_common_t *armv4_5 = target->arch_info;
478 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
480 for (i = 0; i < 16; i++)
482 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
485 for (i = 16; i < 24; i++)
487 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
490 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
491 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
496 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)
498 armv4_5_common_t *armv4_5 = target->arch_info;
499 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
500 enum armv4_5_state core_state = armv4_5->core_state;
501 enum armv4_5_mode core_mode = armv4_5->core_mode;
504 int exit_breakpoint_size = 0;
506 int retval = ERROR_OK;
507 LOG_DEBUG("Running algorithm");
509 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
511 LOG_ERROR("current target isn't an ARMV4/5 target");
512 return ERROR_TARGET_INVALID;
515 if (target->state != TARGET_HALTED)
517 LOG_WARNING("target not halted");
518 return ERROR_TARGET_NOT_HALTED;
521 for (i = 0; i <= 16; i++)
523 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
524 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
525 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
527 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
529 for (i = 0; i < num_mem_params; i++)
531 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
534 for (i = 0; i < num_reg_params; i++)
536 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
539 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
543 if (reg->size != reg_params[i].size)
545 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
549 armv4_5_set_core_reg(reg, reg_params[i].value);
552 armv4_5->core_state = armv4_5_algorithm_info->core_state;
553 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
554 exit_breakpoint_size = 4;
555 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
556 exit_breakpoint_size = 2;
559 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
563 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
565 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
566 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
567 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
568 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
571 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
573 LOG_ERROR("can't add breakpoint to finish algorithm execution");
574 return ERROR_TARGET_FAILURE;
577 target->type->resume(target, 0, entry_point, 1, 1);
578 target->type->poll(target);
580 while (target->state != TARGET_HALTED)
583 target->type->poll(target);
584 if ((timeout_ms -= 10) <= 0)
586 LOG_ERROR("timeout waiting for algorithm to complete, trying to halt target");
587 target->type->halt(target);
589 while (target->state != TARGET_HALTED)
592 target->type->poll(target);
593 if ((timeout_ms -= 10) <= 0)
595 LOG_ERROR("target didn't reenter debug state, exiting");
599 retval = ERROR_TARGET_TIMEOUT;
603 if ((retval != ERROR_TARGET_TIMEOUT) &&
604 (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point))
606 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
607 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
610 breakpoint_remove(target, exit_point);
612 for (i = 0; i < num_mem_params; i++)
614 if (mem_params[i].direction != PARAM_OUT)
615 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
618 for (i = 0; i < num_reg_params; i++)
620 if (reg_params[i].direction != PARAM_OUT)
623 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
626 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
630 if (reg->size != reg_params[i].size)
632 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
636 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
640 for (i = 0; i <= 16; i++)
642 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]);
643 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
644 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
645 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
647 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
648 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
649 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
651 armv4_5->core_state = core_state;
652 armv4_5->core_mode = core_mode;
657 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
659 target->arch_info = armv4_5;
661 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
662 armv4_5->core_state = ARMV4_5_STATE_ARM;
663 armv4_5->core_mode = ARMV4_5_MODE_USR;