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

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)