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

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)