7c4861ffff7cb83724e069d16e25161cb5111e26
[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 for (num = 0; num <= 15; num++)
382 {
383 output_len = 0;
384 for (mode = 0; mode < 6; mode++)
385 {
386 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
387 {
388 armv4_5->full_context(target);
389 }
390 output_len += snprintf(output + output_len,
391 128 - output_len,
392 "%8s: %8.8" PRIx32 " ",
393 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
394 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
395 }
396 command_print(cmd_ctx, "%s", output);
397 }
398 command_print(cmd_ctx,
399 " 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 "",
400 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
401 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
402 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
403 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
404 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
405 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
406
407 return ERROR_OK;
408 }
409
410 COMMAND_HANDLER(handle_armv4_5_core_state_command)
411 {
412 struct target *target = get_current_target(cmd_ctx);
413 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
414
415 if (!is_arm(armv4_5))
416 {
417 command_print(cmd_ctx, "current target isn't an ARM");
418 return ERROR_FAIL;
419 }
420
421 if (argc > 0)
422 {
423 if (strcmp(args[0], "arm") == 0)
424 {
425 armv4_5->core_state = ARMV4_5_STATE_ARM;
426 }
427 if (strcmp(args[0], "thumb") == 0)
428 {
429 armv4_5->core_state = ARMV4_5_STATE_THUMB;
430 }
431 }
432
433 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
434
435 return ERROR_OK;
436 }
437
438 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
439 {
440 int retval = ERROR_OK;
441 struct target *target = get_current_target(cmd_ctx);
442 struct arm *arm = target ? target_to_arm(target) : NULL;
443 uint32_t address;
444 int count = 1;
445 int thumb = 0;
446
447 if (!is_arm(arm)) {
448 command_print(cmd_ctx, "current target isn't an ARM");
449 return ERROR_FAIL;
450 }
451
452 switch (argc) {
453 case 3:
454 if (strcmp(args[2], "thumb") != 0)
455 goto usage;
456 thumb = 1;
457 /* FALL THROUGH */
458 case 2:
459 COMMAND_PARSE_NUMBER(int, args[1], count);
460 /* FALL THROUGH */
461 case 1:
462 COMMAND_PARSE_NUMBER(u32, args[0], address);
463 if (address & 0x01) {
464 if (!thumb) {
465 command_print(cmd_ctx, "Disassemble as Thumb");
466 thumb = 1;
467 }
468 address &= ~1;
469 }
470 break;
471 default:
472 usage:
473 command_print(cmd_ctx,
474 "usage: arm disassemble <address> [<count> ['thumb']]");
475 count = 0;
476 retval = ERROR_FAIL;
477 }
478
479 while (count-- > 0) {
480 struct arm_instruction cur_instruction;
481
482 if (thumb) {
483 /* Always use Thumb2 disassembly for best handling
484 * of 32-bit BL/BLX, and to work with newer cores
485 * (some ARMv6, all ARMv7) that use Thumb2.
486 */
487 retval = thumb2_opcode(target, address,
488 &cur_instruction);
489 if (retval != ERROR_OK)
490 break;
491 } else {
492 uint32_t opcode;
493
494 retval = target_read_u32(target, address, &opcode);
495 if (retval != ERROR_OK)
496 break;
497 retval = arm_evaluate_opcode(opcode, address,
498 &cur_instruction) != ERROR_OK;
499 if (retval != ERROR_OK)
500 break;
501 }
502 command_print(cmd_ctx, "%s", cur_instruction.text);
503 address += cur_instruction.instruction_size;
504 }
505
506 return retval;
507 }
508
509 int armv4_5_register_commands(struct command_context *cmd_ctx)
510 {
511 struct command *armv4_5_cmd;
512
513 armv4_5_cmd = register_command(cmd_ctx, NULL, "arm",
514 NULL, COMMAND_ANY,
515 "generic ARM commands");
516
517 register_command(cmd_ctx, armv4_5_cmd, "reg",
518 handle_armv4_5_reg_command, COMMAND_EXEC,
519 "display ARM core registers");
520 register_command(cmd_ctx, armv4_5_cmd, "core_state",
521 handle_armv4_5_core_state_command, COMMAND_EXEC,
522 "display/change ARM core state <arm | thumb>");
523 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
524 handle_armv4_5_disassemble_command, COMMAND_EXEC,
525 "disassemble instructions <address> [<count> ['thumb']]");
526
527 return ERROR_OK;
528 }
529
530 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
531 {
532 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
533 int i;
534
535 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
536 return ERROR_FAIL;
537
538 *reg_list_size = 26;
539 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
540
541 for (i = 0; i < 16; i++)
542 {
543 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
544 }
545
546 for (i = 16; i < 24; i++)
547 {
548 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
549 }
550
551 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
552 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
553
554 return ERROR_OK;
555 }
556
557 /* wait for execution to complete and check exit point */
558 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
559 {
560 int retval;
561 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
562
563 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
564 {
565 return retval;
566 }
567 if (target->state != TARGET_HALTED)
568 {
569 if ((retval = target_halt(target)) != ERROR_OK)
570 return retval;
571 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
572 {
573 return retval;
574 }
575 return ERROR_TARGET_TIMEOUT;
576 }
577
578 /* fast exit: ARMv5+ code can use BKPT */
579 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
580 0, 32) != exit_point)
581 {
582 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
583 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
584 return ERROR_TARGET_TIMEOUT;
585 }
586
587 return ERROR_OK;
588 }
589
590 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))
591 {
592 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
593 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
594 enum armv4_5_state core_state = armv4_5->core_state;
595 enum armv4_5_mode core_mode = armv4_5->core_mode;
596 uint32_t context[17];
597 uint32_t cpsr;
598 int exit_breakpoint_size = 0;
599 int i;
600 int retval = ERROR_OK;
601 LOG_DEBUG("Running algorithm");
602
603 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
604 {
605 LOG_ERROR("current target isn't an ARMV4/5 target");
606 return ERROR_TARGET_INVALID;
607 }
608
609 if (target->state != TARGET_HALTED)
610 {
611 LOG_WARNING("target not halted");
612 return ERROR_TARGET_NOT_HALTED;
613 }
614
615 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
616 return ERROR_FAIL;
617
618 /* armv5 and later can terminate with BKPT instruction; less overhead */
619 if (!exit_point && armv4_5->is_armv4)
620 {
621 LOG_ERROR("ARMv4 target needs HW breakpoint location");
622 return ERROR_FAIL;
623 }
624
625 for (i = 0; i <= 16; i++)
626 {
627 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
628 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
629 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
630 }
631 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
632
633 for (i = 0; i < num_mem_params; i++)
634 {
635 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
636 {
637 return retval;
638 }
639 }
640
641 for (i = 0; i < num_reg_params; i++)
642 {
643 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
644 if (!reg)
645 {
646 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
647 exit(-1);
648 }
649
650 if (reg->size != reg_params[i].size)
651 {
652 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
653 exit(-1);
654 }
655
656 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
657 {
658 return retval;
659 }
660 }
661
662 armv4_5->core_state = armv4_5_algorithm_info->core_state;
663 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
664 exit_breakpoint_size = 4;
665 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
666 exit_breakpoint_size = 2;
667 else
668 {
669 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
670 exit(-1);
671 }
672
673 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
674 {
675 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
676 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
677 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
678 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
679 }
680
681 /* terminate using a hardware or (ARMv5+) software breakpoint */
682 if (exit_point && (retval = breakpoint_add(target, exit_point,
683 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
684 {
685 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
686 return ERROR_TARGET_FAILURE;
687 }
688
689 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
690 {
691 return retval;
692 }
693 int retvaltemp;
694 retval = run_it(target, exit_point, timeout_ms, arch_info);
695
696 if (exit_point)
697 breakpoint_remove(target, exit_point);
698
699 if (retval != ERROR_OK)
700 return retval;
701
702 for (i = 0; i < num_mem_params; i++)
703 {
704 if (mem_params[i].direction != PARAM_OUT)
705 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
706 {
707 retval = retvaltemp;
708 }
709 }
710
711 for (i = 0; i < num_reg_params; i++)
712 {
713 if (reg_params[i].direction != PARAM_OUT)
714 {
715
716 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
717 if (!reg)
718 {
719 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
720 exit(-1);
721 }
722
723 if (reg->size != reg_params[i].size)
724 {
725 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
726 exit(-1);
727 }
728
729 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
730 }
731 }
732
733 for (i = 0; i <= 16; i++)
734 {
735 uint32_t regvalue;
736 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
737 if (regvalue != context[i])
738 {
739 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]);
740 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
741 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
742 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
743 }
744 }
745 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
746 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
747 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
748
749 armv4_5->core_state = core_state;
750 armv4_5->core_mode = core_mode;
751
752 return retval;
753 }
754
755 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)
756 {
757 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);
758 }
759
760 /**
761 * Runs ARM code in the target to calculate a CRC32 checksum.
762 *
763 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
764 */
765 int arm_checksum_memory(struct target *target,
766 uint32_t address, uint32_t count, uint32_t *checksum)
767 {
768 struct working_area *crc_algorithm;
769 struct armv4_5_algorithm armv4_5_info;
770 struct reg_param reg_params[2];
771 int retval;
772 uint32_t i;
773
774 static const uint32_t arm_crc_code[] = {
775 0xE1A02000, /* mov r2, r0 */
776 0xE3E00000, /* mov r0, #0xffffffff */
777 0xE1A03001, /* mov r3, r1 */
778 0xE3A04000, /* mov r4, #0 */
779 0xEA00000B, /* b ncomp */
780 /* nbyte: */
781 0xE7D21004, /* ldrb r1, [r2, r4] */
782 0xE59F7030, /* ldr r7, CRC32XOR */
783 0xE0200C01, /* eor r0, r0, r1, asl 24 */
784 0xE3A05000, /* mov r5, #0 */
785 /* loop: */
786 0xE3500000, /* cmp r0, #0 */
787 0xE1A06080, /* mov r6, r0, asl #1 */
788 0xE2855001, /* add r5, r5, #1 */
789 0xE1A00006, /* mov r0, r6 */
790 0xB0260007, /* eorlt r0, r6, r7 */
791 0xE3550008, /* cmp r5, #8 */
792 0x1AFFFFF8, /* bne loop */
793 0xE2844001, /* add r4, r4, #1 */
794 /* ncomp: */
795 0xE1540003, /* cmp r4, r3 */
796 0x1AFFFFF1, /* bne nbyte */
797 /* end: */
798 0xEAFFFFFE, /* b end */
799 /* CRC32XOR: */
800 0x04C11DB7 /* .word 0x04C11DB7 */
801 };
802
803 retval = target_alloc_working_area(target,
804 sizeof(arm_crc_code), &crc_algorithm);
805 if (retval != ERROR_OK)
806 return retval;
807
808 /* convert code into a buffer in target endianness */
809 for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) {
810 retval = target_write_u32(target,
811 crc_algorithm->address + i * sizeof(uint32_t),
812 arm_crc_code[i]);
813 if (retval != ERROR_OK)
814 return retval;
815 }
816
817 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
818 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
819 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
820
821 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
822 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
823
824 buf_set_u32(reg_params[0].value, 0, 32, address);
825 buf_set_u32(reg_params[1].value, 0, 32, count);
826
827 /* 20 second timeout/megabyte */
828 int timeout = 20000 * (1 + (count / (1024 * 1024)));
829
830 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
831 crc_algorithm->address,
832 crc_algorithm->address + sizeof(arm_crc_code) - 8,
833 timeout, &armv4_5_info);
834 if (retval != ERROR_OK) {
835 LOG_ERROR("error executing ARM crc algorithm");
836 destroy_reg_param(&reg_params[0]);
837 destroy_reg_param(&reg_params[1]);
838 target_free_working_area(target, crc_algorithm);
839 return retval;
840 }
841
842 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
843
844 destroy_reg_param(&reg_params[0]);
845 destroy_reg_param(&reg_params[1]);
846
847 target_free_working_area(target, crc_algorithm);
848
849 return ERROR_OK;
850 }
851
852 /**
853 * Runs ARM code in the target to check whether a memory block holds
854 * all ones. NOR flash which has been erased, and thus may be written,
855 * holds all ones.
856 *
857 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
858 */
859 int arm_blank_check_memory(struct target *target,
860 uint32_t address, uint32_t count, uint32_t *blank)
861 {
862 struct working_area *check_algorithm;
863 struct reg_param reg_params[3];
864 struct armv4_5_algorithm armv4_5_info;
865 int retval;
866 uint32_t i;
867
868 static const uint32_t check_code[] = {
869 /* loop: */
870 0xe4d03001, /* ldrb r3, [r0], #1 */
871 0xe0022003, /* and r2, r2, r3 */
872 0xe2511001, /* subs r1, r1, #1 */
873 0x1afffffb, /* bne loop */
874 /* end: */
875 0xeafffffe /* b end */
876 };
877
878 /* make sure we have a working area */
879 retval = target_alloc_working_area(target,
880 sizeof(check_code), &check_algorithm);
881 if (retval != ERROR_OK)
882 return retval;
883
884 /* convert code into a buffer in target endianness */
885 for (i = 0; i < ARRAY_SIZE(check_code); i++) {
886 retval = target_write_u32(target,
887 check_algorithm->address
888 + i * sizeof(uint32_t),
889 check_code[i]);
890 if (retval != ERROR_OK)
891 return retval;
892 }
893
894 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
895 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
896 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
897
898 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
899 buf_set_u32(reg_params[0].value, 0, 32, address);
900
901 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
902 buf_set_u32(reg_params[1].value, 0, 32, count);
903
904 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
905 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
906
907 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
908 check_algorithm->address,
909 check_algorithm->address + sizeof(check_code) - 4,
910 10000, &armv4_5_info);
911 if (retval != ERROR_OK) {
912 destroy_reg_param(&reg_params[0]);
913 destroy_reg_param(&reg_params[1]);
914 destroy_reg_param(&reg_params[2]);
915 target_free_working_area(target, check_algorithm);
916 return retval;
917 }
918
919 *blank = buf_get_u32(reg_params[2].value, 0, 32);
920
921 destroy_reg_param(&reg_params[0]);
922 destroy_reg_param(&reg_params[1]);
923 destroy_reg_param(&reg_params[2]);
924
925 target_free_working_area(target, check_algorithm);
926
927 return ERROR_OK;
928 }
929
930 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
931 {
932 target->arch_info = armv4_5;
933
934 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
935 armv4_5->core_state = ARMV4_5_STATE_ARM;
936 armv4_5->core_mode = ARMV4_5_MODE_USR;
937
938 return ERROR_OK;
939 }

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)