target: less implicit inclusion of "command.h"
[openocd.git] / src / target / armv7a.c
1 /***************************************************************************
2 * Copyright (C) 2009 by David Brownell *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "replacements.h"
24
25 #include "armv7a.h"
26 #include "arm_disassembler.h"
27
28 #include "target.h"
29 #include "register.h"
30 #include "binarybuffer.h"
31 #include "command.h"
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36
37
38 char* armv7a_core_reg_list[] =
39 {
40 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
41 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
42 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
43 "r13_irq", "lr_irq",
44 "r13_svc", "lr_svc",
45 "r13_abt", "lr_abt",
46 "r13_und", "lr_und",
47 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
48 "r13_mon", "lr_mon", "spsr_mon"
49 };
50
51 char * armv7a_mode_strings_list[] =
52 {
53 "Illegal mode value", "User", "FIQ", "IRQ",
54 "Supervisor", "Abort", "Undefined", "System", "Monitor"
55 };
56
57 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
58 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
59
60 char* armv7a_state_strings[] =
61 {
62 "ARM", "Thumb", "Jazelle", "ThumbEE"
63 };
64
65 struct armv7a_core_reg armv7a_core_reg_list_arch_info[] =
66 {
67 {0, ARMV4_5_MODE_ANY, NULL, NULL},
68 {1, ARMV4_5_MODE_ANY, NULL, NULL},
69 {2, ARMV4_5_MODE_ANY, NULL, NULL},
70 {3, ARMV4_5_MODE_ANY, NULL, NULL},
71 {4, ARMV4_5_MODE_ANY, NULL, NULL},
72 {5, ARMV4_5_MODE_ANY, NULL, NULL},
73 {6, ARMV4_5_MODE_ANY, NULL, NULL},
74 {7, ARMV4_5_MODE_ANY, NULL, NULL},
75 {8, ARMV4_5_MODE_ANY, NULL, NULL},
76 {9, ARMV4_5_MODE_ANY, NULL, NULL},
77 {10, ARMV4_5_MODE_ANY, NULL, NULL},
78 {11, ARMV4_5_MODE_ANY, NULL, NULL},
79 {12, ARMV4_5_MODE_ANY, NULL, NULL},
80 {13, ARMV4_5_MODE_USR, NULL, NULL},
81 {14, ARMV4_5_MODE_USR, NULL, NULL},
82 {15, ARMV4_5_MODE_ANY, NULL, NULL},
83
84 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
85 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
86 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
87 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
88 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
89 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
90 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
91
92 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
93 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
94
95 {13, ARMV4_5_MODE_SVC, NULL, NULL},
96 {14, ARMV4_5_MODE_SVC, NULL, NULL},
97
98 {13, ARMV4_5_MODE_ABT, NULL, NULL},
99 {14, ARMV4_5_MODE_ABT, NULL, NULL},
100
101 {13, ARMV4_5_MODE_UND, NULL, NULL},
102 {14, ARMV4_5_MODE_UND, NULL, NULL},
103
104 {16, ARMV4_5_MODE_ANY, NULL, NULL},
105 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
106 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
107 {16, ARMV4_5_MODE_SVC, NULL, NULL},
108 {16, ARMV4_5_MODE_ABT, NULL, NULL},
109 {16, ARMV4_5_MODE_UND, NULL, NULL},
110
111 {13, ARMV7A_MODE_MON, NULL, NULL},
112 {14, ARMV7A_MODE_MON, NULL, NULL},
113 {16, ARMV7A_MODE_MON, NULL, NULL}
114 };
115
116 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
117 int armv7a_core_reg_map[8][17] =
118 {
119 { /* USR */
120 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
121 },
122 { /* FIQ */
123 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
124 },
125 { /* IRQ */
126 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
127 },
128 { /* SVC */
129 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
130 },
131 { /* ABT */
132 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
133 },
134 { /* UND */
135 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
136 },
137 { /* SYS */
138 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
139 },
140 { /* MON */
141 /* TODO Fix the register mapping for mon, we need r13_mon,
142 * r14_mon and spsr_mon
143 */
144 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
145 }
146 };
147
148 /* FIXME this dummy is IDENTICAL to the armv4_5, arm11, and armv7m
149 * ones... except for naming/scoping
150 */
151 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
152
153 struct reg armv7a_gdb_dummy_fp_reg =
154 {
155 .name = "GDB dummy floating-point register",
156 .value = armv7a_gdb_dummy_fp_value,
157 .dirty = 0,
158 .valid = 1,
159 .size = 96,
160 .arch_info = NULL,
161 .arch_type = 0,
162 };
163
164 void armv7a_show_fault_registers(struct target *target)
165 {
166 uint32_t dfsr, ifsr, dfar, ifar;
167 struct armv7a_common *armv7a = target_to_armv7a(target);
168
169 armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
170 armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
171 armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
172 armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
173
174 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
175 ", DFAR: %8.8" PRIx32, dfsr, dfar);
176 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
177 ", IFAR: %8.8" PRIx32, ifsr, ifar);
178
179 }
180
181 int armv7a_arch_state(struct target *target)
182 {
183 static const char *state[] =
184 {
185 "disabled", "enabled"
186 };
187
188 struct armv7a_common *armv7a = target_to_armv7a(target);
189 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
190
191 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
192 {
193 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
194 exit(-1);
195 }
196
197 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
198 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
199 "MMU: %s, D-Cache: %s, I-Cache: %s",
200 armv7a_state_strings[armv7a->core_state],
201 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
202 target->debug_reason)->name,
203 armv7a_mode_strings[
204 armv7a_mode_to_number(armv4_5->core_mode)],
205 armv7a_core_reg_list[armv7a_core_reg_map[
206 armv7a_mode_to_number(armv4_5->core_mode)][16]],
207 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
208 armv4_5->core_mode, 16).value, 0, 32),
209 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
210 state[armv7a->armv4_5_mmu.mmu_enabled],
211 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
212 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
213
214 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
215 armv7a_show_fault_registers(target);
216
217 return ERROR_OK;
218 }
219
220
221 COMMAND_HANDLER(handle_dap_baseaddr_command)
222 {
223 struct target *target = get_current_target(cmd_ctx);
224 struct armv7a_common *armv7a = target_to_armv7a(target);
225 struct swjdp_common *swjdp = &armv7a->swjdp_info;
226
227 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
228 }
229
230 COMMAND_HANDLER(handle_dap_memaccess_command)
231 {
232 struct target *target = get_current_target(cmd_ctx);
233 struct armv7a_common *armv7a = target_to_armv7a(target);
234 struct swjdp_common *swjdp = &armv7a->swjdp_info;
235
236 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
237 }
238
239 COMMAND_HANDLER(handle_dap_apsel_command)
240 {
241 struct target *target = get_current_target(cmd_ctx);
242 struct armv7a_common *armv7a = target_to_armv7a(target);
243 struct swjdp_common *swjdp = &armv7a->swjdp_info;
244
245 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
246 }
247
248 COMMAND_HANDLER(handle_dap_apid_command)
249 {
250 struct target *target = get_current_target(cmd_ctx);
251 struct armv7a_common *armv7a = target_to_armv7a(target);
252 struct swjdp_common *swjdp = &armv7a->swjdp_info;
253
254 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
255 }
256
257 COMMAND_HANDLER(handle_dap_info_command)
258 {
259 struct target *target = get_current_target(cmd_ctx);
260 struct armv7a_common *armv7a = target_to_armv7a(target);
261 struct swjdp_common *swjdp = &armv7a->swjdp_info;
262 uint32_t apsel;
263
264 switch (argc) {
265 case 0:
266 apsel = swjdp->apsel;
267 break;
268 case 1:
269 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
270 break;
271 default:
272 return ERROR_COMMAND_SYNTAX_ERROR;
273 }
274
275 return dap_info_command(cmd_ctx, swjdp, apsel);
276 }
277
278 COMMAND_HANDLER(handle_armv7a_disassemble_command)
279 {
280 struct target *target = get_current_target(cmd_ctx);
281 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
282 int thumb = 0;
283 int count = 1;
284 uint32_t address;
285 int i;
286
287 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
288 command_print(cmd_ctx, "current target isn't an ARM target");
289 return ERROR_OK;
290 }
291
292 /* REVISIT: eventually support ThumbEE disassembly too;
293 * some opcodes work differently.
294 */
295
296 switch (argc) {
297 case 3:
298 if (strcmp(args[2], "thumb") != 0)
299 goto usage;
300 thumb = 1;
301 /* FALL THROUGH */
302 case 2:
303 COMMAND_PARSE_NUMBER(int, args[1], count);
304 /* FALL THROUGH */
305 case 1:
306 COMMAND_PARSE_NUMBER(u32, args[0], address);
307 if (address & 0x01) {
308 if (!thumb) {
309 command_print(cmd_ctx, "Disassemble as Thumb");
310 thumb = 1;
311 }
312 address &= ~1;
313 }
314 break;
315 default:
316 usage:
317 command_print(cmd_ctx,
318 "usage: armv7a disassemble <address> [<count> ['thumb']]");
319 return ERROR_OK;
320 }
321
322 for (i = 0; i < count; i++) {
323 struct arm_instruction cur_instruction;
324 int retval;
325
326 if (thumb) {
327 retval = thumb2_opcode(target, address, &cur_instruction);
328 if (retval != ERROR_OK)
329 return retval;
330
331 address += cur_instruction.instruction_size;
332 } else {
333 uint32_t opcode;
334
335 retval = target_read_u32(target, address, &opcode);
336 if (retval != ERROR_OK)
337 return retval;
338
339 retval = arm_evaluate_opcode(opcode, address,
340 &cur_instruction);
341 if (retval != ERROR_OK)
342 return retval;
343
344 address += 4;
345 }
346 command_print(cmd_ctx, "%s", cur_instruction.text);
347 }
348
349 return ERROR_OK;
350 }
351
352 int armv7a_register_commands(struct command_context *cmd_ctx)
353 {
354 struct command *arm_adi_v5_dap_cmd;
355 struct command *armv7a_cmd;
356
357 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
358 NULL, COMMAND_ANY,
359 "cortex dap specific commands");
360
361 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
362 handle_dap_info_command, COMMAND_EXEC,
363 "dap info for ap [num], "
364 "default currently selected AP");
365 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
366 handle_dap_apsel_command, COMMAND_EXEC,
367 "select a different AP [num] (default 0)");
368 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
369 handle_dap_apid_command, COMMAND_EXEC,
370 "return id reg from AP [num], "
371 "default currently selected AP");
372 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
373 handle_dap_baseaddr_command, COMMAND_EXEC,
374 "return debug base address from AP [num], "
375 "default currently selected AP");
376 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
377 handle_dap_memaccess_command, COMMAND_EXEC,
378 "set/get number of extra tck for mem-ap memory "
379 "bus access [0-255]");
380
381 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
382 NULL, COMMAND_ANY,
383 "ARMv7-A specific commands");
384
385 register_command(cmd_ctx, armv7a_cmd, "disassemble",
386 handle_armv7a_disassemble_command, COMMAND_EXEC,
387 "disassemble instructions <address> [<count> ['thumb']]");
388
389 return ERROR_OK;
390 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)