#include "target.h" less wildly
[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 "register.h"
29 #include "binarybuffer.h"
30 #include "command.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36
37 char* armv7a_core_reg_list[] =
38 {
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",
42 "r13_irq", "lr_irq",
43 "r13_svc", "lr_svc",
44 "r13_abt", "lr_abt",
45 "r13_und", "lr_und",
46 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
47 "r13_mon", "lr_mon", "spsr_mon"
48 };
49
50 char * armv7a_mode_strings_list[] =
51 {
52 "Illegal mode value", "User", "FIQ", "IRQ",
53 "Supervisor", "Abort", "Undefined", "System", "Monitor"
54 };
55
56 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
57 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
58
59 char* armv7a_state_strings[] =
60 {
61 "ARM", "Thumb", "Jazelle", "ThumbEE"
62 };
63
64 struct armv7a_core_reg armv7a_core_reg_list_arch_info[] =
65 {
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},
82
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},
90
91 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
92 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
93
94 {13, ARMV4_5_MODE_SVC, NULL, NULL},
95 {14, ARMV4_5_MODE_SVC, NULL, NULL},
96
97 {13, ARMV4_5_MODE_ABT, NULL, NULL},
98 {14, ARMV4_5_MODE_ABT, NULL, NULL},
99
100 {13, ARMV4_5_MODE_UND, NULL, NULL},
101 {14, ARMV4_5_MODE_UND, NULL, NULL},
102
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},
109
110 {13, ARMV7A_MODE_MON, NULL, NULL},
111 {14, ARMV7A_MODE_MON, NULL, NULL},
112 {16, ARMV7A_MODE_MON, NULL, NULL}
113 };
114
115 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
116 int armv7a_core_reg_map[8][17] =
117 {
118 { /* USR */
119 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
120 },
121 { /* FIQ */
122 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
123 },
124 { /* IRQ */
125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
126 },
127 { /* SVC */
128 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
129 },
130 { /* ABT */
131 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
132 },
133 { /* UND */
134 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
135 },
136 { /* SYS */
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
138 },
139 { /* MON */
140 /* TODO Fix the register mapping for mon, we need r13_mon,
141 * r14_mon and spsr_mon
142 */
143 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
144 }
145 };
146
147 /* FIXME this dummy is IDENTICAL to the armv4_5, arm11, and armv7m
148 * ones... except for naming/scoping
149 */
150 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
151
152 struct reg armv7a_gdb_dummy_fp_reg =
153 {
154 .name = "GDB dummy floating-point register",
155 .value = armv7a_gdb_dummy_fp_value,
156 .dirty = 0,
157 .valid = 1,
158 .size = 96,
159 .arch_info = NULL,
160 .arch_type = 0,
161 };
162
163 void armv7a_show_fault_registers(struct target *target)
164 {
165 uint32_t dfsr, ifsr, dfar, ifar;
166 struct armv7a_common *armv7a = target_to_armv7a(target);
167
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);
172
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);
177
178 }
179
180 int armv7a_arch_state(struct target *target)
181 {
182 static const char *state[] =
183 {
184 "disabled", "enabled"
185 };
186
187 struct armv7a_common *armv7a = target_to_armv7a(target);
188 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
189
190 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
191 {
192 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
193 exit(-1);
194 }
195
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,
202 armv7a_mode_strings[
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]);
212
213 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
214 armv7a_show_fault_registers(target);
215
216 return ERROR_OK;
217 }
218
219
220 COMMAND_HANDLER(handle_dap_baseaddr_command)
221 {
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;
225
226 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
227 }
228
229 COMMAND_HANDLER(handle_dap_memaccess_command)
230 {
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;
234
235 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
236 }
237
238 COMMAND_HANDLER(handle_dap_apsel_command)
239 {
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;
243
244 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
245 }
246
247 COMMAND_HANDLER(handle_dap_apid_command)
248 {
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;
252
253 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
254 }
255
256 COMMAND_HANDLER(handle_dap_info_command)
257 {
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;
261 uint32_t apsel;
262
263 switch (argc) {
264 case 0:
265 apsel = swjdp->apsel;
266 break;
267 case 1:
268 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
269 break;
270 default:
271 return ERROR_COMMAND_SYNTAX_ERROR;
272 }
273
274 return dap_info_command(cmd_ctx, swjdp, apsel);
275 }
276
277 COMMAND_HANDLER(handle_armv7a_disassemble_command)
278 {
279 struct target *target = get_current_target(cmd_ctx);
280 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
281 int thumb = 0;
282 int count = 1;
283 uint32_t address;
284 int i;
285
286 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
287 command_print(cmd_ctx, "current target isn't an ARM target");
288 return ERROR_OK;
289 }
290
291 /* REVISIT: eventually support ThumbEE disassembly too;
292 * some opcodes work differently.
293 */
294
295 switch (argc) {
296 case 3:
297 if (strcmp(args[2], "thumb") != 0)
298 goto usage;
299 thumb = 1;
300 /* FALL THROUGH */
301 case 2:
302 COMMAND_PARSE_NUMBER(int, args[1], count);
303 /* FALL THROUGH */
304 case 1:
305 COMMAND_PARSE_NUMBER(u32, args[0], address);
306 if (address & 0x01) {
307 if (!thumb) {
308 command_print(cmd_ctx, "Disassemble as Thumb");
309 thumb = 1;
310 }
311 address &= ~1;
312 }
313 break;
314 default:
315 usage:
316 command_print(cmd_ctx,
317 "usage: armv7a disassemble <address> [<count> ['thumb']]");
318 return ERROR_OK;
319 }
320
321 for (i = 0; i < count; i++) {
322 struct arm_instruction cur_instruction;
323 int retval;
324
325 if (thumb) {
326 retval = thumb2_opcode(target, address, &cur_instruction);
327 if (retval != ERROR_OK)
328 return retval;
329
330 address += cur_instruction.instruction_size;
331 } else {
332 uint32_t opcode;
333
334 retval = target_read_u32(target, address, &opcode);
335 if (retval != ERROR_OK)
336 return retval;
337
338 retval = arm_evaluate_opcode(opcode, address,
339 &cur_instruction);
340 if (retval != ERROR_OK)
341 return retval;
342
343 address += 4;
344 }
345 command_print(cmd_ctx, "%s", cur_instruction.text);
346 }
347
348 return ERROR_OK;
349 }
350
351 int armv7a_register_commands(struct command_context *cmd_ctx)
352 {
353 struct command *arm_adi_v5_dap_cmd;
354 struct command *armv7a_cmd;
355
356 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
357 NULL, COMMAND_ANY,
358 "cortex dap specific commands");
359
360 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
361 handle_dap_info_command, COMMAND_EXEC,
362 "dap info for ap [num], "
363 "default currently selected AP");
364 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
365 handle_dap_apsel_command, COMMAND_EXEC,
366 "select a different AP [num] (default 0)");
367 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
368 handle_dap_apid_command, COMMAND_EXEC,
369 "return id reg from AP [num], "
370 "default currently selected AP");
371 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
372 handle_dap_baseaddr_command, COMMAND_EXEC,
373 "return debug base address from AP [num], "
374 "default currently selected AP");
375 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
376 handle_dap_memaccess_command, COMMAND_EXEC,
377 "set/get number of extra tck for mem-ap memory "
378 "bus access [0-255]");
379
380 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
381 NULL, COMMAND_ANY,
382 "ARMv7-A specific commands");
383
384 register_command(cmd_ctx, armv7a_cmd, "disassemble",
385 handle_armv7a_disassemble_command, COMMAND_EXEC,
386 "disassemble instructions <address> [<count> ['thumb']]");
387
388 return ERROR_OK;
389 }

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)