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 struct bitfield_desc 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 struct armv7a_core_reg 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 *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 *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 COMMAND_HANDLER(handle_dap_baseaddr_command)
235 target_t *target = get_current_target(cmd_ctx);
236 struct armv7a_common *armv7a = target_to_armv7a(target);
237 struct swjdp_common *swjdp = &armv7a->swjdp_info;
239 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
242 COMMAND_HANDLER(handle_dap_memaccess_command)
244 target_t *target = get_current_target(cmd_ctx);
245 struct armv7a_common *armv7a = target_to_armv7a(target);
246 struct swjdp_common *swjdp = &armv7a->swjdp_info;
248 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
251 COMMAND_HANDLER(handle_dap_apsel_command)
253 target_t *target = get_current_target(cmd_ctx);
254 struct armv7a_common *armv7a = target_to_armv7a(target);
255 struct swjdp_common *swjdp = &armv7a->swjdp_info;
257 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
260 COMMAND_HANDLER(handle_dap_apid_command)
262 target_t *target = get_current_target(cmd_ctx);
263 struct armv7a_common *armv7a = target_to_armv7a(target);
264 struct swjdp_common *swjdp = &armv7a->swjdp_info;
266 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
269 COMMAND_HANDLER(handle_dap_info_command)
271 target_t *target = get_current_target(cmd_ctx);
272 struct armv7a_common *armv7a = target_to_armv7a(target);
273 struct swjdp_common *swjdp = &armv7a->swjdp_info;
278 apsel = swjdp->apsel;
281 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
284 return ERROR_COMMAND_SYNTAX_ERROR;
287 return dap_info_command(cmd_ctx, swjdp, apsel);
290 COMMAND_HANDLER(handle_armv7a_disassemble_command)
292 target_t *target = get_current_target(cmd_ctx);
293 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
299 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
300 command_print(cmd_ctx, "current target isn't an ARM target");
304 /* REVISIT: eventually support ThumbEE disassembly too;
305 * some opcodes work differently.
310 if (strcmp(args[2], "thumb") != 0)
315 COMMAND_PARSE_NUMBER(int, args[1], count);
318 COMMAND_PARSE_NUMBER(u32, args[0], address);
319 if (address & 0x01) {
321 command_print(cmd_ctx, "Disassemble as Thumb");
329 command_print(cmd_ctx,
330 "usage: armv7a disassemble <address> [<count> ['thumb']]");
334 for (i = 0; i < count; i++) {
335 struct arm_instruction cur_instruction;
339 retval = thumb2_opcode(target, address, &cur_instruction);
340 if (retval != ERROR_OK)
343 address += cur_instruction.instruction_size;
347 retval = target_read_u32(target, address, &opcode);
348 if (retval != ERROR_OK)
351 retval = arm_evaluate_opcode(opcode, address,
353 if (retval != ERROR_OK)
358 command_print(cmd_ctx, "%s", cur_instruction.text);
364 int armv7a_register_commands(struct command_context_s *cmd_ctx)
366 command_t *arm_adi_v5_dap_cmd;
367 command_t *armv7a_cmd;
369 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
371 "cortex dap specific commands");
373 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
374 handle_dap_info_command, COMMAND_EXEC,
375 "dap info for ap [num], "
376 "default currently selected AP");
377 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
378 handle_dap_apsel_command, COMMAND_EXEC,
379 "select a different AP [num] (default 0)");
380 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
381 handle_dap_apid_command, COMMAND_EXEC,
382 "return id reg from AP [num], "
383 "default currently selected AP");
384 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
385 handle_dap_baseaddr_command, COMMAND_EXEC,
386 "return debug base address from AP [num], "
387 "default currently selected AP");
388 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
389 handle_dap_memaccess_command, COMMAND_EXEC,
390 "set/get number of extra tck for mem-ap memory "
391 "bus access [0-255]");
393 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
395 "ARMv7-A specific commands");
397 register_command(cmd_ctx, armv7a_cmd, "disassemble",
398 handle_armv7a_disassemble_command, COMMAND_EXEC,
399 "disassemble instructions <address> [<count> ['thumb']]");