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 ***************************************************************************/
22 #include "arm_disassembler.h"
29 #include "binarybuffer.h"
36 bitfield_desc_t armv4_5_psr_bitfield_desc[] =
52 char* armv4_5_core_reg_list[] =
54 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
56 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
66 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
69 char* armv4_5_mode_strings[] =
71 "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
74 char* armv4_5_state_strings[] =
76 "ARM", "Thumb", "Jazelle"
79 int armv4_5_core_reg_arch_type = -1;
81 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
83 {0, ARMV4_5_MODE_ANY, NULL, NULL},
84 {1, ARMV4_5_MODE_ANY, NULL, NULL},
85 {2, ARMV4_5_MODE_ANY, NULL, NULL},
86 {3, ARMV4_5_MODE_ANY, NULL, NULL},
87 {4, ARMV4_5_MODE_ANY, NULL, NULL},
88 {5, ARMV4_5_MODE_ANY, NULL, NULL},
89 {6, ARMV4_5_MODE_ANY, NULL, NULL},
90 {7, ARMV4_5_MODE_ANY, NULL, NULL},
91 {8, ARMV4_5_MODE_ANY, NULL, NULL},
92 {9, ARMV4_5_MODE_ANY, NULL, NULL},
93 {10, ARMV4_5_MODE_ANY, NULL, NULL},
94 {11, ARMV4_5_MODE_ANY, NULL, NULL},
95 {12, ARMV4_5_MODE_ANY, NULL, NULL},
96 {13, ARMV4_5_MODE_USR, NULL, NULL},
97 {14, ARMV4_5_MODE_USR, NULL, NULL},
98 {15, ARMV4_5_MODE_ANY, NULL, NULL},
100 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
101 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
102 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
103 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
104 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
105 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
106 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
108 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
109 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
111 {13, ARMV4_5_MODE_SVC, NULL, NULL},
112 {14, ARMV4_5_MODE_SVC, NULL, NULL},
114 {13, ARMV4_5_MODE_ABT, NULL, NULL},
115 {14, ARMV4_5_MODE_ABT, NULL, NULL},
117 {13, ARMV4_5_MODE_UND, NULL, NULL},
118 {14, ARMV4_5_MODE_UND, NULL, NULL},
120 {16, ARMV4_5_MODE_ANY, NULL, NULL},
121 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
122 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
123 {16, ARMV4_5_MODE_SVC, NULL, NULL},
124 {16, ARMV4_5_MODE_ABT, NULL, NULL},
125 {16, ARMV4_5_MODE_UND, NULL, NULL}
128 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
129 int armv4_5_core_reg_map[7][17] =
132 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
135 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
138 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
141 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
144 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
147 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
150 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
154 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
156 reg_t armv4_5_gdb_dummy_fp_reg =
158 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
161 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
163 reg_t armv4_5_gdb_dummy_fps_reg =
165 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
168 /* map psr mode bits to linear number */
169 int armv4_5_mode_to_number(enum armv4_5_mode mode)
173 case 16: return 0; break;
174 case 17: return 1; break;
175 case 18: return 2; break;
176 case 19: return 3; break;
177 case 23: return 4; break;
178 case 27: return 5; break;
179 case 31: return 6; break;
180 case -1: return 0; break; /* map MODE_ANY to user mode */
182 ERROR("invalid mode value encountered");
187 /* map linear number to mode bits */
188 enum armv4_5_mode armv4_5_number_to_mode(int number)
192 case 0: return ARMV4_5_MODE_USR; break;
193 case 1: return ARMV4_5_MODE_FIQ; break;
194 case 2: return ARMV4_5_MODE_IRQ; break;
195 case 3: return ARMV4_5_MODE_SVC; break;
196 case 4: return ARMV4_5_MODE_ABT; break;
197 case 5: return ARMV4_5_MODE_UND; break;
198 case 6: return ARMV4_5_MODE_SYS; break;
200 ERROR("mode index out of bounds");
205 int armv4_5_get_core_reg(reg_t *reg)
208 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
209 target_t *target = armv4_5->target;
211 if (target->state != TARGET_HALTED)
213 return ERROR_TARGET_NOT_HALTED;
216 //retval = armv4_5->armv4_5_common->full_context(target);
217 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
222 int armv4_5_set_core_reg(reg_t *reg, u32 value)
224 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
225 target_t *target = armv4_5->target;
227 if (target->state != TARGET_HALTED)
229 return ERROR_TARGET_NOT_HALTED;
232 buf_set_u32(reg->value, 0, 32, value);
239 int armv4_5_invalidate_core_regs(target_t *target)
241 armv4_5_common_t *armv4_5 = target->arch_info;
244 for (i = 0; i < 37; i++)
246 armv4_5->core_cache->reg_list[i].valid = 0;
247 armv4_5->core_cache->reg_list[i].dirty = 0;
253 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
256 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
257 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
258 armv4_5_core_reg_t *arch_info = malloc(sizeof(reg_t) * num_regs);
261 cache->name = "arm v4/5 registers";
263 cache->reg_list = reg_list;
264 cache->num_regs = num_regs;
266 if (armv4_5_core_reg_arch_type == -1)
267 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
269 for (i = 0; i < 37; i++)
271 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
272 arch_info[i].target = target;
273 arch_info[i].armv4_5_common = armv4_5_common;
274 reg_list[i].name = armv4_5_core_reg_list[i];
275 reg_list[i].size = 32;
276 reg_list[i].value = calloc(1, 4);
277 reg_list[i].dirty = 0;
278 reg_list[i].valid = 0;
279 reg_list[i].bitfield_desc = NULL;
280 reg_list[i].num_bitfields = 0;
281 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
282 reg_list[i].arch_info = &arch_info[i];
288 int armv4_5_arch_state(struct target_s *target, char *buf, int buf_size)
290 armv4_5_common_t *armv4_5 = target->arch_info;
292 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
294 ERROR("BUG: called for a non-ARMv4/5 target");
298 snprintf(buf, buf_size,
299 "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->type->read_memory(target, address, 4, 1, (u8*)&opcode);
415 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, NULL);
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;
441 if (target->state != TARGET_HALTED)
443 return ERROR_TARGET_NOT_HALTED;
447 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
449 for (i = 0; i < 16; i++)
451 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
454 for (i = 16; i < 24; i++)
456 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
459 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
460 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
465 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)
467 armv4_5_common_t *armv4_5 = target->arch_info;
468 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
469 enum armv4_5_state core_state = armv4_5->core_state;
470 enum armv4_5_mode core_mode = armv4_5->core_mode;
473 int exit_breakpoint_size = 0;
475 int retval = ERROR_OK;
477 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
479 ERROR("current target isn't an ARMV4/5 target");
480 return ERROR_TARGET_INVALID;
483 if (target->state != TARGET_HALTED)
485 WARNING("target not halted");
486 return ERROR_TARGET_NOT_HALTED;
489 for (i = 0; i <= 16; i++)
491 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
492 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
493 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
495 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
497 for (i = 0; i < num_mem_params; i++)
499 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
502 for (i = 0; i < num_reg_params; i++)
504 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
507 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
511 if (reg->size != reg_params[i].size)
513 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
517 armv4_5_set_core_reg(reg, buf_get_u32(reg_params[i].value, 0, 32));
520 armv4_5->core_state = armv4_5_algorithm_info->core_state;
521 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
522 exit_breakpoint_size = 4;
523 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
524 exit_breakpoint_size = 2;
527 ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
531 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
533 DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
534 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
535 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
536 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
539 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
541 ERROR("can't add breakpoint to finish algorithm execution");
542 return ERROR_TARGET_FAILURE;
545 target->type->resume(target, 0, entry_point, 1, 1);
546 target->type->poll(target);
548 while (target->state != TARGET_HALTED)
551 target->type->poll(target);
552 if ((timeout_ms -= 10) <= 0)
554 ERROR("timeout waiting for algorithm to complete, trying to halt target");
555 target->type->halt(target);
557 while (target->state != TARGET_HALTED)
560 target->type->poll(target);
561 if ((timeout_ms -= 10) <= 0)
563 ERROR("target didn't reenter debug state, exiting");
567 retval = ERROR_TARGET_TIMEOUT;
571 breakpoint_remove(target, exit_point);
573 for (i = 0; i < num_mem_params; i++)
575 if (mem_params[i].direction != PARAM_OUT)
576 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
579 for (i = 0; i < num_reg_params; i++)
581 if (reg_params[i].direction != PARAM_OUT)
584 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
587 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
591 if (reg->size != reg_params[i].size)
593 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
597 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
601 for (i = 0; i <= 16; i++)
603 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));
604 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
605 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
606 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
608 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
609 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
610 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
612 armv4_5->core_state = core_state;
613 armv4_5->core_mode = core_mode;
618 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
620 target->arch_info = armv4_5;
622 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
623 armv4_5->core_state = ARMV4_5_STATE_ARM;
624 armv4_5->core_mode = ARMV4_5_MODE_USR;