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
;
180 /* get pointers to arch-specific information */
181 armv4_5_common_t
*armv4_5
= target
->arch_info
;
182 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
184 armv7a
->read_cp15(target
, 0, 0, 5, 0, &dfsr
);
185 armv7a
->read_cp15(target
, 0, 1, 5, 0, &ifsr
);
186 armv7a
->read_cp15(target
, 0, 0, 6, 0, &dfar
);
187 armv7a
->read_cp15(target
, 0, 2, 6, 0, &ifar
);
189 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
190 ", DFAR: %8.8" PRIx32
, dfsr
, dfar
);
191 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
192 ", IFAR: %8.8" PRIx32
, ifsr
, ifar
);
196 int armv7a_arch_state(struct target_s
*target
)
198 static const char *state
[] =
200 "disabled", "enabled"
203 armv4_5_common_t
*armv4_5
= target
->arch_info
;
204 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
206 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
208 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
212 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
213 "%s: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"\n"
214 "MMU: %s, D-Cache: %s, I-Cache: %s",
215 armv7a_state_strings
[armv7a
->core_state
],
216 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
217 target
->debug_reason
)->name
,
219 armv7a_mode_to_number(armv4_5
->core_mode
)],
220 armv7a_core_reg_list
[armv7a_core_reg_map
[
221 armv7a_mode_to_number(armv4_5
->core_mode
)][16]],
222 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5
->core_cache
,
223 armv4_5
->core_mode
, 16).value
, 0, 32),
224 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32),
225 state
[armv7a
->armv4_5_mmu
.mmu_enabled
],
226 state
[armv7a
->armv4_5_mmu
.armv4_5_cache
.d_u_cache_enabled
],
227 state
[armv7a
->armv4_5_mmu
.armv4_5_cache
.i_cache_enabled
]);
229 if (armv4_5
->core_mode
== ARMV7A_MODE_ABT
)
230 armv7a_show_fault_registers(target
);
236 static int handle_dap_baseaddr_command(struct command_context_s
*cmd_ctx
,
237 char *cmd
, char **args
, int argc
)
239 target_t
*target
= get_current_target(cmd_ctx
);
240 armv4_5_common_t
*armv4_5
= target
->arch_info
;
241 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
242 swjdp_common_t
*swjdp
= &armv7a
->swjdp_info
;
244 return dap_baseaddr_command(cmd_ctx
, swjdp
, args
, argc
);
247 static int handle_dap_memaccess_command(struct command_context_s
*cmd_ctx
,
248 char *cmd
, char **args
, int argc
)
250 target_t
*target
= get_current_target(cmd_ctx
);
251 armv4_5_common_t
*armv4_5
= target
->arch_info
;
252 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
253 swjdp_common_t
*swjdp
= &armv7a
->swjdp_info
;
255 return dap_memaccess_command(cmd_ctx
, swjdp
, args
, argc
);
258 static int handle_dap_apsel_command(struct command_context_s
*cmd_ctx
,
259 char *cmd
, char **args
, int argc
)
261 target_t
*target
= get_current_target(cmd_ctx
);
262 armv4_5_common_t
*armv4_5
= target
->arch_info
;
263 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
264 swjdp_common_t
*swjdp
= &armv7a
->swjdp_info
;
266 return dap_apsel_command(cmd_ctx
, swjdp
, args
, argc
);
269 static int handle_dap_apid_command(struct command_context_s
*cmd_ctx
,
270 char *cmd
, char **args
, int argc
)
272 target_t
*target
= get_current_target(cmd_ctx
);
273 armv4_5_common_t
*armv4_5
= target
->arch_info
;
274 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
275 swjdp_common_t
*swjdp
= &armv7a
->swjdp_info
;
277 return dap_apid_command(cmd_ctx
, swjdp
, args
, argc
);
280 static int handle_dap_info_command(struct command_context_s
*cmd_ctx
,
281 char *cmd
, char **args
, int argc
)
283 target_t
*target
= get_current_target(cmd_ctx
);
284 armv4_5_common_t
*armv4_5
= target
->arch_info
;
285 armv7a_common_t
*armv7a
= armv4_5
->arch_info
;
286 swjdp_common_t
*swjdp
= &armv7a
->swjdp_info
;
289 apsel
= swjdp
->apsel
;
291 apsel
= strtoul(args
[0], NULL
, 0);
293 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
297 handle_armv7a_disassemble_command(struct command_context_s
*cmd_ctx
,
298 char *cmd
, char **args
, int argc
)
300 target_t
*target
= get_current_target(cmd_ctx
);
301 armv4_5_common_t
*armv4_5
= target
->arch_info
;
307 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
) {
308 command_print(cmd_ctx
, "current target isn't an ARM target");
312 /* REVISIT: eventually support ThumbEE disassembly too;
313 * some opcodes work differently.
318 if (strcmp(args
[2], "thumb") != 0)
323 count
= strtoul(args
[1], NULL
, 0);
326 address
= strtoul(args
[0], NULL
, 0);
327 if (address
& 0x01) {
329 command_print(cmd_ctx
, "Disassemble as Thumb");
337 command_print(cmd_ctx
,
338 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
342 for (i
= 0; i
< count
; i
++) {
343 arm_instruction_t cur_instruction
;
347 retval
= thumb2_opcode(target
, address
, &cur_instruction
);
348 if (retval
!= ERROR_OK
)
351 address
+= cur_instruction
.instruction_size
;
355 retval
= target_read_u32(target
, address
, &opcode
);
356 if (retval
!= ERROR_OK
)
359 retval
= arm_evaluate_opcode(opcode
, address
,
361 if (retval
!= ERROR_OK
)
366 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
372 int armv7a_register_commands(struct command_context_s
*cmd_ctx
)
374 command_t
*arm_adi_v5_dap_cmd
;
375 command_t
*armv7a_cmd
;
377 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
379 "cortex dap specific commands");
381 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
382 handle_dap_info_command
, COMMAND_EXEC
,
383 "dap info for ap [num], "
384 "default currently selected AP");
385 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
386 handle_dap_apsel_command
, COMMAND_EXEC
,
387 "select a different AP [num] (default 0)");
388 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
389 handle_dap_apid_command
, COMMAND_EXEC
,
390 "return id reg from AP [num], "
391 "default currently selected AP");
392 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
393 handle_dap_baseaddr_command
, COMMAND_EXEC
,
394 "return debug base address from AP [num], "
395 "default currently selected AP");
396 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
397 handle_dap_memaccess_command
, COMMAND_EXEC
,
398 "set/get number of extra tck for mem-ap memory "
399 "bus access [0-255]");
401 armv7a_cmd
= register_command(cmd_ctx
, NULL
, "armv7a",
403 "ARMv7-A specific commands");
405 register_command(cmd_ctx
, armv7a_cmd
, "disassemble",
406 handle_armv7a_disassemble_command
, COMMAND_EXEC
,
407 "disassemble instructions <address> [<count> ['thumb']]");