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

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)