1e0e02f189f024fa0e639514de6dc3c32a38f80b
[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 apsel = swjdp->apsel;
290 if (argc > 0)
291 apsel = strtoul(args[0], NULL, 0);
292
293 return dap_info_command(cmd_ctx, swjdp, apsel);
294 }
295
296 static int
297 handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
298 char *cmd, char **args, int argc)
299 {
300 target_t *target = get_current_target(cmd_ctx);
301 armv4_5_common_t *armv4_5 = target->arch_info;
302 int thumb = 0;
303 int count = 1;
304 uint32_t address;
305 int i;
306
307 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
308 command_print(cmd_ctx, "current target isn't an ARM target");
309 return ERROR_OK;
310 }
311
312 /* REVISIT: eventually support ThumbEE disassembly too;
313 * some opcodes work differently.
314 */
315
316 switch (argc) {
317 case 3:
318 if (strcmp(args[2], "thumb") != 0)
319 goto usage;
320 thumb = 1;
321 /* FALL THROUGH */
322 case 2:
323 count = strtoul(args[1], NULL, 0);
324 /* FALL THROUGH */
325 case 1:
326 address = strtoul(args[0], NULL, 0);
327 if (address & 0x01) {
328 if (!thumb) {
329 command_print(cmd_ctx, "Disassemble as Thumb");
330 thumb = 1;
331 }
332 address &= ~1;
333 }
334 break;
335 default:
336 usage:
337 command_print(cmd_ctx,
338 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
339 return ERROR_OK;
340 }
341
342 for (i = 0; i < count; i++) {
343 arm_instruction_t cur_instruction;
344 int retval;
345
346 if (thumb) {
347 retval = thumb2_opcode(target, address, &cur_instruction);
348 if (retval != ERROR_OK)
349 return retval;
350
351 address += cur_instruction.instruction_size;
352 } else {
353 uint32_t opcode;
354
355 retval = target_read_u32(target, address, &opcode);
356 if (retval != ERROR_OK)
357 return retval;
358
359 retval = arm_evaluate_opcode(opcode, address,
360 &cur_instruction);
361 if (retval != ERROR_OK)
362 return retval;
363
364 address += 4;
365 }
366 command_print(cmd_ctx, "%s", cur_instruction.text);
367 }
368
369 return ERROR_OK;
370 }
371
372 int armv7a_register_commands(struct command_context_s *cmd_ctx)
373 {
374 command_t *arm_adi_v5_dap_cmd;
375 command_t *armv7a_cmd;
376
377 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
378 NULL, COMMAND_ANY,
379 "cortex dap specific commands");
380
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]");
400
401 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
402 NULL, COMMAND_ANY,
403 "ARMv7-A specific commands");
404
405 register_command(cmd_ctx, armv7a_cmd, "disassemble",
406 handle_armv7a_disassemble_command, COMMAND_EXEC,
407 "disassemble instructions <address> [<count> ['thumb']]");
408
409 return ERROR_OK;
410 }

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)