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 16: return 0; break;
178 case 17: return 1; break;
179 case 18: return 2; break;
180 case 19: return 3; break;
181 case 23: return 4; break;
182 case 27: return 5; break;
183 case 31: return 6; break;
184 case -1: return 0; break; /* map MODE_ANY to user mode */
186 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 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, u32 value)
228 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
229 target_t *target = armv4_5->target;
231 if (target->state != TARGET_HALTED)
233 return ERROR_TARGET_NOT_HALTED;
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(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, char *buf, int buf_size)
294 armv4_5_common_t *armv4_5 = target->arch_info;
296 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
298 ERROR("BUG: called for a non-ARMv4/5 target");
302 snprintf(buf, buf_size,
303 "target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
304 armv4_5_state_strings[armv4_5->core_state],
305 target_debug_reason_strings[target->debug_reason],
306 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
307 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
308 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
313 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
318 target_t *target = get_current_target(cmd_ctx);
319 armv4_5_common_t *armv4_5 = target->arch_info;
321 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
323 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
327 if (target->state != TARGET_HALTED)
329 command_print(cmd_ctx, "error: target must be halted for register accesses");
333 for (num = 0; num <= 15; num++)
336 for (mode = 0; mode < 6; mode++)
338 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
340 armv4_5->full_context(target);
342 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
343 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
345 command_print(cmd_ctx, output);
347 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",
348 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
349 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
352 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
353 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
358 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
360 target_t *target = get_current_target(cmd_ctx);
361 armv4_5_common_t *armv4_5 = target->arch_info;
363 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
365 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
371 if (strcmp(args[0], "arm") == 0)
373 armv4_5->core_state = ARMV4_5_STATE_ARM;
375 if (strcmp(args[0], "thumb") == 0)
377 armv4_5->core_state = ARMV4_5_STATE_THUMB;
381 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
386 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
388 target_t *target = get_current_target(cmd_ctx);
389 armv4_5_common_t *armv4_5 = target->arch_info;
393 arm_instruction_t cur_instruction;
397 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
399 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
405 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
409 address = strtoul(args[0], NULL, 0);
410 count = strtoul(args[1], NULL, 0);
413 if (strcmp(args[2], "thumb") == 0)
416 for (i = 0; i < count; i++)
418 target_read_u32(target, address, &opcode);
419 evaluate_opcode(opcode, address, &cur_instruction);
420 command_print(cmd_ctx, "%s", cur_instruction.text);
421 address += (thumb) ? 2 : 4;
427 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
429 command_t *armv4_5_cmd;
431 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
433 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
434 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
436 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
440 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
442 armv4_5_common_t *armv4_5 = target->arch_info;
445 if (target->state != TARGET_HALTED)
447 return ERROR_TARGET_NOT_HALTED;
451 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
453 for (i = 0; i < 16; i++)
455 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
458 for (i = 16; i < 24; i++)
460 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
463 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
464 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
469 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)
471 armv4_5_common_t *armv4_5 = target->arch_info;
472 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
473 enum armv4_5_state core_state = armv4_5->core_state;
474 enum armv4_5_mode core_mode = armv4_5->core_mode;
477 int exit_breakpoint_size = 0;
479 int retval = ERROR_OK;
481 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
483 ERROR("current target isn't an ARMV4/5 target");
484 return ERROR_TARGET_INVALID;
487 if (target->state != TARGET_HALTED)
489 WARNING("target not halted");
490 return ERROR_TARGET_NOT_HALTED;
493 for (i = 0; i <= 16; i++)
495 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
496 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
497 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
499 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
501 for (i = 0; i < num_mem_params; i++)
503 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
506 for (i = 0; i < num_reg_params; i++)
508 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
511 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
515 if (reg->size != reg_params[i].size)
517 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
521 armv4_5_set_core_reg(reg, buf_get_u32(reg_params[i].value, 0, 32));
524 armv4_5->core_state = armv4_5_algorithm_info->core_state;
525 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
526 exit_breakpoint_size = 4;
527 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
528 exit_breakpoint_size = 2;
531 ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
535 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
537 DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
538 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
539 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
540 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
543 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
545 ERROR("can't add breakpoint to finish algorithm execution");
546 return ERROR_TARGET_FAILURE;
549 target->type->resume(target, 0, entry_point, 1, 1);
550 target->type->poll(target);
552 while (target->state != TARGET_HALTED)
555 target->type->poll(target);
556 if ((timeout_ms -= 10) <= 0)
558 ERROR("timeout waiting for algorithm to complete, trying to halt target");
559 target->type->halt(target);
561 while (target->state != TARGET_HALTED)
564 target->type->poll(target);
565 if ((timeout_ms -= 10) <= 0)
567 ERROR("target didn't reenter debug state, exiting");
571 retval = ERROR_TARGET_TIMEOUT;
575 breakpoint_remove(target, exit_point);
577 for (i = 0; i < num_mem_params; i++)
579 if (mem_params[i].direction != PARAM_OUT)
580 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
583 for (i = 0; i < num_reg_params; i++)
585 if (reg_params[i].direction != PARAM_OUT)
588 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
591 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
595 if (reg->size != reg_params[i].size)
597 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
601 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
605 for (i = 0; i <= 16; i++)
607 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, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32));
608 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
609 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
610 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
612 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
613 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
614 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
616 armv4_5->core_state = core_state;
617 armv4_5->core_mode = core_mode;
622 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
624 target->arch_info = armv4_5;
626 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
627 armv4_5->core_state = ARMV4_5_STATE_ARM;
628 armv4_5->core_mode = ARMV4_5_MODE_USR;