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

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)