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

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)