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

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)