1583e995f63efa78bcef52f8beab6a0017cc428c
[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
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;
183
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);
188
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);
193
194 }
195
196 int armv7a_arch_state(struct target_s *target)
197 {
198 static const char *state[] =
199 {
200 "disabled", "enabled"
201 };
202
203 armv4_5_common_t *armv4_5 = target->arch_info;
204 armv7a_common_t *armv7a = armv4_5->arch_info;
205
206 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
207 {
208 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
209 exit(-1);
210 }
211
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,
218 armv7a_mode_strings[
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]);
228
229 if (armv4_5->core_mode == ARMV7A_MODE_ABT)
230 armv7a_show_fault_registers(target);
231
232 return ERROR_OK;
233 }
234
235
236 static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
237 char *cmd, char **args, int argc)
238 {
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;
243
244 return dap_baseaddr_command(cmd_ctx, swjdp, args, argc);
245 }
246
247 static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
248 char *cmd, char **args, int argc)
249 {
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;
254
255 return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
256 }
257
258 static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
259 char *cmd, char **args, int argc)
260 {
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;
265
266 return dap_apsel_command(cmd_ctx, swjdp, args, argc);
267 }
268
269 static int handle_dap_apid_command(struct command_context_s *cmd_ctx,
270 char *cmd, char **args, int argc)
271 {
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;
276
277 return dap_apid_command(cmd_ctx, swjdp, args, argc);
278 }
279
280 static int handle_dap_info_command(struct command_context_s *cmd_ctx,
281 char *cmd, char **args, int argc)
282 {
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;
287 uint32_t apsel;
288
289 switch (argc) {
290 case 0:
291 apsel = swjdp->apsel;
292 break;
293 case 1:
294 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
295 break;
296 default:
297 return ERROR_COMMAND_SYNTAX_ERROR;
298 }
299
300 return dap_info_command(cmd_ctx, swjdp, apsel);
301 }
302
303 static int
304 handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
305 char *cmd, char **args, int argc)
306 {
307 target_t *target = get_current_target(cmd_ctx);
308 armv4_5_common_t *armv4_5 = target->arch_info;
309 int thumb = 0;
310 int count = 1;
311 uint32_t address;
312 int i;
313
314 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
315 command_print(cmd_ctx, "current target isn't an ARM target");
316 return ERROR_OK;
317 }
318
319 /* REVISIT: eventually support ThumbEE disassembly too;
320 * some opcodes work differently.
321 */
322
323 switch (argc) {
324 case 3:
325 if (strcmp(args[2], "thumb") != 0)
326 goto usage;
327 thumb = 1;
328 /* FALL THROUGH */
329 case 2:
330 COMMAND_PARSE_NUMBER(int, args[1], count);
331 /* FALL THROUGH */
332 case 1:
333 COMMAND_PARSE_NUMBER(u32, args[0], address);
334 if (address & 0x01) {
335 if (!thumb) {
336 command_print(cmd_ctx, "Disassemble as Thumb");
337 thumb = 1;
338 }
339 address &= ~1;
340 }
341 break;
342 default:
343 usage:
344 command_print(cmd_ctx,
345 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
346 return ERROR_OK;
347 }
348
349 for (i = 0; i < count; i++) {
350 arm_instruction_t cur_instruction;
351 int retval;
352
353 if (thumb) {
354 retval = thumb2_opcode(target, address, &cur_instruction);
355 if (retval != ERROR_OK)
356 return retval;
357
358 address += cur_instruction.instruction_size;
359 } else {
360 uint32_t opcode;
361
362 retval = target_read_u32(target, address, &opcode);
363 if (retval != ERROR_OK)
364 return retval;
365
366 retval = arm_evaluate_opcode(opcode, address,
367 &cur_instruction);
368 if (retval != ERROR_OK)
369 return retval;
370
371 address += 4;
372 }
373 command_print(cmd_ctx, "%s", cur_instruction.text);
374 }
375
376 return ERROR_OK;
377 }
378
379 int armv7a_register_commands(struct command_context_s *cmd_ctx)
380 {
381 command_t *arm_adi_v5_dap_cmd;
382 command_t *armv7a_cmd;
383
384 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
385 NULL, COMMAND_ANY,
386 "cortex dap specific commands");
387
388 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
389 handle_dap_info_command, COMMAND_EXEC,
390 "dap info for ap [num], "
391 "default currently selected AP");
392 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
393 handle_dap_apsel_command, COMMAND_EXEC,
394 "select a different AP [num] (default 0)");
395 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
396 handle_dap_apid_command, COMMAND_EXEC,
397 "return id reg from AP [num], "
398 "default currently selected AP");
399 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
400 handle_dap_baseaddr_command, COMMAND_EXEC,
401 "return debug base address from AP [num], "
402 "default currently selected AP");
403 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
404 handle_dap_memaccess_command, COMMAND_EXEC,
405 "set/get number of extra tck for mem-ap memory "
406 "bus access [0-255]");
407
408 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
409 NULL, COMMAND_ANY,
410 "ARMv7-A specific commands");
411
412 register_command(cmd_ctx, armv7a_cmd, "disassemble",
413 handle_armv7a_disassemble_command, COMMAND_EXEC,
414 "disassemble instructions <address> [<count> ['thumb']]");
415
416 return ERROR_OK;
417 }

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)