David Brownell <david-b@pacbell.net>
[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", "System and User", "FIQ", "IRQ",
74 "Supervisor", "Abort", "Undefined", "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 int armv7a_arch_state(struct target_s *target)
177 {
178 static const char *state[] =
179 {
180 "disabled", "enabled"
181 };
182
183 armv4_5_common_t *armv4_5 = target->arch_info;
184 armv7a_common_t *armv7a = armv4_5->arch_info;
185
186 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
187 {
188 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
189 exit(-1);
190 }
191
192 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
193 "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
194 "MMU: %s, D-Cache: %s, I-Cache: %s",
195 armv7a_state_strings[armv4_5->core_state],
196 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
197 target->debug_reason)->name,
198 armv7a_mode_strings[
199 armv7a_mode_to_number(armv4_5->core_mode)],
200 armv7a_core_reg_list[armv7a_core_reg_map[
201 armv7a_mode_to_number(armv4_5->core_mode)][16]],
202 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
203 armv4_5->core_mode, 16).value, 0, 32),
204 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
205 state[armv7a->armv4_5_mmu.mmu_enabled],
206 state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
207 state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
208
209 return ERROR_OK;
210 }
211
212
213 static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
214 char *cmd, char **args, int argc)
215 {
216 target_t *target = get_current_target(cmd_ctx);
217 armv4_5_common_t *armv4_5 = target->arch_info;
218 armv7a_common_t *armv7a = armv4_5->arch_info;
219 swjdp_common_t *swjdp = &armv7a->swjdp_info;
220
221 return dap_baseaddr_command(cmd_ctx, swjdp, args, argc);
222 }
223
224 static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
225 char *cmd, char **args, int argc)
226 {
227 target_t *target = get_current_target(cmd_ctx);
228 armv4_5_common_t *armv4_5 = target->arch_info;
229 armv7a_common_t *armv7a = armv4_5->arch_info;
230 swjdp_common_t *swjdp = &armv7a->swjdp_info;
231
232 return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
233 }
234
235 static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
236 char *cmd, char **args, int argc)
237 {
238 target_t *target = get_current_target(cmd_ctx);
239 armv4_5_common_t *armv4_5 = target->arch_info;
240 armv7a_common_t *armv7a = armv4_5->arch_info;
241 swjdp_common_t *swjdp = &armv7a->swjdp_info;
242
243 return dap_apsel_command(cmd_ctx, swjdp, args, argc);
244 }
245
246 static int handle_dap_apid_command(struct command_context_s *cmd_ctx,
247 char *cmd, char **args, int argc)
248 {
249 target_t *target = get_current_target(cmd_ctx);
250 armv4_5_common_t *armv4_5 = target->arch_info;
251 armv7a_common_t *armv7a = armv4_5->arch_info;
252 swjdp_common_t *swjdp = &armv7a->swjdp_info;
253
254 return dap_apid_command(cmd_ctx, swjdp, args, argc);
255 }
256
257 static int handle_dap_info_command(struct command_context_s *cmd_ctx,
258 char *cmd, char **args, int argc)
259 {
260 target_t *target = get_current_target(cmd_ctx);
261 armv4_5_common_t *armv4_5 = target->arch_info;
262 armv7a_common_t *armv7a = armv4_5->arch_info;
263 swjdp_common_t *swjdp = &armv7a->swjdp_info;
264 uint32_t apsel;
265
266 apsel = swjdp->apsel;
267 if (argc > 0)
268 apsel = strtoul(args[0], NULL, 0);
269
270 return dap_info_command(cmd_ctx, swjdp, apsel);
271 }
272
273 static int
274 handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
275 char *cmd, char **args, int argc)
276 {
277 target_t *target = get_current_target(cmd_ctx);
278 armv4_5_common_t *armv4_5 = target->arch_info;
279 int thumb = 0;
280 int count = 1;
281 uint32_t address;
282 int i;
283
284 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
285 command_print(cmd_ctx, "current target isn't an ARM target");
286 return ERROR_OK;
287 }
288
289 /* REVISIT: eventually support ThumbEE disassembly too;
290 * some opcodes work differently.
291 */
292
293 switch (argc) {
294 case 3:
295 if (strcmp(args[2], "thumb") != 0)
296 goto usage;
297 thumb = 1;
298 /* FALL THROUGH */
299 case 2:
300 count = strtoul(args[1], NULL, 0);
301 /* FALL THROUGH */
302 case 1:
303 address = strtoul(args[0], NULL, 0);
304 if (address & 0x01) {
305 if (!thumb) {
306 command_print(cmd_ctx, "Disassemble as Thumb");
307 thumb = 1;
308 }
309 address &= ~1;
310 }
311 break;
312 default:
313 usage:
314 command_print(cmd_ctx,
315 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
316 return ERROR_OK;
317 }
318
319 for (i = 0; i < count; i++) {
320 arm_instruction_t cur_instruction;
321 int retval;
322
323 if (thumb) {
324 retval = thumb2_opcode(target, address, &cur_instruction);
325 if (retval != ERROR_OK)
326 return retval;
327
328 address += cur_instruction.instruction_size;
329 } else {
330 uint32_t opcode;
331
332 retval = target_read_u32(target, address, &opcode);
333 if (retval != ERROR_OK)
334 return retval;
335
336 retval = arm_evaluate_opcode(opcode, address,
337 &cur_instruction);
338 if (retval != ERROR_OK)
339 return retval;
340
341 address += 4;
342 }
343 command_print(cmd_ctx, "%s", cur_instruction.text);
344 }
345
346 return ERROR_OK;
347 }
348
349 int armv7a_register_commands(struct command_context_s *cmd_ctx)
350 {
351 command_t *arm_adi_v5_dap_cmd;
352 command_t *armv7a_cmd;
353
354 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
355 NULL, COMMAND_ANY,
356 "cortex dap specific commands");
357
358 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
359 handle_dap_info_command, COMMAND_EXEC,
360 "dap info for ap [num], "
361 "default currently selected AP");
362 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
363 handle_dap_apsel_command, COMMAND_EXEC,
364 "select a different AP [num] (default 0)");
365 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
366 handle_dap_apid_command, COMMAND_EXEC,
367 "return id reg from AP [num], "
368 "default currently selected AP");
369 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
370 handle_dap_baseaddr_command, COMMAND_EXEC,
371 "return debug base address from AP [num], "
372 "default currently selected AP");
373 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
374 handle_dap_memaccess_command, COMMAND_EXEC,
375 "set/get number of extra tck for mem-ap memory "
376 "bus access [0-255]");
377
378 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
379 NULL, COMMAND_ANY,
380 "ARMv7-A specific commands");
381
382 register_command(cmd_ctx, armv7a_cmd, "disassemble",
383 handle_armv7a_disassemble_command, COMMAND_EXEC,
384 "disassemble instructions <address> [<count> ['thumb']]");
385
386 return ERROR_OK;
387 }

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)