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

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)