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, 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 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 DEBUG("changing to ARM state");
257 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
262 buf_set_u32(reg->value, 0, 32, value);
269 int armv4_5_invalidate_core_regs(target_t *target)
271 armv4_5_common_t *armv4_5 = target->arch_info;
274 for (i = 0; i < 37; i++)
276 armv4_5->core_cache->reg_list[i].valid = 0;
277 armv4_5->core_cache->reg_list[i].dirty = 0;
283 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
286 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
287 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
288 armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
291 cache->name = "arm v4/5 registers";
293 cache->reg_list = reg_list;
294 cache->num_regs = num_regs;
296 if (armv4_5_core_reg_arch_type == -1)
297 armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
299 for (i = 0; i < 37; i++)
301 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
302 arch_info[i].target = target;
303 arch_info[i].armv4_5_common = armv4_5_common;
304 reg_list[i].name = armv4_5_core_reg_list[i];
305 reg_list[i].size = 32;
306 reg_list[i].value = calloc(1, 4);
307 reg_list[i].dirty = 0;
308 reg_list[i].valid = 0;
309 reg_list[i].bitfield_desc = NULL;
310 reg_list[i].num_bitfields = 0;
311 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
312 reg_list[i].arch_info = &arch_info[i];
318 int armv4_5_arch_state(struct target_s *target, char *buf, int buf_size)
320 armv4_5_common_t *armv4_5 = target->arch_info;
322 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
324 ERROR("BUG: called for a non-ARMv4/5 target");
328 snprintf(buf, buf_size,
329 "target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
330 armv4_5_state_strings[armv4_5->core_state],
331 target_debug_reason_strings[target->debug_reason],
332 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
333 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
334 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
339 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
344 target_t *target = get_current_target(cmd_ctx);
345 armv4_5_common_t *armv4_5 = target->arch_info;
347 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
349 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
353 if (target->state != TARGET_HALTED)
355 command_print(cmd_ctx, "error: target must be halted for register accesses");
359 for (num = 0; num <= 15; num++)
362 for (mode = 0; mode < 6; mode++)
364 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
366 armv4_5->full_context(target);
368 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
369 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
371 command_print(cmd_ctx, output);
373 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",
374 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
375 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
376 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
377 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
378 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
379 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
384 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
386 target_t *target = get_current_target(cmd_ctx);
387 armv4_5_common_t *armv4_5 = target->arch_info;
389 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
391 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
397 if (strcmp(args[0], "arm") == 0)
399 armv4_5->core_state = ARMV4_5_STATE_ARM;
401 if (strcmp(args[0], "thumb") == 0)
403 armv4_5->core_state = ARMV4_5_STATE_THUMB;
407 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
412 int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
414 target_t *target = get_current_target(cmd_ctx);
415 armv4_5_common_t *armv4_5 = target->arch_info;
419 arm_instruction_t cur_instruction;
423 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
425 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
431 command_print(cmd_ctx, "usage: armv4_5 disassemble <address> <count> ['thumb']");
435 address = strtoul(args[0], NULL, 0);
436 count = strtoul(args[1], NULL, 0);
439 if (strcmp(args[2], "thumb") == 0)
442 for (i = 0; i < count; i++)
444 target_read_u32(target, address, &opcode);
445 evaluate_opcode(opcode, address, &cur_instruction);
446 command_print(cmd_ctx, "%s", cur_instruction.text);
447 address += (thumb) ? 2 : 4;
453 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
455 command_t *armv4_5_cmd;
457 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
459 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
460 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
462 register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions <address> <count> ['thumb']");
466 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
468 armv4_5_common_t *armv4_5 = target->arch_info;
471 if (target->state != TARGET_HALTED)
473 return ERROR_TARGET_NOT_HALTED;
477 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
479 for (i = 0; i < 16; i++)
481 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
484 for (i = 16; i < 24; i++)
486 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
489 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
490 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
495 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)
497 armv4_5_common_t *armv4_5 = target->arch_info;
498 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
499 enum armv4_5_state core_state = armv4_5->core_state;
500 enum armv4_5_mode core_mode = armv4_5->core_mode;
503 int exit_breakpoint_size = 0;
505 int retval = ERROR_OK;
507 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
509 ERROR("current target isn't an ARMV4/5 target");
510 return ERROR_TARGET_INVALID;
513 if (target->state != TARGET_HALTED)
515 WARNING("target not halted");
516 return ERROR_TARGET_NOT_HALTED;
519 for (i = 0; i <= 16; i++)
521 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
522 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
523 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
525 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
527 for (i = 0; i < num_mem_params; i++)
529 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
532 for (i = 0; i < num_reg_params; i++)
534 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
537 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
541 if (reg->size != reg_params[i].size)
543 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
547 armv4_5_set_core_reg(reg, reg_params[i].value);
550 armv4_5->core_state = armv4_5_algorithm_info->core_state;
551 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
552 exit_breakpoint_size = 4;
553 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
554 exit_breakpoint_size = 2;
557 ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
561 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
563 DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
564 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
565 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
566 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
569 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
571 ERROR("can't add breakpoint to finish algorithm execution");
572 return ERROR_TARGET_FAILURE;
575 target->type->resume(target, 0, entry_point, 1, 1);
576 target->type->poll(target);
578 while (target->state != TARGET_HALTED)
581 target->type->poll(target);
582 if ((timeout_ms -= 10) <= 0)
584 ERROR("timeout waiting for algorithm to complete, trying to halt target");
585 target->type->halt(target);
587 while (target->state != TARGET_HALTED)
590 target->type->poll(target);
591 if ((timeout_ms -= 10) <= 0)
593 ERROR("target didn't reenter debug state, exiting");
597 retval = ERROR_TARGET_TIMEOUT;
601 breakpoint_remove(target, exit_point);
603 for (i = 0; i < num_mem_params; i++)
605 if (mem_params[i].direction != PARAM_OUT)
606 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
609 for (i = 0; i < num_reg_params; i++)
611 if (reg_params[i].direction != PARAM_OUT)
614 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
617 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
621 if (reg->size != reg_params[i].size)
623 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
627 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
631 for (i = 0; i <= 16; i++)
633 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]);
634 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
635 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
636 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
638 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
639 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
640 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
642 armv4_5->core_state = core_state;
643 armv4_5->core_mode = core_mode;
648 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
650 target->arch_info = armv4_5;
652 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
653 armv4_5->core_state = ARMV4_5_STATE_ARM;
654 armv4_5->core_mode = ARMV4_5_MODE_USR;