1 /***************************************************************************
2 * Copyright (C) 2009 by David Brownell *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
23 #include "replacements.h"
26 #include "arm_disassembler.h"
31 #include "binarybuffer.h"
38 bitfield_desc_t armv7a_psr_bitfield_desc[] =
58 char* armv7a_core_reg_list[] =
60 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
61 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
62 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
67 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
68 "r13_mon", "lr_mon", "spsr_mon"
71 char * armv7a_mode_strings_list[] =
73 "Illegal mode value", "User", "FIQ", "IRQ",
74 "Supervisor", "Abort", "Undefined", "System", "Monitor"
77 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
78 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
80 char* armv7a_state_strings[] =
82 "ARM", "Thumb", "Jazelle", "ThumbEE"
85 armv7a_core_reg_t armv7a_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},
131 {13, ARMV7A_MODE_MON, NULL, NULL},
132 {14, ARMV7A_MODE_MON, NULL, NULL},
133 {16, ARMV7A_MODE_MON, NULL, NULL}
136 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
137 int armv7a_core_reg_map[8][17] =
140 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
143 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
146 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
149 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
152 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
155 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
158 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
161 /* TODO Fix the register mapping for mon, we need r13_mon,
162 * r14_mon and spsr_mon
164 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
168 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
170 reg_t armv7a_gdb_dummy_fp_reg =
172 "GDB dummy floating-point register", armv7a_gdb_dummy_fp_value,
173 0, 1, 96, NULL, 0, NULL, 0
176 void armv7a_show_fault_registers(target_t *target)
178 uint32_t dfsr, ifsr, dfar, ifar;
179 struct armv7a_common_s *armv7a = target_to_armv7a(target);
181 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
182 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
183 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
184 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
186 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
187 ", DFAR: %8.8" PRIx32, dfsr, dfar);
188 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
189 ", IFAR: %8.8" PRIx32, ifsr, ifar);
193 int armv7a_arch_state(struct target_s *target)
195 static const char *state[] =
197 "disabled", "enabled"
200 struct armv7a_common_s *armv7a = target_to_armv7a(target);
201 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
203 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
205 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
209 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
210 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
211 "MMU: %s, D-Cache: %s, I-Cache: %s",
212 armv7a_state_strings[armv7a->core_state],
213 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
214 target->debug_reason)->name,
216 armv7a_mode_to_number(armv4_5->core_mode)],
217 armv7a_core_reg_list[armv7a_core_reg_map[
218 armv7a_mode_to_number(armv4_5->core_mode)][16]],
219 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
220 armv4_5->core_mode, 16).value, 0, 32),
221 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
222 state[armv7a->armv4_5_mmu.mmu_enabled],
223 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
224 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
226 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
227 armv7a_show_fault_registers(target);
233 static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
234 char *cmd, char **args, int argc)
236 target_t *target = get_current_target(cmd_ctx);
237 struct armv7a_common_s *armv7a = target_to_armv7a(target);
238 swjdp_common_t *swjdp = &armv7a->swjdp_info;
240 return dap_baseaddr_command(cmd_ctx, swjdp, args, argc);
243 static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
244 char *cmd, char **args, int argc)
246 target_t *target = get_current_target(cmd_ctx);
247 struct armv7a_common_s *armv7a = target_to_armv7a(target);
248 swjdp_common_t *swjdp = &armv7a->swjdp_info;
250 return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
253 static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
254 char *cmd, char **args, int argc)
256 target_t *target = get_current_target(cmd_ctx);
257 struct armv7a_common_s *armv7a = target_to_armv7a(target);
258 swjdp_common_t *swjdp = &armv7a->swjdp_info;
260 return dap_apsel_command(cmd_ctx, swjdp, args, argc);
263 static int handle_dap_apid_command(struct command_context_s *cmd_ctx,
264 char *cmd, char **args, int argc)
266 target_t *target = get_current_target(cmd_ctx);
267 struct armv7a_common_s *armv7a = target_to_armv7a(target);
268 swjdp_common_t *swjdp = &armv7a->swjdp_info;
270 return dap_apid_command(cmd_ctx, swjdp, args, argc);
273 static int handle_dap_info_command(struct command_context_s *cmd_ctx,
274 char *cmd, char **args, int argc)
276 target_t *target = get_current_target(cmd_ctx);
277 struct armv7a_common_s *armv7a = target_to_armv7a(target);
278 swjdp_common_t *swjdp = &armv7a->swjdp_info;
283 apsel = swjdp->apsel;
286 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
289 return ERROR_COMMAND_SYNTAX_ERROR;
292 return dap_info_command(cmd_ctx, swjdp, apsel);
296 handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
297 char *cmd, char **args, int argc)
299 target_t *target = get_current_target(cmd_ctx);
300 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
306 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
307 command_print(cmd_ctx, "current target isn't an ARM target");
311 /* REVISIT: eventually support ThumbEE disassembly too;
312 * some opcodes work differently.
317 if (strcmp(args[2], "thumb") != 0)
322 COMMAND_PARSE_NUMBER(int, args[1], count);
325 COMMAND_PARSE_NUMBER(u32, args[0], address);
326 if (address & 0x01) {
328 command_print(cmd_ctx, "Disassemble as Thumb");
336 command_print(cmd_ctx,
337 "usage: armv7a disassemble <address> [<count> ['thumb']]");
341 for (i = 0; i < count; i++) {
342 arm_instruction_t cur_instruction;
346 retval = thumb2_opcode(target, address, &cur_instruction);
347 if (retval != ERROR_OK)
350 address += cur_instruction.instruction_size;
354 retval = target_read_u32(target, address, &opcode);
355 if (retval != ERROR_OK)
358 retval = arm_evaluate_opcode(opcode, address,
360 if (retval != ERROR_OK)
365 command_print(cmd_ctx, "%s", cur_instruction.text);
371 int armv7a_register_commands(struct command_context_s *cmd_ctx)
373 command_t *arm_adi_v5_dap_cmd;
374 command_t *armv7a_cmd;
376 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
378 "cortex dap specific commands");
380 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
381 handle_dap_info_command, COMMAND_EXEC,
382 "dap info for ap [num], "
383 "default currently selected AP");
384 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
385 handle_dap_apsel_command, COMMAND_EXEC,
386 "select a different AP [num] (default 0)");
387 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
388 handle_dap_apid_command, COMMAND_EXEC,
389 "return id reg from AP [num], "
390 "default currently selected AP");
391 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
392 handle_dap_baseaddr_command, COMMAND_EXEC,
393 "return debug base address from AP [num], "
394 "default currently selected AP");
395 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
396 handle_dap_memaccess_command, COMMAND_EXEC,
397 "set/get number of extra tck for mem-ap memory "
398 "bus access [0-255]");
400 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
402 "ARMv7-A specific commands");
404 register_command(cmd_ctx, armv7a_cmd, "disassemble",
405 handle_armv7a_disassemble_command, COMMAND_EXEC,
406 "disassemble instructions <address> [<count> ['thumb']]");