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

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)