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 void armv7a_show_fault_registers(struct target *target)
149 uint32_t dfsr, ifsr, dfar, ifar;
150 struct armv7a_common *armv7a = target_to_armv7a(target);
152 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
153 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
154 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
155 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
157 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
158 ", DFAR: %8.8" PRIx32, dfsr, dfar);
159 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
160 ", IFAR: %8.8" PRIx32, ifsr, ifar);
164 int armv7a_arch_state(struct target *target)
166 static const char *state[] =
168 "disabled", "enabled"
171 struct armv7a_common *armv7a = target_to_armv7a(target);
172 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
174 if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
176 LOG_ERROR("BUG: called for a non-ARMv7A target");
177 return ERROR_INVALID_ARGUMENTS;
180 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
181 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
182 "MMU: %s, D-Cache: %s, I-Cache: %s",
183 armv7a_state_strings[armv7a->core_state],
184 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
185 target->debug_reason)->name,
187 armv7a_mode_to_number(armv4_5->core_mode)],
188 armv7a_core_reg_list[armv7a_core_reg_map[
189 armv7a_mode_to_number(armv4_5->core_mode)][16]],
190 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
191 armv4_5->core_mode, 16).value, 0, 32),
192 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
193 state[armv7a->armv4_5_mmu.mmu_enabled],
194 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
195 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
197 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
198 armv7a_show_fault_registers(target);
204 COMMAND_HANDLER(handle_dap_baseaddr_command)
206 struct target *target = get_current_target(CMD_CTX);
207 struct armv7a_common *armv7a = target_to_armv7a(target);
208 struct swjdp_common *swjdp = &armv7a->swjdp_info;
210 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
213 COMMAND_HANDLER(handle_dap_memaccess_command)
215 struct target *target = get_current_target(CMD_CTX);
216 struct armv7a_common *armv7a = target_to_armv7a(target);
217 struct swjdp_common *swjdp = &armv7a->swjdp_info;
219 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
222 COMMAND_HANDLER(handle_dap_apsel_command)
224 struct target *target = get_current_target(CMD_CTX);
225 struct armv7a_common *armv7a = target_to_armv7a(target);
226 struct swjdp_common *swjdp = &armv7a->swjdp_info;
228 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
231 COMMAND_HANDLER(handle_dap_apid_command)
233 struct target *target = get_current_target(CMD_CTX);
234 struct armv7a_common *armv7a = target_to_armv7a(target);
235 struct swjdp_common *swjdp = &armv7a->swjdp_info;
237 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
240 COMMAND_HANDLER(handle_dap_info_command)
242 struct target *target = get_current_target(CMD_CTX);
243 struct armv7a_common *armv7a = target_to_armv7a(target);
244 struct swjdp_common *swjdp = &armv7a->swjdp_info;
249 apsel = swjdp->apsel;
252 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
255 return ERROR_COMMAND_SYNTAX_ERROR;
258 return dap_info_command(CMD_CTX, swjdp, apsel);
261 int armv7a_register_commands(struct command_context *cmd_ctx)
263 struct command *arm_adi_v5_dap_cmd;
265 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
267 "cortex dap specific commands");
269 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
270 handle_dap_info_command, COMMAND_EXEC,
271 "dap info for ap [num], "
272 "default currently selected AP");
273 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
274 handle_dap_apsel_command, COMMAND_EXEC,
275 "select a different AP [num] (default 0)");
276 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
277 handle_dap_apid_command, COMMAND_EXEC,
278 "return id reg from AP [num], "
279 "default currently selected AP");
280 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
281 handle_dap_baseaddr_command, COMMAND_EXEC,
282 "return debug base address from AP [num], "
283 "default currently selected AP");
284 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
285 handle_dap_memaccess_command, COMMAND_EXEC,
286 "set/get number of extra tck for mem-ap memory "
287 "bus access [0-255]");