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

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)