target_t -> struct target
[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 struct bitfield_desc 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 struct armv7a_core_reg 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 struct reg 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(struct target *target)
177 {
178 uint32_t dfsr, ifsr, dfar, ifar;
179 struct armv7a_common *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 *target)
194 {
195 static const char *state[] =
196 {
197 "disabled", "enabled"
198 };
199
200 struct armv7a_common *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 COMMAND_HANDLER(handle_dap_baseaddr_command)
234 {
235 struct target *target = get_current_target(cmd_ctx);
236 struct armv7a_common *armv7a = target_to_armv7a(target);
237 struct swjdp_common *swjdp = &armv7a->swjdp_info;
238
239 return CALL_COMMAND_HANDLER(dap_baseaddr_command, swjdp);
240 }
241
242 COMMAND_HANDLER(handle_dap_memaccess_command)
243 {
244 struct target *target = get_current_target(cmd_ctx);
245 struct armv7a_common *armv7a = target_to_armv7a(target);
246 struct swjdp_common *swjdp = &armv7a->swjdp_info;
247
248 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
249 }
250
251 COMMAND_HANDLER(handle_dap_apsel_command)
252 {
253 struct target *target = get_current_target(cmd_ctx);
254 struct armv7a_common *armv7a = target_to_armv7a(target);
255 struct swjdp_common *swjdp = &armv7a->swjdp_info;
256
257 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
258 }
259
260 COMMAND_HANDLER(handle_dap_apid_command)
261 {
262 struct target *target = get_current_target(cmd_ctx);
263 struct armv7a_common *armv7a = target_to_armv7a(target);
264 struct swjdp_common *swjdp = &armv7a->swjdp_info;
265
266 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
267 }
268
269 COMMAND_HANDLER(handle_dap_info_command)
270 {
271 struct target *target = get_current_target(cmd_ctx);
272 struct armv7a_common *armv7a = target_to_armv7a(target);
273 struct swjdp_common *swjdp = &armv7a->swjdp_info;
274 uint32_t apsel;
275
276 switch (argc) {
277 case 0:
278 apsel = swjdp->apsel;
279 break;
280 case 1:
281 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
282 break;
283 default:
284 return ERROR_COMMAND_SYNTAX_ERROR;
285 }
286
287 return dap_info_command(cmd_ctx, swjdp, apsel);
288 }
289
290 COMMAND_HANDLER(handle_armv7a_disassemble_command)
291 {
292 struct target *target = get_current_target(cmd_ctx);
293 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
294 int thumb = 0;
295 int count = 1;
296 uint32_t address;
297 int i;
298
299 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
300 command_print(cmd_ctx, "current target isn't an ARM target");
301 return ERROR_OK;
302 }
303
304 /* REVISIT: eventually support ThumbEE disassembly too;
305 * some opcodes work differently.
306 */
307
308 switch (argc) {
309 case 3:
310 if (strcmp(args[2], "thumb") != 0)
311 goto usage;
312 thumb = 1;
313 /* FALL THROUGH */
314 case 2:
315 COMMAND_PARSE_NUMBER(int, args[1], count);
316 /* FALL THROUGH */
317 case 1:
318 COMMAND_PARSE_NUMBER(u32, args[0], address);
319 if (address & 0x01) {
320 if (!thumb) {
321 command_print(cmd_ctx, "Disassemble as Thumb");
322 thumb = 1;
323 }
324 address &= ~1;
325 }
326 break;
327 default:
328 usage:
329 command_print(cmd_ctx,
330 "usage: armv7a disassemble <address> [<count> ['thumb']]");
331 return ERROR_OK;
332 }
333
334 for (i = 0; i < count; i++) {
335 struct arm_instruction cur_instruction;
336 int retval;
337
338 if (thumb) {
339 retval = thumb2_opcode(target, address, &cur_instruction);
340 if (retval != ERROR_OK)
341 return retval;
342
343 address += cur_instruction.instruction_size;
344 } else {
345 uint32_t opcode;
346
347 retval = target_read_u32(target, address, &opcode);
348 if (retval != ERROR_OK)
349 return retval;
350
351 retval = arm_evaluate_opcode(opcode, address,
352 &cur_instruction);
353 if (retval != ERROR_OK)
354 return retval;
355
356 address += 4;
357 }
358 command_print(cmd_ctx, "%s", cur_instruction.text);
359 }
360
361 return ERROR_OK;
362 }
363
364 int armv7a_register_commands(struct command_context_s *cmd_ctx)
365 {
366 command_t *arm_adi_v5_dap_cmd;
367 command_t *armv7a_cmd;
368
369 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
370 NULL, COMMAND_ANY,
371 "cortex dap specific commands");
372
373 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
374 handle_dap_info_command, COMMAND_EXEC,
375 "dap info for ap [num], "
376 "default currently selected AP");
377 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
378 handle_dap_apsel_command, COMMAND_EXEC,
379 "select a different AP [num] (default 0)");
380 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
381 handle_dap_apid_command, COMMAND_EXEC,
382 "return id reg from AP [num], "
383 "default currently selected AP");
384 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
385 handle_dap_baseaddr_command, COMMAND_EXEC,
386 "return debug base address from AP [num], "
387 "default currently selected AP");
388 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
389 handle_dap_memaccess_command, COMMAND_EXEC,
390 "set/get number of extra tck for mem-ap memory "
391 "bus access [0-255]");
392
393 armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
394 NULL, COMMAND_ANY,
395 "ARMv7-A specific commands");
396
397 register_command(cmd_ctx, armv7a_cmd, "disassemble",
398 handle_armv7a_disassemble_command, COMMAND_EXEC,
399 "disassemble instructions <address> [<count> ['thumb']]");
400
401 return ERROR_OK;
402 }

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)