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

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)