Cortex-A8: use the new inheritance/nesting scheme
[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 "log.h"
31 #include "binarybuffer.h"
32 #include "command.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 bitfield_desc_t armv7a_psr_bitfield_desc[] =
39 {
40 {"M[4:0]", 5},
41 {"T", 1},
42 {"F", 1},
43 {"I", 1},
44 {"A", 1},
45 {"E", 1},
46 {"IT[7:2]", 6},
47 {"GE[3:0]", 4},
48 {"reserved(DNM)", 4},
49 {"J", 1},
50 {"IT[0:1]", 2},
51 {"Q", 1},
52 {"V", 1},
53 {"C", 1},
54 {"Z", 1},
55 {"N", 1},
56 };
57
58 char* armv7a_core_reg_list[] =
59 {
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",
63 "r13_irq", "lr_irq",
64 "r13_svc", "lr_svc",
65 "r13_abt", "lr_abt",
66 "r13_und", "lr_und",
67 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
68 "r13_mon", "lr_mon", "spsr_mon"
69 };
70
71 char * armv7a_mode_strings_list[] =
72 {
73 "Illegal mode value", "User", "FIQ", "IRQ",
74 "Supervisor", "Abort", "Undefined", "System", "Monitor"
75 };
76
77 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
78 char** armv7a_mode_strings = armv7a_mode_strings_list+1;
79
80 char* armv7a_state_strings[] =
81 {
82 "ARM", "Thumb", "Jazelle", "ThumbEE"
83 };
84
85 armv7a_core_reg_t armv7a_core_reg_list_arch_info[] =
86 {
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},
103
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},
111
112 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
113 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
114
115 {13, ARMV4_5_MODE_SVC, NULL, NULL},
116 {14, ARMV4_5_MODE_SVC, NULL, NULL},
117
118 {13, ARMV4_5_MODE_ABT, NULL, NULL},
119 {14, ARMV4_5_MODE_ABT, NULL, NULL},
120
121 {13, ARMV4_5_MODE_UND, NULL, NULL},
122 {14, ARMV4_5_MODE_UND, NULL, NULL},
123
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},
130
131 {13, ARMV7A_MODE_MON, NULL, NULL},
132 {14, ARMV7A_MODE_MON, NULL, NULL},
133 {16, ARMV7A_MODE_MON, NULL, NULL}
134 };
135
136 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
137 int armv7a_core_reg_map[8][17] =
138 {
139 { /* USR */
140 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
141 },
142 { /* FIQ */
143 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
144 },
145 { /* IRQ */
146 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
147 },
148 { /* SVC */
149 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
150 },
151 { /* ABT */
152 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
153 },
154 { /* UND */
155 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
156 },
157 { /* SYS */
158 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
159 },
160 { /* MON */
161 /* TODO Fix the register mapping for mon, we need r13_mon,
162 * r14_mon and spsr_mon
163 */
164 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
165 }
166 };
167
168 uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
169
170 reg_t armv7a_gdb_dummy_fp_reg =
171 {
172 "GDB dummy floating-point register", armv7a_gdb_dummy_fp_value,
173 0, 1, 96, NULL, 0, NULL, 0
174 };
175
176 void armv7a_show_fault_registers(target_t *target)
177 {
178 uint32_t dfsr, ifsr, dfar, ifar;
179 struct armv7a_common_s *armv7a = target_to_armv7a(target);
180
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);
185
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);
190
191 }
192
193 int armv7a_arch_state(struct target_s *target)
194 {
195 static const char *state[] =
196 {
197 "disabled", "enabled"
198 };
199
200 struct armv7a_common_s *armv7a = target_to_armv7a(target);
201 struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
202
203 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
204 {
205 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
206 exit(-1);
207 }
208
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,
215 armv7a_mode_strings[
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]);
225
226 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
227 armv7a_show_fault_registers(target);
228
229 return ERROR_OK;
230 }
231
232
233 static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
234 char *cmd, char **args, int argc)
235 {
236 target_t *target = get_current_target(cmd_ctx);
237 struct armv7a_common_s *armv7a = target_to_armv7a(target);
238 swjdp_common_t *swjdp = &armv7a->swjdp_info;
239
240 return dap_baseaddr_command(cmd_ctx, swjdp, args, argc);
241 }
242
243 static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
244 char *cmd, char **args, int argc)
245 {
246 target_t *target = get_current_target(cmd_ctx);
247 struct armv7a_common_s *armv7a = target_to_armv7a(target);
248 swjdp_common_t *swjdp = &armv7a->swjdp_info;
249
250 return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
251 }
252
253 static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
254 char *cmd, char **args, int argc)
255 {
256 target_t *target = get_current_target(cmd_ctx);
257 struct armv7a_common_s *armv7a = target_to_armv7a(target);
258 swjdp_common_t *swjdp = &armv7a->swjdp_info;
259
260 return dap_apsel_command(cmd_ctx, swjdp, args, argc);
261 }
262
263 static int handle_dap_apid_command(struct command_context_s *cmd_ctx,
264 char *cmd, char **args, int argc)
265 {
266 target_t *target = get_current_target(cmd_ctx);
267 struct armv7a_common_s *armv7a = target_to_armv7a(target);
268 swjdp_common_t *swjdp = &armv7a->swjdp_info;
269
270 return dap_apid_command(cmd_ctx, swjdp, args, argc);
271 }
272
273 static int handle_dap_info_command(struct command_context_s *cmd_ctx,
274 char *cmd, char **args, int argc)
275 {
276 target_t *target = get_current_target(cmd_ctx);
277 struct armv7a_common_s *armv7a = target_to_armv7a(target);
278 swjdp_common_t *swjdp = &armv7a->swjdp_info;
279 uint32_t apsel;
280
281 switch (argc) {
282 case 0:
283 apsel = swjdp->apsel;
284 break;
285 case 1:
286 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
287 break;
288 default:
289 return ERROR_COMMAND_SYNTAX_ERROR;
290 }
291
292 return dap_info_command(cmd_ctx, swjdp, apsel);
293 }
294
295 static int
296 handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
297 char *cmd, char **args, int argc)
298 {
299 target_t *target = get_current_target(cmd_ctx);
300 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
301 int thumb = 0;
302 int count = 1;
303 uint32_t address;
304 int i;
305
306 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
307 command_print(cmd_ctx, "current target isn't an ARM target");
308 return ERROR_OK;
309 }
310
311 /* REVISIT: eventually support ThumbEE disassembly too;
312 * some opcodes work differently.
313 */
314
315 switch (argc) {
316 case 3:
317 if (strcmp(args[2], "thumb") != 0)
318 goto usage;
319 thumb = 1;
320 /* FALL THROUGH */
321 case 2:
322 COMMAND_PARSE_NUMBER(int, args[1], count);
323 /* FALL THROUGH */
324 case 1:
325 COMMAND_PARSE_NUMBER(u32, args[0], address);
326 if (address & 0x01) {
327 if (!thumb) {
328 command_print(cmd_ctx, "Disassemble as Thumb");
329 thumb = 1;
330 }
331 address &= ~1;
332 }
333 break;
334 default:
335 usage:
336 command_print(cmd_ctx,
337 "usage: armv7a disassemble <address> [<count> ['thumb']]");
338 return ERROR_OK;
339 }
340
341 for (i = 0; i < count; i++) {
342 arm_instruction_t cur_instruction;
343 int retval;
344
345 if (thumb) {
346 retval = thumb2_opcode(target, address, &cur_instruction);
347 if (retval != ERROR_OK)
348 return retval;
349
350 address += cur_instruction.instruction_size;
351 } else {
352 uint32_t opcode;
353
354 retval = target_read_u32(target, address, &opcode);
355 if (retval != ERROR_OK)
356 return retval;
357
358 retval = arm_evaluate_opcode(opcode, address,
359 &cur_instruction);
360 if (retval != ERROR_OK)
361 return retval;
362
363 address += 4;
364 }
365 command_print(cmd_ctx, "%s", cur_instruction.text);
366 }
367
368 return ERROR_OK;
369 }
370
371 int armv7a_register_commands(struct command_context_s *cmd_ctx)
372 {
373 command_t *arm_adi_v5_dap_cmd;
374 command_t *armv7a_cmd;
375
376 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
377 NULL, COMMAND_ANY,
378 "cortex dap specific commands");
379
380 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
381 handle_dap_info_command, COMMAND_EXEC,
382 "dap info for ap [num], "
383 "default currently selected AP");
384 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
385 handle_dap_apsel_command, COMMAND_EXEC,
386 "select a different AP [num] (default 0)");
387 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
388 handle_dap_apid_command, COMMAND_EXEC,
389 "return id reg from AP [num], "
390 "default currently selected AP");
391 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
392 handle_dap_baseaddr_command, COMMAND_EXEC,
393 "return debug base address from AP [num], "
394 "default currently selected AP");
395 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
396 handle_dap_memaccess_command, COMMAND_EXEC,
397 "set/get number of extra tck for mem-ap memory "
398 "bus access [0-255]");
399
400 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
401 NULL, COMMAND_ANY,
402 "ARMv7-A specific commands");
403
404 register_command(cmd_ctx, armv7a_cmd, "disassemble",
405 handle_armv7a_disassemble_command, COMMAND_EXEC,
406 "disassemble instructions <address> [<count> ['thumb']]");
407
408 return ERROR_OK;
409 }

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)