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

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)