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,
163 void armv7a_show_fault_registers(struct target *target)
165 uint32_t dfsr, ifsr, dfar, ifar;
166 struct armv7a_common *armv7a = target_to_armv7a(target);
168 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
169 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
170 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
171 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
173 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
174 ", DFAR: %8.8" PRIx32, dfsr, dfar);
175 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
176 ", IFAR: %8.8" PRIx32, ifsr, ifar);
180 int armv7a_arch_state(struct target *target)
182 static const char *state[] =
184 "disabled", "enabled"
187 struct armv7a_common *armv7a = target_to_armv7a(target);
188 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
190 if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
192 LOG_ERROR("BUG: called for a non-ARMv7A target");
193 return ERROR_INVALID_ARGUMENTS;
196 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
197 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
198 "MMU: %s, D-Cache: %s, I-Cache: %s",
199 armv7a_state_strings[armv7a->core_state],
200 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
201 target->debug_reason)->name,
203 armv7a_mode_to_number(armv4_5->core_mode)],
204 armv7a_core_reg_list[armv7a_core_reg_map[
205 armv7a_mode_to_number(armv4_5->core_mode)][16]],
206 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
207 armv4_5->core_mode, 16).value, 0, 32),
208 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
209 state[armv7a->armv4_5_mmu.mmu_enabled],
210 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
211 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
213 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
214 armv7a_show_fault_registers(target);
220 COMMAND_HANDLER(handle_dap_baseaddr_command)
222 struct target *target = get_current_target(cmd_ctx);
223 struct armv7a_common *armv7a = target_to_armv7a(target);
224 struct swjdp_common *swjdp = &armv7a->swjdp_info;
226 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
229 COMMAND_HANDLER(handle_dap_memaccess_command)
231 struct target *target = get_current_target(cmd_ctx);
232 struct armv7a_common *armv7a = target_to_armv7a(target);
233 struct swjdp_common *swjdp = &armv7a->swjdp_info;
235 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
238 COMMAND_HANDLER(handle_dap_apsel_command)
240 struct target *target = get_current_target(cmd_ctx);
241 struct armv7a_common *armv7a = target_to_armv7a(target);
242 struct swjdp_common *swjdp = &armv7a->swjdp_info;
244 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
247 COMMAND_HANDLER(handle_dap_apid_command)
249 struct target *target = get_current_target(cmd_ctx);
250 struct armv7a_common *armv7a = target_to_armv7a(target);
251 struct swjdp_common *swjdp = &armv7a->swjdp_info;
253 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
256 COMMAND_HANDLER(handle_dap_info_command)
258 struct target *target = get_current_target(cmd_ctx);
259 struct armv7a_common *armv7a = target_to_armv7a(target);
260 struct swjdp_common *swjdp = &armv7a->swjdp_info;
265 apsel = swjdp->apsel;
268 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
271 return ERROR_COMMAND_SYNTAX_ERROR;
274 return dap_info_command(cmd_ctx, swjdp, apsel);
277 int armv7a_register_commands(struct command_context *cmd_ctx)
279 struct command *arm_adi_v5_dap_cmd;
281 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
283 "cortex dap specific commands");
285 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
286 handle_dap_info_command, COMMAND_EXEC,
287 "dap info for ap [num], "
288 "default currently selected AP");
289 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
290 handle_dap_apsel_command, COMMAND_EXEC,
291 "select a different AP [num] (default 0)");
292 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
293 handle_dap_apid_command, COMMAND_EXEC,
294 "return id reg from AP [num], "
295 "default currently selected AP");
296 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
297 handle_dap_baseaddr_command, COMMAND_EXEC,
298 "return debug base address from AP [num], "
299 "default currently selected AP");
300 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
301 handle_dap_memaccess_command, COMMAND_EXEC,
302 "set/get number of extra tck for mem-ap memory "
303 "bus access [0-255]");