4c2a6e5422189d42fe3cc8da4ddf98fbb8eec02d
[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 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
120 {
121 {0, ARMV4_5_MODE_ANY, NULL, NULL},
122 {1, ARMV4_5_MODE_ANY, NULL, NULL},
123 {2, ARMV4_5_MODE_ANY, NULL, NULL},
124 {3, ARMV4_5_MODE_ANY, NULL, NULL},
125 {4, ARMV4_5_MODE_ANY, NULL, NULL},
126 {5, ARMV4_5_MODE_ANY, NULL, NULL},
127 {6, ARMV4_5_MODE_ANY, NULL, NULL},
128 {7, ARMV4_5_MODE_ANY, NULL, NULL},
129 {8, ARMV4_5_MODE_ANY, NULL, NULL},
130 {9, ARMV4_5_MODE_ANY, NULL, NULL},
131 {10, ARMV4_5_MODE_ANY, NULL, NULL},
132 {11, ARMV4_5_MODE_ANY, NULL, NULL},
133 {12, ARMV4_5_MODE_ANY, NULL, NULL},
134 {13, ARMV4_5_MODE_USR, NULL, NULL},
135 {14, ARMV4_5_MODE_USR, NULL, NULL},
136 {15, ARMV4_5_MODE_ANY, NULL, NULL},
137
138 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
139 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
140 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
141 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
142 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
143 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
144 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
145
146 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
147 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
148
149 {13, ARMV4_5_MODE_SVC, NULL, NULL},
150 {14, ARMV4_5_MODE_SVC, NULL, NULL},
151
152 {13, ARMV4_5_MODE_ABT, NULL, NULL},
153 {14, ARMV4_5_MODE_ABT, NULL, NULL},
154
155 {13, ARMV4_5_MODE_UND, NULL, NULL},
156 {14, ARMV4_5_MODE_UND, NULL, NULL},
157
158 {16, ARMV4_5_MODE_ANY, NULL, NULL},
159 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
160 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
161 {16, ARMV4_5_MODE_SVC, NULL, NULL},
162 {16, ARMV4_5_MODE_ABT, NULL, NULL},
163 {16, ARMV4_5_MODE_UND, NULL, NULL}
164 };
165
166 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
167 int armv4_5_core_reg_map[7][17] =
168 {
169 { /* USR */
170 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
171 },
172 { /* FIQ */
173 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
174 },
175 { /* IRQ */
176 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
177 },
178 { /* SVC */
179 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
180 },
181 { /* ABT */
182 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
183 },
184 { /* UND */
185 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
186 },
187 { /* SYS */
188 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
189 }
190 };
191
192 uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
193
194 struct reg armv4_5_gdb_dummy_fp_reg =
195 {
196 .name = "GDB dummy floating-point register",
197 .value = armv4_5_gdb_dummy_fp_value,
198 .dirty = 0,
199 .valid = 1,
200 .size = 96,
201 .arch_info = NULL,
202 };
203
204 uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
205
206 struct reg armv4_5_gdb_dummy_fps_reg =
207 {
208 .name = "GDB dummy floating-point status register",
209 .value = armv4_5_gdb_dummy_fps_value,
210 .dirty = 0,
211 .valid = 1,
212 .size = 32,
213 .arch_info = NULL,
214 };
215
216 int armv4_5_get_core_reg(struct reg *reg)
217 {
218 int retval;
219 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
220 struct target *target = armv4_5->target;
221
222 if (target->state != TARGET_HALTED)
223 {
224 LOG_ERROR("Target not halted");
225 return ERROR_TARGET_NOT_HALTED;
226 }
227
228 /* retval = armv4_5->armv4_5_common->full_context(target); */
229 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
230
231 return retval;
232 }
233
234 int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
235 {
236 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
237 struct target *target = armv4_5->target;
238 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
239 uint32_t value = buf_get_u32(buf, 0, 32);
240
241 if (target->state != TARGET_HALTED)
242 {
243 return ERROR_TARGET_NOT_HALTED;
244 }
245
246 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
247 {
248 if (value & 0x20)
249 {
250 /* T bit should be set */
251 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
252 {
253 /* change state to Thumb */
254 LOG_DEBUG("changing to Thumb state");
255 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
256 }
257 }
258 else
259 {
260 /* T bit should be cleared */
261 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
262 {
263 /* change state to ARM */
264 LOG_DEBUG("changing to ARM state");
265 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
266 }
267 }
268
269 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
270 {
271 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]);
272 armv4_5_target->core_mode = value & 0x1f;
273 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
274 }
275 }
276
277 buf_set_u32(reg->value, 0, 32, value);
278 reg->dirty = 1;
279 reg->valid = 1;
280
281 return ERROR_OK;
282 }
283
284 static const struct reg_arch_type arm_reg_type = {
285 .get = armv4_5_get_core_reg,
286 .set = armv4_5_set_core_reg,
287 };
288
289 int armv4_5_invalidate_core_regs(struct target *target)
290 {
291 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
292 int i;
293
294 for (i = 0; i < 37; i++)
295 {
296 armv4_5->core_cache->reg_list[i].valid = 0;
297 armv4_5->core_cache->reg_list[i].dirty = 0;
298 }
299
300 return ERROR_OK;
301 }
302
303 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
304 {
305 int num_regs = 37;
306 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
307 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
308 struct armv4_5_core_reg *arch_info = malloc(sizeof(struct armv4_5_core_reg) * num_regs);
309 int i;
310
311 cache->name = "arm v4/5 registers";
312 cache->next = NULL;
313 cache->reg_list = reg_list;
314 cache->num_regs = num_regs;
315
316 register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
317 register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
318
319 for (i = 0; i < 37; i++)
320 {
321 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
322 arch_info[i].target = target;
323 arch_info[i].armv4_5_common = armv4_5_common;
324 reg_list[i].name = armv4_5_core_reg_list[i];
325 reg_list[i].size = 32;
326 reg_list[i].value = calloc(1, 4);
327 reg_list[i].dirty = 0;
328 reg_list[i].valid = 0;
329 reg_list[i].type = &arm_reg_type;
330 reg_list[i].arch_info = &arch_info[i];
331 }
332
333 return cache;
334 }
335
336 int armv4_5_arch_state(struct target *target)
337 {
338 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
339
340 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
341 {
342 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
343 return ERROR_FAIL;
344 }
345
346 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
347 armv4_5_state_strings[armv4_5->core_state],
348 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
349 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
350 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
351 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
352
353 return ERROR_OK;
354 }
355
356 COMMAND_HANDLER(handle_armv4_5_reg_command)
357 {
358 char output[128];
359 int output_len;
360 int mode, num;
361 struct target *target = get_current_target(cmd_ctx);
362 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
363
364 if (!is_arm(armv4_5))
365 {
366 command_print(cmd_ctx, "current target isn't an ARM");
367 return ERROR_FAIL;
368 }
369
370 if (target->state != TARGET_HALTED)
371 {
372 command_print(cmd_ctx, "error: target must be halted for register accesses");
373 return ERROR_OK;
374 }
375
376 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
377 return ERROR_FAIL;
378
379 if (!armv4_5->full_context) {
380 command_print(cmd_ctx, "error: target doesn't support %s",
381 CMD_NAME);
382 return ERROR_FAIL;
383 }
384
385 for (num = 0; num <= 15; num++)
386 {
387 output_len = 0;
388 for (mode = 0; mode < 6; mode++)
389 {
390 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
391 {
392 armv4_5->full_context(target);
393 }
394 output_len += snprintf(output + output_len,
395 128 - output_len,
396 "%8s: %8.8" PRIx32 " ",
397 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
398 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
399 }
400 command_print(cmd_ctx, "%s", output);
401 }
402 command_print(cmd_ctx,
403 " 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 "",
404 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
405 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
406 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
407 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
408 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
409 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
410
411 return ERROR_OK;
412 }
413
414 COMMAND_HANDLER(handle_armv4_5_core_state_command)
415 {
416 struct target *target = get_current_target(cmd_ctx);
417 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
418
419 if (!is_arm(armv4_5))
420 {
421 command_print(cmd_ctx, "current target isn't an ARM");
422 return ERROR_FAIL;
423 }
424
425 if (CMD_ARGC > 0)
426 {
427 if (strcmp(args[0], "arm") == 0)
428 {
429 armv4_5->core_state = ARMV4_5_STATE_ARM;
430 }
431 if (strcmp(args[0], "thumb") == 0)
432 {
433 armv4_5->core_state = ARMV4_5_STATE_THUMB;
434 }
435 }
436
437 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
438
439 return ERROR_OK;
440 }
441
442 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
443 {
444 int retval = ERROR_OK;
445 struct target *target = get_current_target(cmd_ctx);
446 struct arm *arm = target ? target_to_arm(target) : NULL;
447 uint32_t address;
448 int count = 1;
449 int thumb = 0;
450
451 if (!is_arm(arm)) {
452 command_print(cmd_ctx, "current target isn't an ARM");
453 return ERROR_FAIL;
454 }
455
456 switch (CMD_ARGC) {
457 case 3:
458 if (strcmp(args[2], "thumb") != 0)
459 goto usage;
460 thumb = 1;
461 /* FALL THROUGH */
462 case 2:
463 COMMAND_PARSE_NUMBER(int, args[1], count);
464 /* FALL THROUGH */
465 case 1:
466 COMMAND_PARSE_NUMBER(u32, args[0], address);
467 if (address & 0x01) {
468 if (!thumb) {
469 command_print(cmd_ctx, "Disassemble as Thumb");
470 thumb = 1;
471 }
472 address &= ~1;
473 }
474 break;
475 default:
476 usage:
477 command_print(cmd_ctx,
478 "usage: arm disassemble <address> [<count> ['thumb']]");
479 count = 0;
480 retval = ERROR_FAIL;
481 }
482
483 while (count-- > 0) {
484 struct arm_instruction cur_instruction;
485
486 if (thumb) {
487 /* Always use Thumb2 disassembly for best handling
488 * of 32-bit BL/BLX, and to work with newer cores
489 * (some ARMv6, all ARMv7) that use Thumb2.
490 */
491 retval = thumb2_opcode(target, address,
492 &cur_instruction);
493 if (retval != ERROR_OK)
494 break;
495 } else {
496 uint32_t opcode;
497
498 retval = target_read_u32(target, address, &opcode);
499 if (retval != ERROR_OK)
500 break;
501 retval = arm_evaluate_opcode(opcode, address,
502 &cur_instruction) != ERROR_OK;
503 if (retval != ERROR_OK)
504 break;
505 }
506 command_print(cmd_ctx, "%s", cur_instruction.text);
507 address += cur_instruction.instruction_size;
508 }
509
510 return retval;
511 }
512
513 int armv4_5_register_commands(struct command_context *cmd_ctx)
514 {
515 struct command *armv4_5_cmd;
516
517 armv4_5_cmd = register_command(cmd_ctx, NULL, "arm",
518 NULL, COMMAND_ANY,
519 "generic ARM commands");
520
521 register_command(cmd_ctx, armv4_5_cmd, "reg",
522 handle_armv4_5_reg_command, COMMAND_EXEC,
523 "display ARM core registers");
524 register_command(cmd_ctx, armv4_5_cmd, "core_state",
525 handle_armv4_5_core_state_command, COMMAND_EXEC,
526 "display/change ARM core state <arm | thumb>");
527 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
528 handle_armv4_5_disassemble_command, COMMAND_EXEC,
529 "disassemble instructions "
530 "<address> [<count> ['thumb']]");
531
532 return ERROR_OK;
533 }
534
535 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
536 {
537 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
538 int i;
539
540 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
541 return ERROR_FAIL;
542
543 *reg_list_size = 26;
544 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
545
546 for (i = 0; i < 16; i++)
547 {
548 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
549 }
550
551 for (i = 16; i < 24; i++)
552 {
553 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
554 }
555
556 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
557 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
558
559 return ERROR_OK;
560 }
561
562 /* wait for execution to complete and check exit point */
563 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
564 {
565 int retval;
566 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
567
568 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
569 {
570 return retval;
571 }
572 if (target->state != TARGET_HALTED)
573 {
574 if ((retval = target_halt(target)) != ERROR_OK)
575 return retval;
576 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
577 {
578 return retval;
579 }
580 return ERROR_TARGET_TIMEOUT;
581 }
582
583 /* fast exit: ARMv5+ code can use BKPT */
584 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
585 0, 32) != exit_point)
586 {
587 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
588 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
589 return ERROR_TARGET_TIMEOUT;
590 }
591
592 return ERROR_OK;
593 }
594
595 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))
596 {
597 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
598 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
599 enum armv4_5_state core_state = armv4_5->core_state;
600 enum armv4_5_mode core_mode = armv4_5->core_mode;
601 uint32_t context[17];
602 uint32_t cpsr;
603 int exit_breakpoint_size = 0;
604 int i;
605 int retval = ERROR_OK;
606 LOG_DEBUG("Running algorithm");
607
608 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
609 {
610 LOG_ERROR("current target isn't an ARMV4/5 target");
611 return ERROR_TARGET_INVALID;
612 }
613
614 if (target->state != TARGET_HALTED)
615 {
616 LOG_WARNING("target not halted");
617 return ERROR_TARGET_NOT_HALTED;
618 }
619
620 if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
621 return ERROR_FAIL;
622
623 /* armv5 and later can terminate with BKPT instruction; less overhead */
624 if (!exit_point && armv4_5->is_armv4)
625 {
626 LOG_ERROR("ARMv4 target needs HW breakpoint location");
627 return ERROR_FAIL;
628 }
629
630 for (i = 0; i <= 16; i++)
631 {
632 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
633 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
634 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
635 }
636 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
637
638 for (i = 0; i < num_mem_params; i++)
639 {
640 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
641 {
642 return retval;
643 }
644 }
645
646 for (i = 0; i < num_reg_params; i++)
647 {
648 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
649 if (!reg)
650 {
651 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
652 return ERROR_INVALID_ARGUMENTS;
653 }
654
655 if (reg->size != reg_params[i].size)
656 {
657 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
658 return ERROR_INVALID_ARGUMENTS;
659 }
660
661 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
662 {
663 return retval;
664 }
665 }
666
667 armv4_5->core_state = armv4_5_algorithm_info->core_state;
668 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
669 exit_breakpoint_size = 4;
670 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
671 exit_breakpoint_size = 2;
672 else
673 {
674 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
675 return ERROR_INVALID_ARGUMENTS;
676 }
677
678 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
679 {
680 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
681 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
682 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
683 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
684 }
685
686 /* terminate using a hardware or (ARMv5+) software breakpoint */
687 if (exit_point && (retval = breakpoint_add(target, exit_point,
688 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
689 {
690 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
691 return ERROR_TARGET_FAILURE;
692 }
693
694 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
695 {
696 return retval;
697 }
698 int retvaltemp;
699 retval = run_it(target, exit_point, timeout_ms, arch_info);
700
701 if (exit_point)
702 breakpoint_remove(target, exit_point);
703
704 if (retval != ERROR_OK)
705 return retval;
706
707 for (i = 0; i < num_mem_params; i++)
708 {
709 if (mem_params[i].direction != PARAM_OUT)
710 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
711 {
712 retval = retvaltemp;
713 }
714 }
715
716 for (i = 0; i < num_reg_params; i++)
717 {
718 if (reg_params[i].direction != PARAM_OUT)
719 {
720
721 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
722 if (!reg)
723 {
724 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
725 retval = ERROR_INVALID_ARGUMENTS;
726 continue;
727 }
728
729 if (reg->size != reg_params[i].size)
730 {
731 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
732 retval = ERROR_INVALID_ARGUMENTS;
733 continue;
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)