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

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)