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"
29 #include "binarybuffer.h"
37 char* armv7a_core_reg_list[] =
39 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
40 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
41 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
46 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
47 "r13_mon", "lr_mon", "spsr_mon"
50 char * armv7a_mode_strings_list[] =
52 "Illegal mode value", "User", "FIQ", "IRQ",
53 "Supervisor", "Abort", "Undefined", "System", "Monitor"
56 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
57 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
59 char* armv7a_state_strings[] =
61 "ARM", "Thumb", "Jazelle", "ThumbEE"
64 struct armv7a_core_reg armv7a_core_reg_list_arch_info[] =
66 {0, ARMV4_5_MODE_ANY, NULL, NULL},
67 {1, ARMV4_5_MODE_ANY, NULL, NULL},
68 {2, ARMV4_5_MODE_ANY, NULL, NULL},
69 {3, ARMV4_5_MODE_ANY, NULL, NULL},
70 {4, ARMV4_5_MODE_ANY, NULL, NULL},
71 {5, ARMV4_5_MODE_ANY, NULL, NULL},
72 {6, ARMV4_5_MODE_ANY, NULL, NULL},
73 {7, ARMV4_5_MODE_ANY, NULL, NULL},
74 {8, ARMV4_5_MODE_ANY, NULL, NULL},
75 {9, ARMV4_5_MODE_ANY, NULL, NULL},
76 {10, ARMV4_5_MODE_ANY, NULL, NULL},
77 {11, ARMV4_5_MODE_ANY, NULL, NULL},
78 {12, ARMV4_5_MODE_ANY, NULL, NULL},
79 {13, ARMV4_5_MODE_USR, NULL, NULL},
80 {14, ARMV4_5_MODE_USR, NULL, NULL},
81 {15, ARMV4_5_MODE_ANY, NULL, NULL},
83 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
84 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
85 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
86 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
87 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
88 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
89 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
91 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
92 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
94 {13, ARMV4_5_MODE_SVC, NULL, NULL},
95 {14, ARMV4_5_MODE_SVC, NULL, NULL},
97 {13, ARMV4_5_MODE_ABT, NULL, NULL},
98 {14, ARMV4_5_MODE_ABT, NULL, NULL},
100 {13, ARMV4_5_MODE_UND, NULL, NULL},
101 {14, ARMV4_5_MODE_UND, NULL, NULL},
103 {16, ARMV4_5_MODE_ANY, NULL, NULL},
104 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
105 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
106 {16, ARMV4_5_MODE_SVC, NULL, NULL},
107 {16, ARMV4_5_MODE_ABT, NULL, NULL},
108 {16, ARMV4_5_MODE_UND, NULL, NULL},
110 {13, ARMV7A_MODE_MON, NULL, NULL},
111 {14, ARMV7A_MODE_MON, NULL, NULL},
112 {16, ARMV7A_MODE_MON, NULL, NULL}
115 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
116 int armv7a_core_reg_map[8][17] =
119 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
122 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
128 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
131 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
140 /* TODO Fix the register mapping for mon, we need r13_mon,
141 * r14_mon and spsr_mon
143 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
147 /* FIXME this dummy is IDENTICAL to the armv4_5, arm11, and armv7m
148 * ones... except for naming/scoping
150 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
152 struct reg armv7a_gdb_dummy_fp_reg =
154 .name = "GDB dummy floating-point register",
155 .value = armv7a_gdb_dummy_fp_value,
162 void armv7a_show_fault_registers(struct target *target)
164 uint32_t dfsr, ifsr, dfar, ifar;
165 struct armv7a_common *armv7a = target_to_armv7a(target);
167 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
168 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
169 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
170 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
172 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
173 ", DFAR: %8.8" PRIx32, dfsr, dfar);
174 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
175 ", IFAR: %8.8" PRIx32, ifsr, ifar);
179 int armv7a_arch_state(struct target *target)
181 static const char *state[] =
183 "disabled", "enabled"
186 struct armv7a_common *armv7a = target_to_armv7a(target);
187 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
189 if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
191 LOG_ERROR("BUG: called for a non-ARMv7A target");
192 return ERROR_INVALID_ARGUMENTS;
195 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
196 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
197 "MMU: %s, D-Cache: %s, I-Cache: %s",
198 armv7a_state_strings[armv7a->core_state],
199 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
200 target->debug_reason)->name,
202 armv7a_mode_to_number(armv4_5->core_mode)],
203 armv7a_core_reg_list[armv7a_core_reg_map[
204 armv7a_mode_to_number(armv4_5->core_mode)][16]],
205 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
206 armv4_5->core_mode, 16).value, 0, 32),
207 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
208 state[armv7a->armv4_5_mmu.mmu_enabled],
209 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
210 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
212 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
213 armv7a_show_fault_registers(target);
219 COMMAND_HANDLER(handle_dap_baseaddr_command)
221 struct target *target = get_current_target(cmd_ctx);
222 struct armv7a_common *armv7a = target_to_armv7a(target);
223 struct swjdp_common *swjdp = &armv7a->swjdp_info;
225 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
228 COMMAND_HANDLER(handle_dap_memaccess_command)
230 struct target *target = get_current_target(cmd_ctx);
231 struct armv7a_common *armv7a = target_to_armv7a(target);
232 struct swjdp_common *swjdp = &armv7a->swjdp_info;
234 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
237 COMMAND_HANDLER(handle_dap_apsel_command)
239 struct target *target = get_current_target(cmd_ctx);
240 struct armv7a_common *armv7a = target_to_armv7a(target);
241 struct swjdp_common *swjdp = &armv7a->swjdp_info;
243 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
246 COMMAND_HANDLER(handle_dap_apid_command)
248 struct target *target = get_current_target(cmd_ctx);
249 struct armv7a_common *armv7a = target_to_armv7a(target);
250 struct swjdp_common *swjdp = &armv7a->swjdp_info;
252 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
255 COMMAND_HANDLER(handle_dap_info_command)
257 struct target *target = get_current_target(cmd_ctx);
258 struct armv7a_common *armv7a = target_to_armv7a(target);
259 struct swjdp_common *swjdp = &armv7a->swjdp_info;
264 apsel = swjdp->apsel;
267 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
270 return ERROR_COMMAND_SYNTAX_ERROR;
273 return dap_info_command(cmd_ctx, swjdp, apsel);
276 int armv7a_register_commands(struct command_context *cmd_ctx)
278 struct command *arm_adi_v5_dap_cmd;
280 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
282 "cortex dap specific commands");
284 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
285 handle_dap_info_command, COMMAND_EXEC,
286 "dap info for ap [num], "
287 "default currently selected AP");
288 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
289 handle_dap_apsel_command, COMMAND_EXEC,
290 "select a different AP [num] (default 0)");
291 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
292 handle_dap_apid_command, COMMAND_EXEC,
293 "return id reg from AP [num], "
294 "default currently selected AP");
295 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
296 handle_dap_baseaddr_command, COMMAND_EXEC,
297 "return debug base address from AP [num], "
298 "default currently selected AP");
299 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
300 handle_dap_memaccess_command, COMMAND_EXEC,
301 "set/get number of extra tck for mem-ap memory "
302 "bus access [0-255]");