5e882e67fb76406eaf5956edff49c54ea0df0bd4
[openocd.git] / src / target / armv4_5.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "armv4_5.h"
31 #include "arm_jtag.h"
32 #include "breakpoints.h"
33 #include "arm_disassembler.h"
34 #include "binarybuffer.h"
35 #include "algorithm.h"
36 #include "register.h"
37
38
39 static const char *armv4_5_core_reg_list[] =
40 {
41 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
42 "r8", "r9", "r10", "r11", "r12", "sp_usr", "lr_usr", "pc",
43
44 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "sp_fiq", "lr_fiq",
45
46 "sp_irq", "lr_irq",
47
48 "sp_svc", "lr_svc",
49
50 "sp_abt", "lr_abt",
51
52 "sp_und", "lr_und",
53
54 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
55
56 "sp_mon", "lr_mon", "spsr_mon",
57 };
58
59 static const uint8_t arm_usr_indices[17] = {
60 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ARMV4_5_CPSR,
61 };
62
63 static const uint8_t arm_fiq_indices[8] = {
64 16, 17, 18, 19, 20, 21, 22, ARMV4_5_SPSR_FIQ,
65 };
66
67 static const uint8_t arm_irq_indices[3] = {
68 23, 24, ARMV4_5_SPSR_IRQ,
69 };
70
71 static const uint8_t arm_svc_indices[3] = {
72 25, 26, ARMV4_5_SPSR_SVC,
73 };
74
75 static const uint8_t arm_abt_indices[3] = {
76 27, 28, ARMV4_5_SPSR_ABT,
77 };
78
79 static const uint8_t arm_und_indices[3] = {
80 29, 30, ARMV4_5_SPSR_UND,
81 };
82
83 static const uint8_t arm_mon_indices[3] = {
84 37, 38, ARM_SPSR_MON,
85 };
86
87 static const struct {
88 const char *name;
89 unsigned short psr;
90 /* For user and system modes, these list indices for all registers.
91 * otherwise they're just indices for the shadow registers and SPSR.
92 */
93 unsigned short n_indices;
94 const uint8_t *indices;
95 } arm_mode_data[] = {
96 /* Seven modes are standard from ARM7 on. "System" and "User" share
97 * the same registers; other modes shadow from 3 to 8 registers.
98 */
99 {
100 .name = "User",
101 .psr = ARMV4_5_MODE_USR,
102 .n_indices = ARRAY_SIZE(arm_usr_indices),
103 .indices = arm_usr_indices,
104 },
105 {
106 .name = "FIQ",
107 .psr = ARMV4_5_MODE_FIQ,
108 .n_indices = ARRAY_SIZE(arm_fiq_indices),
109 .indices = arm_fiq_indices,
110 },
111 {
112 .name = "Supervisor",
113 .psr = ARMV4_5_MODE_SVC,
114 .n_indices = ARRAY_SIZE(arm_svc_indices),
115 .indices = arm_svc_indices,
116 },
117 {
118 .name = "Abort",
119 .psr = ARMV4_5_MODE_ABT,
120 .n_indices = ARRAY_SIZE(arm_abt_indices),
121 .indices = arm_abt_indices,
122 },
123 {
124 .name = "IRQ",
125 .psr = ARMV4_5_MODE_IRQ,
126 .n_indices = ARRAY_SIZE(arm_irq_indices),
127 .indices = arm_irq_indices,
128 },
129 {
130 .name = "Undefined instruction",
131 .psr = ARMV4_5_MODE_UND,
132 .n_indices = ARRAY_SIZE(arm_und_indices),
133 .indices = arm_und_indices,
134 },
135 {
136 .name = "System",
137 .psr = ARMV4_5_MODE_SYS,
138 .n_indices = ARRAY_SIZE(arm_usr_indices),
139 .indices = arm_usr_indices,
140 },
141 /* TrustZone "Security Extensions" add a secure monitor mode.
142 * This is distinct from a "debug monitor" which can support
143 * non-halting debug, in conjunction with some debuggers.
144 */
145 {
146 .name = "Secure Monitor",
147 .psr = ARM_MODE_MON,
148 .n_indices = ARRAY_SIZE(arm_mon_indices),
149 .indices = arm_mon_indices,
150 },
151 };
152
153 /** Map PSR mode bits to the name of an ARM processor operating mode. */
154 const char *arm_mode_name(unsigned psr_mode)
155 {
156 for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
157 if (arm_mode_data[i].psr == psr_mode)
158 return arm_mode_data[i].name;
159 }
160 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode);
161 return "UNRECOGNIZED";
162 }
163
164 /** Return true iff the parameter denotes a valid ARM processor mode. */
165 bool is_arm_mode(unsigned psr_mode)
166 {
167 for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
168 if (arm_mode_data[i].psr == psr_mode)
169 return true;
170 }
171 return false;
172 }
173
174 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
175 int armv4_5_mode_to_number(enum armv4_5_mode mode)
176 {
177 switch (mode) {
178 case ARMV4_5_MODE_ANY:
179 /* map MODE_ANY to user mode */
180 case ARMV4_5_MODE_USR:
181 return 0;
182 case ARMV4_5_MODE_FIQ:
183 return 1;
184 case ARMV4_5_MODE_IRQ:
185 return 2;
186 case ARMV4_5_MODE_SVC:
187 return 3;
188 case ARMV4_5_MODE_ABT:
189 return 4;
190 case ARMV4_5_MODE_UND:
191 return 5;
192 case ARMV4_5_MODE_SYS:
193 return 6;
194 case ARM_MODE_MON:
195 return 7;
196 default:
197 LOG_ERROR("invalid mode value encountered %d", mode);
198 return -1;
199 }
200 }
201
202 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
203 enum armv4_5_mode armv4_5_number_to_mode(int number)
204 {
205 switch (number) {
206 case 0:
207 return ARMV4_5_MODE_USR;
208 case 1:
209 return ARMV4_5_MODE_FIQ;
210 case 2:
211 return ARMV4_5_MODE_IRQ;
212 case 3:
213 return ARMV4_5_MODE_SVC;
214 case 4:
215 return ARMV4_5_MODE_ABT;
216 case 5:
217 return ARMV4_5_MODE_UND;
218 case 6:
219 return ARMV4_5_MODE_SYS;
220 case 7:
221 return ARM_MODE_MON;
222 default:
223 LOG_ERROR("mode index out of bounds %d", number);
224 return ARMV4_5_MODE_ANY;
225 }
226 }
227
228 char* armv4_5_state_strings[] =
229 {
230 "ARM", "Thumb", "Jazelle", "ThumbEE",
231 };
232
233 static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
234 {
235 {0, ARMV4_5_MODE_ANY, NULL, NULL},
236 {1, ARMV4_5_MODE_ANY, NULL, NULL},
237 {2, ARMV4_5_MODE_ANY, NULL, NULL},
238 {3, ARMV4_5_MODE_ANY, NULL, NULL},
239 {4, ARMV4_5_MODE_ANY, NULL, NULL},
240 {5, ARMV4_5_MODE_ANY, NULL, NULL},
241 {6, ARMV4_5_MODE_ANY, NULL, NULL},
242 {7, ARMV4_5_MODE_ANY, NULL, NULL},
243 {8, ARMV4_5_MODE_ANY, NULL, NULL},
244 {9, ARMV4_5_MODE_ANY, NULL, NULL},
245 {10, ARMV4_5_MODE_ANY, NULL, NULL},
246 {11, ARMV4_5_MODE_ANY, NULL, NULL},
247 {12, ARMV4_5_MODE_ANY, NULL, NULL},
248 {13, ARMV4_5_MODE_USR, NULL, NULL},
249 {14, ARMV4_5_MODE_USR, NULL, NULL},
250 {15, ARMV4_5_MODE_ANY, NULL, NULL},
251
252 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
253 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
254 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
255 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
256 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
257 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
258 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
259
260 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
261 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
262
263 {13, ARMV4_5_MODE_SVC, NULL, NULL},
264 {14, ARMV4_5_MODE_SVC, NULL, NULL},
265
266 {13, ARMV4_5_MODE_ABT, NULL, NULL},
267 {14, ARMV4_5_MODE_ABT, NULL, NULL},
268
269 {13, ARMV4_5_MODE_UND, NULL, NULL},
270 {14, ARMV4_5_MODE_UND, NULL, NULL},
271
272 {16, ARMV4_5_MODE_ANY, NULL, NULL},
273 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
274 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
275 {16, ARMV4_5_MODE_SVC, NULL, NULL},
276 {16, ARMV4_5_MODE_ABT, NULL, NULL},
277 {16, ARMV4_5_MODE_UND, NULL, NULL},
278
279 {13, ARM_MODE_MON, NULL, NULL},
280 {14, ARM_MODE_MON, NULL, NULL},
281 {16, ARM_MODE_MON, NULL, NULL},
282 };
283
284 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
285 const int armv4_5_core_reg_map[8][17] =
286 {
287 { /* USR */
288 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
289 },
290 { /* FIQ (8 shadows of USR, vs normal 3) */
291 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
292 },
293 { /* IRQ */
294 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
295 },
296 { /* SVC */
297 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
298 },
299 { /* ABT */
300 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
301 },
302 { /* UND */
303 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
304 },
305 { /* SYS (same registers as USR) */
306 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
307 },
308 { /* MON */
309 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
310 }
311 };
312
313 static const uint8_t arm_gdb_dummy_fp_value[12];
314
315 /**
316 * Dummy FPA registers are required to support GDB on ARM.
317 * Register packets require eight obsolete FPA register values.
318 * Modern ARM cores use Vector Floating Point (VFP), if they
319 * have any floating point support. VFP is not FPA-compatible.
320 */
321 struct reg arm_gdb_dummy_fp_reg =
322 {
323 .name = "GDB dummy FPA register",
324 .value = (uint8_t *) arm_gdb_dummy_fp_value,
325 .valid = 1,
326 .size = 96,
327 };
328
329 static const uint8_t arm_gdb_dummy_fps_value[4];
330
331 /**
332 * Dummy FPA status registers are required to support GDB on ARM.
333 * Register packets require an obsolete FPA status register.
334 */
335 struct reg arm_gdb_dummy_fps_reg =
336 {
337 .name = "GDB dummy FPA status register",
338 .value = (uint8_t *) arm_gdb_dummy_fps_value,
339 .valid = 1,
340 .size = 32,
341 };
342
343 static void arm_gdb_dummy_init(void) __attribute__ ((constructor));
344
345 static void arm_gdb_dummy_init(void)
346 {
347 register_init_dummy(&arm_gdb_dummy_fp_reg);
348 register_init_dummy(&arm_gdb_dummy_fps_reg);
349 }
350
351 static int armv4_5_get_core_reg(struct reg *reg)
352 {
353 int retval;
354 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
355 struct target *target = armv4_5->target;
356
357 if (target->state != TARGET_HALTED)
358 {
359 LOG_ERROR("Target not halted");
360 return ERROR_TARGET_NOT_HALTED;
361 }
362
363 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
364 if (retval == ERROR_OK)
365 reg->valid = 1;
366
367 return retval;
368 }
369
370 static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
371 {
372 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
373 struct target *target = armv4_5->target;
374 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
375 uint32_t value = buf_get_u32(buf, 0, 32);
376
377 if (target->state != TARGET_HALTED)
378 {
379 LOG_ERROR("Target not halted");
380 return ERROR_TARGET_NOT_HALTED;
381 }
382
383 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
384 {
385 if (value & 0x20)
386 {
387 /* T bit should be set */
388 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
389 {
390 /* change state to Thumb */
391 LOG_DEBUG("changing to Thumb state");
392 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
393 }
394 }
395 else
396 {
397 /* T bit should be cleared */
398 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
399 {
400 /* change state to ARM */
401 LOG_DEBUG("changing to ARM state");
402 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
403 }
404 }
405
406 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
407 {
408 LOG_DEBUG("changing ARM core mode to '%s'",
409 arm_mode_name(value & 0x1f));
410 armv4_5_target->core_mode = value & 0x1f;
411 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
412 }
413 }
414
415 buf_set_u32(reg->value, 0, 32, value);
416 reg->dirty = 1;
417 reg->valid = 1;
418
419 return ERROR_OK;
420 }
421
422 static const struct reg_arch_type arm_reg_type = {
423 .get = armv4_5_get_core_reg,
424 .set = armv4_5_set_core_reg,
425 };
426
427 /** Marks the contents of the register cache as invalid (and clean). */
428 int armv4_5_invalidate_core_regs(struct target *target)
429 {
430 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
431 unsigned num_regs = armv4_5->core_cache->num_regs;
432 struct reg *reg = armv4_5->core_cache->reg_list;
433
434 for (unsigned i = 0; i < num_regs; i++, reg++) {
435 reg->valid = 0;
436 reg->dirty = 0;
437 }
438
439 /* FIXME don't bother returning a value then */
440 return ERROR_OK;
441 }
442
443 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
444 {
445 int num_regs = ARRAY_SIZE(armv4_5_core_reg_list_arch_info);
446 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
447 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
448 struct armv4_5_core_reg *arch_info = calloc(num_regs,
449 sizeof(struct armv4_5_core_reg));
450 int i;
451
452 if (!cache || !reg_list || !arch_info) {
453 free(cache);
454 free(reg_list);
455 free(arch_info);
456 return NULL;
457 }
458
459 cache->name = "ARM registers";
460 cache->next = NULL;
461 cache->reg_list = reg_list;
462 cache->num_regs = 0;
463
464 for (i = 0; i < num_regs; i++)
465 {
466 /* Skip registers this core doesn't expose */
467 if (armv4_5_core_reg_list_arch_info[i].mode == ARM_MODE_MON
468 && armv4_5_common->core_type != ARM_MODE_MON)
469 continue;
470
471 /* REVISIT handle Cortex-M, which only shadows R13/SP */
472
473 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
474 arch_info[i].target = target;
475 arch_info[i].armv4_5_common = armv4_5_common;
476 reg_list[i].name = (char *) armv4_5_core_reg_list[i];
477 reg_list[i].size = 32;
478 reg_list[i].value = calloc(1, 4);
479 reg_list[i].type = &arm_reg_type;
480 reg_list[i].arch_info = &arch_info[i];
481
482 cache->num_regs++;
483 }
484
485 return cache;
486 }
487
488 int armv4_5_arch_state(struct target *target)
489 {
490 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
491
492 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
493 {
494 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
495 return ERROR_FAIL;
496 }
497
498 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
499 armv4_5_state_strings[armv4_5->core_state],
500 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
501 arm_mode_name(armv4_5->core_mode),
502 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
503 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
504
505 return ERROR_OK;
506 }
507
508 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
509 cache->reg_list[armv4_5_core_reg_map[mode][num]]
510
511 COMMAND_HANDLER(handle_armv4_5_reg_command)
512 {
513 struct target *target = get_current_target(CMD_CTX);
514 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
515 unsigned num_regs;
516 struct reg *regs;
517
518 if (!is_arm(armv4_5))
519 {
520 command_print(CMD_CTX, "current target isn't an ARM");
521 return ERROR_FAIL;
522 }
523
524 if (target->state != TARGET_HALTED)
525 {
526 command_print(CMD_CTX, "error: target must be halted for register accesses");
527 return ERROR_FAIL;
528 }
529
530 if (!is_arm_mode(armv4_5->core_mode))
531 return ERROR_FAIL;
532
533 if (!armv4_5->full_context) {
534 command_print(CMD_CTX, "error: target doesn't support %s",
535 CMD_NAME);
536 return ERROR_FAIL;
537 }
538
539 num_regs = armv4_5->core_cache->num_regs;
540 regs = armv4_5->core_cache->reg_list;
541
542 for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) {
543 const char *name;
544 char *sep = "\n";
545 char *shadow = "";
546
547 /* label this bank of registers (or shadows) */
548 switch (arm_mode_data[mode].psr) {
549 case ARMV4_5_MODE_SYS:
550 continue;
551 case ARMV4_5_MODE_USR:
552 name = "System and User";
553 sep = "";
554 break;
555 case ARM_MODE_MON:
556 if (armv4_5->core_type != ARM_MODE_MON)
557 continue;
558 /* FALLTHROUGH */
559 default:
560 name = arm_mode_data[mode].name;
561 shadow = "shadow ";
562 break;
563 }
564 command_print(CMD_CTX, "%s%s mode %sregisters",
565 sep, name, shadow);
566
567 /* display N rows of up to 4 registers each */
568 for (unsigned i = 0; i < arm_mode_data[mode].n_indices;) {
569 char output[80];
570 int output_len = 0;
571
572 for (unsigned j = 0; j < 4; j++, i++) {
573 uint32_t value;
574 struct reg *reg = regs;
575
576 if (i >= arm_mode_data[mode].n_indices)
577 break;
578
579 reg += arm_mode_data[mode].indices[i];
580
581 /* REVISIT be smarter about faults... */
582 if (!reg->valid)
583 armv4_5->full_context(target);
584
585 value = buf_get_u32(reg->value, 0, 32);
586 output_len += snprintf(output + output_len,
587 sizeof(output) - output_len,
588 "%8s: %8.8" PRIx32 " ",
589 reg->name, value);
590 }
591 command_print(CMD_CTX, "%s", output);
592 }
593 }
594
595 return ERROR_OK;
596 }
597
598 COMMAND_HANDLER(handle_armv4_5_core_state_command)
599 {
600 struct target *target = get_current_target(CMD_CTX);
601 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
602
603 if (!is_arm(armv4_5))
604 {
605 command_print(CMD_CTX, "current target isn't an ARM");
606 return ERROR_FAIL;
607 }
608
609 if (CMD_ARGC > 0)
610 {
611 if (strcmp(CMD_ARGV[0], "arm") == 0)
612 {
613 armv4_5->core_state = ARMV4_5_STATE_ARM;
614 }
615 if (strcmp(CMD_ARGV[0], "thumb") == 0)
616 {
617 armv4_5->core_state = ARMV4_5_STATE_THUMB;
618 }
619 }
620
621 command_print(CMD_CTX, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
622
623 return ERROR_OK;
624 }
625
626 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
627 {
628 int retval = ERROR_OK;
629 struct target *target = get_current_target(CMD_CTX);
630 struct arm *arm = target ? target_to_arm(target) : NULL;
631 uint32_t address;
632 int count = 1;
633 int thumb = 0;
634
635 if (!is_arm(arm)) {
636 command_print(CMD_CTX, "current target isn't an ARM");
637 return ERROR_FAIL;
638 }
639
640 switch (CMD_ARGC) {
641 case 3:
642 if (strcmp(CMD_ARGV[2], "thumb") != 0)
643 goto usage;
644 thumb = 1;
645 /* FALL THROUGH */
646 case 2:
647 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
648 /* FALL THROUGH */
649 case 1:
650 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
651 if (address & 0x01) {
652 if (!thumb) {
653 command_print(CMD_CTX, "Disassemble as Thumb");
654 thumb = 1;
655 }
656 address &= ~1;
657 }
658 break;
659 default:
660 usage:
661 command_print(CMD_CTX,
662 "usage: arm disassemble <address> [<count> ['thumb']]");
663 count = 0;
664 retval = ERROR_FAIL;
665 }
666
667 while (count-- > 0) {
668 struct arm_instruction cur_instruction;
669
670 if (thumb) {
671 /* Always use Thumb2 disassembly for best handling
672 * of 32-bit BL/BLX, and to work with newer cores
673 * (some ARMv6, all ARMv7) that use Thumb2.
674 */
675 retval = thumb2_opcode(target, address,
676 &cur_instruction);
677 if (retval != ERROR_OK)
678 break;
679 } else {
680 uint32_t opcode;
681
682 retval = target_read_u32(target, address, &opcode);
683 if (retval != ERROR_OK)
684 break;
685 retval = arm_evaluate_opcode(opcode, address,
686 &cur_instruction) != ERROR_OK;
687 if (retval != ERROR_OK)
688 break;
689 }
690 command_print(CMD_CTX, "%s", cur_instruction.text);
691 address += cur_instruction.instruction_size;
692 }
693
694 return retval;
695 }
696
697 int armv4_5_register_commands(struct command_context *cmd_ctx)
698 {
699 struct command *armv4_5_cmd;
700
701 armv4_5_cmd = register_command(cmd_ctx, NULL, "arm",
702 NULL, COMMAND_ANY,
703 "generic ARM commands");
704
705 register_command(cmd_ctx, armv4_5_cmd, "reg",
706 handle_armv4_5_reg_command, COMMAND_EXEC,
707 "display ARM core registers");
708 register_command(cmd_ctx, armv4_5_cmd, "core_state",
709 handle_armv4_5_core_state_command, COMMAND_EXEC,
710 "display/change ARM core state <arm | thumb>");
711 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
712 handle_armv4_5_disassemble_command, COMMAND_EXEC,
713 "disassemble instructions "
714 "<address> [<count> ['thumb']]");
715
716 return ERROR_OK;
717 }
718
719 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
720 {
721 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
722 int i;
723
724 if (!is_arm_mode(armv4_5->core_mode))
725 return ERROR_FAIL;
726
727 *reg_list_size = 26;
728 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
729
730 for (i = 0; i < 16; i++)
731 {
732 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
733 }
734
735 for (i = 16; i < 24; i++)
736 {
737 (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
738 }
739
740 (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
741 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
742
743 return ERROR_OK;
744 }
745
746 /* wait for execution to complete and check exit point */
747 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
748 {
749 int retval;
750 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
751
752 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
753 {
754 return retval;
755 }
756 if (target->state != TARGET_HALTED)
757 {
758 if ((retval = target_halt(target)) != ERROR_OK)
759 return retval;
760 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
761 {
762 return retval;
763 }
764 return ERROR_TARGET_TIMEOUT;
765 }
766
767 /* fast exit: ARMv5+ code can use BKPT */
768 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
769 0, 32) != exit_point)
770 {
771 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
772 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
773 return ERROR_TARGET_TIMEOUT;
774 }
775
776 return ERROR_OK;
777 }
778
779 int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info))
780 {
781 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
782 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
783 enum armv4_5_state core_state = armv4_5->core_state;
784 enum armv4_5_mode core_mode = armv4_5->core_mode;
785 uint32_t context[17];
786 uint32_t cpsr;
787 int exit_breakpoint_size = 0;
788 int i;
789 int retval = ERROR_OK;
790 LOG_DEBUG("Running algorithm");
791
792 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
793 {
794 LOG_ERROR("current target isn't an ARMV4/5 target");
795 return ERROR_TARGET_INVALID;
796 }
797
798 if (target->state != TARGET_HALTED)
799 {
800 LOG_WARNING("target not halted");
801 return ERROR_TARGET_NOT_HALTED;
802 }
803
804 if (!is_arm_mode(armv4_5->core_mode))
805 return ERROR_FAIL;
806
807 /* armv5 and later can terminate with BKPT instruction; less overhead */
808 if (!exit_point && armv4_5->is_armv4)
809 {
810 LOG_ERROR("ARMv4 target needs HW breakpoint location");
811 return ERROR_FAIL;
812 }
813
814 for (i = 0; i <= 16; i++)
815 {
816 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
817 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
818 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
819 }
820 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
821
822 for (i = 0; i < num_mem_params; i++)
823 {
824 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
825 {
826 return retval;
827 }
828 }
829
830 for (i = 0; i < num_reg_params; i++)
831 {
832 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
833 if (!reg)
834 {
835 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
836 return ERROR_INVALID_ARGUMENTS;
837 }
838
839 if (reg->size != reg_params[i].size)
840 {
841 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
842 return ERROR_INVALID_ARGUMENTS;
843 }
844
845 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
846 {
847 return retval;
848 }
849 }
850
851 armv4_5->core_state = armv4_5_algorithm_info->core_state;
852 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
853 exit_breakpoint_size = 4;
854 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
855 exit_breakpoint_size = 2;
856 else
857 {
858 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
859 return ERROR_INVALID_ARGUMENTS;
860 }
861
862 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
863 {
864 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
865 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
866 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
867 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
868 }
869
870 /* terminate using a hardware or (ARMv5+) software breakpoint */
871 if (exit_point && (retval = breakpoint_add(target, exit_point,
872 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
873 {
874 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
875 return ERROR_TARGET_FAILURE;
876 }
877
878 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
879 {
880 return retval;
881 }
882 int retvaltemp;
883 retval = run_it(target, exit_point, timeout_ms, arch_info);
884
885 if (exit_point)
886 breakpoint_remove(target, exit_point);
887
888 if (retval != ERROR_OK)
889 return retval;
890
891 for (i = 0; i < num_mem_params; i++)
892 {
893 if (mem_params[i].direction != PARAM_OUT)
894 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
895 {
896 retval = retvaltemp;
897 }
898 }
899
900 for (i = 0; i < num_reg_params; i++)
901 {
902 if (reg_params[i].direction != PARAM_OUT)
903 {
904
905 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
906 if (!reg)
907 {
908 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
909 retval = ERROR_INVALID_ARGUMENTS;
910 continue;
911 }
912
913 if (reg->size != reg_params[i].size)
914 {
915 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
916 retval = ERROR_INVALID_ARGUMENTS;
917 continue;
918 }
919
920 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
921 }
922 }
923
924 for (i = 0; i <= 16; i++)
925 {
926 uint32_t regvalue;
927 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
928 if (regvalue != context[i])
929 {
930 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]);
931 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
932 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
933 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
934 }
935 }
936 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
937 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
938 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
939
940 armv4_5->core_state = core_state;
941 armv4_5->core_mode = core_mode;
942
943 return retval;
944 }
945
946 int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
947 {
948 return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion);
949 }
950
951 /**
952 * Runs ARM code in the target to calculate a CRC32 checksum.
953 *
954 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
955 */
956 int arm_checksum_memory(struct target *target,
957 uint32_t address, uint32_t count, uint32_t *checksum)
958 {
959 struct working_area *crc_algorithm;
960 struct armv4_5_algorithm armv4_5_info;
961 struct reg_param reg_params[2];
962 int retval;
963 uint32_t i;
964
965 static const uint32_t arm_crc_code[] = {
966 0xE1A02000, /* mov r2, r0 */
967 0xE3E00000, /* mov r0, #0xffffffff */
968 0xE1A03001, /* mov r3, r1 */
969 0xE3A04000, /* mov r4, #0 */
970 0xEA00000B, /* b ncomp */
971 /* nbyte: */
972 0xE7D21004, /* ldrb r1, [r2, r4] */
973 0xE59F7030, /* ldr r7, CRC32XOR */
974 0xE0200C01, /* eor r0, r0, r1, asl 24 */
975 0xE3A05000, /* mov r5, #0 */
976 /* loop: */
977 0xE3500000, /* cmp r0, #0 */
978 0xE1A06080, /* mov r6, r0, asl #1 */
979 0xE2855001, /* add r5, r5, #1 */
980 0xE1A00006, /* mov r0, r6 */
981 0xB0260007, /* eorlt r0, r6, r7 */
982 0xE3550008, /* cmp r5, #8 */
983 0x1AFFFFF8, /* bne loop */
984 0xE2844001, /* add r4, r4, #1 */
985 /* ncomp: */
986 0xE1540003, /* cmp r4, r3 */
987 0x1AFFFFF1, /* bne nbyte */
988 /* end: */
989 0xEAFFFFFE, /* b end */
990 /* CRC32XOR: */
991 0x04C11DB7 /* .word 0x04C11DB7 */
992 };
993
994 retval = target_alloc_working_area(target,
995 sizeof(arm_crc_code), &crc_algorithm);
996 if (retval != ERROR_OK)
997 return retval;
998
999 /* convert code into a buffer in target endianness */
1000 for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) {
1001 retval = target_write_u32(target,
1002 crc_algorithm->address + i * sizeof(uint32_t),
1003 arm_crc_code[i]);
1004 if (retval != ERROR_OK)
1005 return retval;
1006 }
1007
1008 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
1009 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
1010 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
1011
1012 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
1013 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1014
1015 buf_set_u32(reg_params[0].value, 0, 32, address);
1016 buf_set_u32(reg_params[1].value, 0, 32, count);
1017
1018 /* 20 second timeout/megabyte */
1019 int timeout = 20000 * (1 + (count / (1024 * 1024)));
1020
1021 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
1022 crc_algorithm->address,
1023 crc_algorithm->address + sizeof(arm_crc_code) - 8,
1024 timeout, &armv4_5_info);
1025 if (retval != ERROR_OK) {
1026 LOG_ERROR("error executing ARM crc algorithm");
1027 destroy_reg_param(&reg_params[0]);
1028 destroy_reg_param(&reg_params[1]);
1029 target_free_working_area(target, crc_algorithm);
1030 return retval;
1031 }
1032
1033 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
1034
1035 destroy_reg_param(&reg_params[0]);
1036 destroy_reg_param(&reg_params[1]);
1037
1038 target_free_working_area(target, crc_algorithm);
1039
1040 return ERROR_OK;
1041 }
1042
1043 /**
1044 * Runs ARM code in the target to check whether a memory block holds
1045 * all ones. NOR flash which has been erased, and thus may be written,
1046 * holds all ones.
1047 *
1048 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
1049 */
1050 int arm_blank_check_memory(struct target *target,
1051 uint32_t address, uint32_t count, uint32_t *blank)
1052 {
1053 struct working_area *check_algorithm;
1054 struct reg_param reg_params[3];
1055 struct armv4_5_algorithm armv4_5_info;
1056 int retval;
1057 uint32_t i;
1058
1059 static const uint32_t check_code[] = {
1060 /* loop: */
1061 0xe4d03001, /* ldrb r3, [r0], #1 */
1062 0xe0022003, /* and r2, r2, r3 */
1063 0xe2511001, /* subs r1, r1, #1 */
1064 0x1afffffb, /* bne loop */
1065 /* end: */
1066 0xeafffffe /* b end */
1067 };
1068
1069 /* make sure we have a working area */
1070 retval = target_alloc_working_area(target,
1071 sizeof(check_code), &check_algorithm);
1072 if (retval != ERROR_OK)
1073 return retval;
1074
1075 /* convert code into a buffer in target endianness */
1076 for (i = 0; i < ARRAY_SIZE(check_code); i++) {
1077 retval = target_write_u32(target,
1078 check_algorithm->address
1079 + i * sizeof(uint32_t),
1080 check_code[i]);
1081 if (retval != ERROR_OK)
1082 return retval;
1083 }
1084
1085 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
1086 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
1087 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
1088
1089 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1090 buf_set_u32(reg_params[0].value, 0, 32, address);
1091
1092 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1093 buf_set_u32(reg_params[1].value, 0, 32, count);
1094
1095 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
1096 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
1097
1098 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
1099 check_algorithm->address,
1100 check_algorithm->address + sizeof(check_code) - 4,
1101 10000, &armv4_5_info);
1102 if (retval != ERROR_OK) {
1103 destroy_reg_param(&reg_params[0]);
1104 destroy_reg_param(&reg_params[1]);
1105 destroy_reg_param(&reg_params[2]);
1106 target_free_working_area(target, check_algorithm);
1107 return retval;
1108 }
1109
1110 *blank = buf_get_u32(reg_params[2].value, 0, 32);
1111
1112 destroy_reg_param(&reg_params[0]);
1113 destroy_reg_param(&reg_params[1]);
1114 destroy_reg_param(&reg_params[2]);
1115
1116 target_free_working_area(target, check_algorithm);
1117
1118 return ERROR_OK;
1119 }
1120
1121 static int arm_full_context(struct target *target)
1122 {
1123 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
1124 unsigned num_regs = armv4_5->core_cache->num_regs;
1125 struct reg *reg = armv4_5->core_cache->reg_list;
1126 int retval = ERROR_OK;
1127
1128 for (; num_regs && retval == ERROR_OK; num_regs--, reg++) {
1129 if (reg->valid)
1130 continue;
1131 retval = armv4_5_get_core_reg(reg);
1132 }
1133 return retval;
1134 }
1135
1136 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
1137 {
1138 target->arch_info = armv4_5;
1139
1140 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
1141 armv4_5->core_state = ARMV4_5_STATE_ARM;
1142 armv4_5->core_mode = ARMV4_5_MODE_USR;
1143
1144 /* core_type may be overridden by subtype logic */
1145 armv4_5->core_type = ARMV4_5_MODE_ANY;
1146
1147 /* default full_context() has no core-specific optimizations */
1148 if (!armv4_5->full_context && armv4_5->read_core_reg)
1149 armv4_5->full_context = arm_full_context;
1150
1151 return ERROR_OK;
1152 }

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)