3e27ba4183cdb3783482a8d428380566001d4a60
[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 static const 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 static const struct {
57 const char *name;
58 unsigned psr;
59 } arm_mode_data[] = {
60 /* Seven modes are standard from ARM7 on. "System" and "User" share
61 * the same registers; other modes shadow from 3 to 8 registers.
62 */
63 {
64 .name = "User",
65 .psr = ARMV4_5_MODE_USR,
66 },
67 {
68 .name = "FIQ",
69 .psr = ARMV4_5_MODE_FIQ,
70 },
71 {
72 .name = "Supervisor",
73 .psr = ARMV4_5_MODE_SVC,
74 },
75 {
76 .name = "Abort",
77 .psr = ARMV4_5_MODE_ABT,
78 },
79 {
80 .name = "IRQ",
81 .psr = ARMV4_5_MODE_IRQ,
82 },
83 {
84 .name = "Undefined" /* instruction */,
85 .psr = ARMV4_5_MODE_UND,
86 },
87 {
88 .name = "System",
89 .psr = ARMV4_5_MODE_SYS,
90 },
91 /* TrustZone "Security Extensions" add a secure monitor mode.
92 * This is distinct from a "debug monitor" which can support
93 * non-halting debug, in conjunction with some debuggers.
94 */
95 {
96 .name = "Secure Monitor",
97 .psr = ARM_MODE_MON,
98 },
99 };
100
101 /** Map PSR mode bits to the name of an ARM processor operating mode. */
102 const char *arm_mode_name(unsigned psr_mode)
103 {
104 for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
105 if (arm_mode_data[i].psr == psr_mode)
106 return arm_mode_data[i].name;
107 }
108 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode);
109 return "UNRECOGNIZED";
110 }
111
112 /** Return true iff the parameter denotes a valid ARM processor mode. */
113 bool is_arm_mode(unsigned psr_mode)
114 {
115 for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
116 if (arm_mode_data[i].psr == psr_mode)
117 return true;
118 }
119 return false;
120 }
121
122 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
123 int armv4_5_mode_to_number(enum armv4_5_mode mode)
124 {
125 switch (mode) {
126 case ARMV4_5_MODE_ANY:
127 /* map MODE_ANY to user mode */
128 case ARMV4_5_MODE_USR:
129 return 0;
130 case ARMV4_5_MODE_FIQ:
131 return 1;
132 case ARMV4_5_MODE_IRQ:
133 return 2;
134 case ARMV4_5_MODE_SVC:
135 return 3;
136 case ARMV4_5_MODE_ABT:
137 return 4;
138 case ARMV4_5_MODE_UND:
139 return 5;
140 case ARMV4_5_MODE_SYS:
141 return 6;
142 default:
143 LOG_ERROR("invalid mode value encountered %d", mode);
144 return -1;
145 }
146 }
147
148 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
149 enum armv4_5_mode armv4_5_number_to_mode(int number)
150 {
151 switch (number) {
152 case 0:
153 return ARMV4_5_MODE_USR;
154 case 1:
155 return ARMV4_5_MODE_FIQ;
156 case 2:
157 return ARMV4_5_MODE_IRQ;
158 case 3:
159 return ARMV4_5_MODE_SVC;
160 case 4:
161 return ARMV4_5_MODE_ABT;
162 case 5:
163 return ARMV4_5_MODE_UND;
164 case 6:
165 return ARMV4_5_MODE_SYS;
166 default:
167 LOG_ERROR("mode index out of bounds %d", number);
168 return ARMV4_5_MODE_ANY;
169 }
170 }
171
172 char* armv4_5_state_strings[] =
173 {
174 "ARM", "Thumb", "Jazelle"
175 };
176
177 static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
178 {
179 {0, ARMV4_5_MODE_ANY, NULL, NULL},
180 {1, ARMV4_5_MODE_ANY, NULL, NULL},
181 {2, ARMV4_5_MODE_ANY, NULL, NULL},
182 {3, ARMV4_5_MODE_ANY, NULL, NULL},
183 {4, ARMV4_5_MODE_ANY, NULL, NULL},
184 {5, ARMV4_5_MODE_ANY, NULL, NULL},
185 {6, ARMV4_5_MODE_ANY, NULL, NULL},
186 {7, ARMV4_5_MODE_ANY, NULL, NULL},
187 {8, ARMV4_5_MODE_ANY, NULL, NULL},
188 {9, ARMV4_5_MODE_ANY, NULL, NULL},
189 {10, ARMV4_5_MODE_ANY, NULL, NULL},
190 {11, ARMV4_5_MODE_ANY, NULL, NULL},
191 {12, ARMV4_5_MODE_ANY, NULL, NULL},
192 {13, ARMV4_5_MODE_USR, NULL, NULL},
193 {14, ARMV4_5_MODE_USR, NULL, NULL},
194 {15, ARMV4_5_MODE_ANY, NULL, NULL},
195
196 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
197 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
198 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
199 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
200 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
201 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
202 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
203
204 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
205 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
206
207 {13, ARMV4_5_MODE_SVC, NULL, NULL},
208 {14, ARMV4_5_MODE_SVC, NULL, NULL},
209
210 {13, ARMV4_5_MODE_ABT, NULL, NULL},
211 {14, ARMV4_5_MODE_ABT, NULL, NULL},
212
213 {13, ARMV4_5_MODE_UND, NULL, NULL},
214 {14, ARMV4_5_MODE_UND, NULL, NULL},
215
216 {16, ARMV4_5_MODE_ANY, NULL, NULL},
217 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
218 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
219 {16, ARMV4_5_MODE_SVC, NULL, NULL},
220 {16, ARMV4_5_MODE_ABT, NULL, NULL},
221 {16, ARMV4_5_MODE_UND, NULL, NULL}
222 };
223
224 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
225 const int armv4_5_core_reg_map[7][17] =
226 {
227 { /* USR */
228 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
229 },
230 { /* FIQ */
231 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
232 },
233 { /* IRQ */
234 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
235 },
236 { /* SVC */
237 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
238 },
239 { /* ABT */
240 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
241 },
242 { /* UND */
243 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
244 },
245 { /* SYS */
246 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
247 }
248 };
249
250 static const uint8_t arm_gdb_dummy_fp_value[12];
251
252 /**
253 * Dummy FPA registers are required to support GDB on ARM.
254 * Register packets require eight obsolete FPA register values.
255 * Modern ARM cores use Vector Floating Point (VFP), if they
256 * have any floating point support. VFP is not FPA-compatible.
257 */
258 struct reg arm_gdb_dummy_fp_reg =
259 {
260 .name = "GDB dummy FPA register",
261 .value = (uint8_t *) arm_gdb_dummy_fp_value,
262 .valid = 1,
263 .size = 96,
264 };
265
266 static const uint8_t arm_gdb_dummy_fps_value[4];
267
268 /**
269 * Dummy FPA status registers are required to support GDB on ARM.
270 * Register packets require an obsolete FPA status register.
271 */
272 struct reg arm_gdb_dummy_fps_reg =
273 {
274 .name = "GDB dummy FPA status register",
275 .value = (uint8_t *) arm_gdb_dummy_fps_value,
276 .valid = 1,
277 .size = 32,
278 };
279
280 static void arm_gdb_dummy_init(void) __attribute__ ((constructor));
281
282 static void arm_gdb_dummy_init(void)
283 {
284 register_init_dummy(&arm_gdb_dummy_fp_reg);
285 register_init_dummy(&arm_gdb_dummy_fps_reg);
286 }
287
288 int armv4_5_get_core_reg(struct reg *reg)
289 {
290 int retval;
291 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
292 struct target *target = armv4_5->target;
293
294 if (target->state != TARGET_HALTED)
295 {
296 LOG_ERROR("Target not halted");
297 return ERROR_TARGET_NOT_HALTED;
298 }
299
300 /* retval = armv4_5->armv4_5_common->full_context(target); */
301 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
302
303 return retval;
304 }
305
306 int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
307 {
308 struct armv4_5_core_reg *armv4_5 = reg->arch_info;
309 struct target *target = armv4_5->target;
310 struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
311 uint32_t value = buf_get_u32(buf, 0, 32);
312
313 if (target->state != TARGET_HALTED)
314 {
315 return ERROR_TARGET_NOT_HALTED;
316 }
317
318 if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
319 {
320 if (value & 0x20)
321 {
322 /* T bit should be set */
323 if (armv4_5_target->core_state == ARMV4_5_STATE_ARM)
324 {
325 /* change state to Thumb */
326 LOG_DEBUG("changing to Thumb state");
327 armv4_5_target->core_state = ARMV4_5_STATE_THUMB;
328 }
329 }
330 else
331 {
332 /* T bit should be cleared */
333 if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB)
334 {
335 /* change state to ARM */
336 LOG_DEBUG("changing to ARM state");
337 armv4_5_target->core_state = ARMV4_5_STATE_ARM;
338 }
339 }
340
341 if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
342 {
343 LOG_DEBUG("changing ARM core mode to '%s'",
344 arm_mode_name(value & 0x1f));
345 armv4_5_target->core_mode = value & 0x1f;
346 armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
347 }
348 }
349
350 buf_set_u32(reg->value, 0, 32, value);
351 reg->dirty = 1;
352 reg->valid = 1;
353
354 return ERROR_OK;
355 }
356
357 static const struct reg_arch_type arm_reg_type = {
358 .get = armv4_5_get_core_reg,
359 .set = armv4_5_set_core_reg,
360 };
361
362 int armv4_5_invalidate_core_regs(struct target *target)
363 {
364 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
365 int i;
366
367 for (i = 0; i < 37; i++)
368 {
369 armv4_5->core_cache->reg_list[i].valid = 0;
370 armv4_5->core_cache->reg_list[i].dirty = 0;
371 }
372
373 return ERROR_OK;
374 }
375
376 struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *armv4_5_common)
377 {
378 int num_regs = 37;
379 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
380 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
381 struct armv4_5_core_reg *arch_info = malloc(sizeof(struct armv4_5_core_reg) * num_regs);
382 int i;
383
384 cache->name = "arm v4/5 registers";
385 cache->next = NULL;
386 cache->reg_list = reg_list;
387 cache->num_regs = num_regs;
388
389 for (i = 0; i < 37; i++)
390 {
391 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
392 arch_info[i].target = target;
393 arch_info[i].armv4_5_common = armv4_5_common;
394 reg_list[i].name = (char *) armv4_5_core_reg_list[i];
395 reg_list[i].size = 32;
396 reg_list[i].value = calloc(1, 4);
397 reg_list[i].dirty = 0;
398 reg_list[i].valid = 0;
399 reg_list[i].type = &arm_reg_type;
400 reg_list[i].arch_info = &arch_info[i];
401 }
402
403 return cache;
404 }
405
406 int armv4_5_arch_state(struct target *target)
407 {
408 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
409
410 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
411 {
412 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
413 return ERROR_FAIL;
414 }
415
416 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
417 armv4_5_state_strings[armv4_5->core_state],
418 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
419 arm_mode_name(armv4_5->core_mode),
420 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
421 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
422
423 return ERROR_OK;
424 }
425
426 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
427 cache->reg_list[armv4_5_core_reg_map[mode][num]]
428
429 COMMAND_HANDLER(handle_armv4_5_reg_command)
430 {
431 char output[128];
432 int output_len;
433 int mode, num;
434 struct target *target = get_current_target(CMD_CTX);
435 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
436
437 if (!is_arm(armv4_5))
438 {
439 command_print(CMD_CTX, "current target isn't an ARM");
440 return ERROR_FAIL;
441 }
442
443 if (target->state != TARGET_HALTED)
444 {
445 command_print(CMD_CTX, "error: target must be halted for register accesses");
446 return ERROR_OK;
447 }
448
449 if (!is_arm_mode(armv4_5->core_mode))
450 return ERROR_FAIL;
451
452 if (!armv4_5->full_context) {
453 command_print(CMD_CTX, "error: target doesn't support %s",
454 CMD_NAME);
455 return ERROR_FAIL;
456 }
457
458 for (num = 0; num <= 15; num++)
459 {
460 output_len = 0;
461 for (mode = 0; mode < 6; mode++)
462 {
463 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
464 {
465 armv4_5->full_context(target);
466 }
467 output_len += snprintf(output + output_len,
468 128 - output_len,
469 "%8s: %8.8" PRIx32 " ",
470 ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
471 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
472 }
473 command_print(CMD_CTX, "%s", output);
474 }
475 command_print(CMD_CTX,
476 " 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 "",
477 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
478 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
479 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
480 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
481 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
482 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
483
484 return ERROR_OK;
485 }
486
487 COMMAND_HANDLER(handle_armv4_5_core_state_command)
488 {
489 struct target *target = get_current_target(CMD_CTX);
490 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
491
492 if (!is_arm(armv4_5))
493 {
494 command_print(CMD_CTX, "current target isn't an ARM");
495 return ERROR_FAIL;
496 }
497
498 if (CMD_ARGC > 0)
499 {
500 if (strcmp(CMD_ARGV[0], "arm") == 0)
501 {
502 armv4_5->core_state = ARMV4_5_STATE_ARM;
503 }
504 if (strcmp(CMD_ARGV[0], "thumb") == 0)
505 {
506 armv4_5->core_state = ARMV4_5_STATE_THUMB;
507 }
508 }
509
510 command_print(CMD_CTX, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
511
512 return ERROR_OK;
513 }
514
515 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
516 {
517 int retval = ERROR_OK;
518 struct target *target = get_current_target(CMD_CTX);
519 struct arm *arm = target ? target_to_arm(target) : NULL;
520 uint32_t address;
521 int count = 1;
522 int thumb = 0;
523
524 if (!is_arm(arm)) {
525 command_print(CMD_CTX, "current target isn't an ARM");
526 return ERROR_FAIL;
527 }
528
529 switch (CMD_ARGC) {
530 case 3:
531 if (strcmp(CMD_ARGV[2], "thumb") != 0)
532 goto usage;
533 thumb = 1;
534 /* FALL THROUGH */
535 case 2:
536 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
537 /* FALL THROUGH */
538 case 1:
539 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
540 if (address & 0x01) {
541 if (!thumb) {
542 command_print(CMD_CTX, "Disassemble as Thumb");
543 thumb = 1;
544 }
545 address &= ~1;
546 }
547 break;
548 default:
549 usage:
550 command_print(CMD_CTX,
551 "usage: arm disassemble <address> [<count> ['thumb']]");
552 count = 0;
553 retval = ERROR_FAIL;
554 }
555
556 while (count-- > 0) {
557 struct arm_instruction cur_instruction;
558
559 if (thumb) {
560 /* Always use Thumb2 disassembly for best handling
561 * of 32-bit BL/BLX, and to work with newer cores
562 * (some ARMv6, all ARMv7) that use Thumb2.
563 */
564 retval = thumb2_opcode(target, address,
565 &cur_instruction);
566 if (retval != ERROR_OK)
567 break;
568 } else {
569 uint32_t opcode;
570
571 retval = target_read_u32(target, address, &opcode);
572 if (retval != ERROR_OK)
573 break;
574 retval = arm_evaluate_opcode(opcode, address,
575 &cur_instruction) != ERROR_OK;
576 if (retval != ERROR_OK)
577 break;
578 }
579 command_print(CMD_CTX, "%s", cur_instruction.text);
580 address += cur_instruction.instruction_size;
581 }
582
583 return retval;
584 }
585
586 int armv4_5_register_commands(struct command_context *cmd_ctx)
587 {
588 struct command *armv4_5_cmd;
589
590 armv4_5_cmd = register_command(cmd_ctx, NULL, "arm",
591 NULL, COMMAND_ANY,
592 "generic ARM commands");
593
594 register_command(cmd_ctx, armv4_5_cmd, "reg",
595 handle_armv4_5_reg_command, COMMAND_EXEC,
596 "display ARM core registers");
597 register_command(cmd_ctx, armv4_5_cmd, "core_state",
598 handle_armv4_5_core_state_command, COMMAND_EXEC,
599 "display/change ARM core state <arm | thumb>");
600 register_command(cmd_ctx, armv4_5_cmd, "disassemble",
601 handle_armv4_5_disassemble_command, COMMAND_EXEC,
602 "disassemble instructions "
603 "<address> [<count> ['thumb']]");
604
605 return ERROR_OK;
606 }
607
608 int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
609 {
610 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
611 int i;
612
613 if (!is_arm_mode(armv4_5->core_mode))
614 return ERROR_FAIL;
615
616 *reg_list_size = 26;
617 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
618
619 for (i = 0; i < 16; i++)
620 {
621 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
622 }
623
624 for (i = 16; i < 24; i++)
625 {
626 (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
627 }
628
629 (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
630 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
631
632 return ERROR_OK;
633 }
634
635 /* wait for execution to complete and check exit point */
636 static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info)
637 {
638 int retval;
639 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
640
641 if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
642 {
643 return retval;
644 }
645 if (target->state != TARGET_HALTED)
646 {
647 if ((retval = target_halt(target)) != ERROR_OK)
648 return retval;
649 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
650 {
651 return retval;
652 }
653 return ERROR_TARGET_TIMEOUT;
654 }
655
656 /* fast exit: ARMv5+ code can use BKPT */
657 if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value,
658 0, 32) != exit_point)
659 {
660 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
661 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
662 return ERROR_TARGET_TIMEOUT;
663 }
664
665 return ERROR_OK;
666 }
667
668 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))
669 {
670 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
671 struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
672 enum armv4_5_state core_state = armv4_5->core_state;
673 enum armv4_5_mode core_mode = armv4_5->core_mode;
674 uint32_t context[17];
675 uint32_t cpsr;
676 int exit_breakpoint_size = 0;
677 int i;
678 int retval = ERROR_OK;
679 LOG_DEBUG("Running algorithm");
680
681 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
682 {
683 LOG_ERROR("current target isn't an ARMV4/5 target");
684 return ERROR_TARGET_INVALID;
685 }
686
687 if (target->state != TARGET_HALTED)
688 {
689 LOG_WARNING("target not halted");
690 return ERROR_TARGET_NOT_HALTED;
691 }
692
693 if (!is_arm_mode(armv4_5->core_mode))
694 return ERROR_FAIL;
695
696 /* armv5 and later can terminate with BKPT instruction; less overhead */
697 if (!exit_point && armv4_5->is_armv4)
698 {
699 LOG_ERROR("ARMv4 target needs HW breakpoint location");
700 return ERROR_FAIL;
701 }
702
703 for (i = 0; i <= 16; i++)
704 {
705 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
706 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
707 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
708 }
709 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
710
711 for (i = 0; i < num_mem_params; i++)
712 {
713 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
714 {
715 return retval;
716 }
717 }
718
719 for (i = 0; i < num_reg_params; i++)
720 {
721 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
722 if (!reg)
723 {
724 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
725 return ERROR_INVALID_ARGUMENTS;
726 }
727
728 if (reg->size != reg_params[i].size)
729 {
730 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
731 return ERROR_INVALID_ARGUMENTS;
732 }
733
734 if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
735 {
736 return retval;
737 }
738 }
739
740 armv4_5->core_state = armv4_5_algorithm_info->core_state;
741 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
742 exit_breakpoint_size = 4;
743 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
744 exit_breakpoint_size = 2;
745 else
746 {
747 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
748 return ERROR_INVALID_ARGUMENTS;
749 }
750
751 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
752 {
753 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
754 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
755 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
756 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
757 }
758
759 /* terminate using a hardware or (ARMv5+) software breakpoint */
760 if (exit_point && (retval = breakpoint_add(target, exit_point,
761 exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
762 {
763 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
764 return ERROR_TARGET_FAILURE;
765 }
766
767 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
768 {
769 return retval;
770 }
771 int retvaltemp;
772 retval = run_it(target, exit_point, timeout_ms, arch_info);
773
774 if (exit_point)
775 breakpoint_remove(target, exit_point);
776
777 if (retval != ERROR_OK)
778 return retval;
779
780 for (i = 0; i < num_mem_params; i++)
781 {
782 if (mem_params[i].direction != PARAM_OUT)
783 if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
784 {
785 retval = retvaltemp;
786 }
787 }
788
789 for (i = 0; i < num_reg_params; i++)
790 {
791 if (reg_params[i].direction != PARAM_OUT)
792 {
793
794 struct reg *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
795 if (!reg)
796 {
797 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
798 retval = ERROR_INVALID_ARGUMENTS;
799 continue;
800 }
801
802 if (reg->size != reg_params[i].size)
803 {
804 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
805 retval = ERROR_INVALID_ARGUMENTS;
806 continue;
807 }
808
809 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
810 }
811 }
812
813 for (i = 0; i <= 16; i++)
814 {
815 uint32_t regvalue;
816 regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
817 if (regvalue != context[i])
818 {
819 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]);
820 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
821 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
822 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
823 }
824 }
825 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
826 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
827 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
828
829 armv4_5->core_state = core_state;
830 armv4_5->core_mode = core_mode;
831
832 return retval;
833 }
834
835 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)
836 {
837 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);
838 }
839
840 /**
841 * Runs ARM code in the target to calculate a CRC32 checksum.
842 *
843 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
844 */
845 int arm_checksum_memory(struct target *target,
846 uint32_t address, uint32_t count, uint32_t *checksum)
847 {
848 struct working_area *crc_algorithm;
849 struct armv4_5_algorithm armv4_5_info;
850 struct reg_param reg_params[2];
851 int retval;
852 uint32_t i;
853
854 static const uint32_t arm_crc_code[] = {
855 0xE1A02000, /* mov r2, r0 */
856 0xE3E00000, /* mov r0, #0xffffffff */
857 0xE1A03001, /* mov r3, r1 */
858 0xE3A04000, /* mov r4, #0 */
859 0xEA00000B, /* b ncomp */
860 /* nbyte: */
861 0xE7D21004, /* ldrb r1, [r2, r4] */
862 0xE59F7030, /* ldr r7, CRC32XOR */
863 0xE0200C01, /* eor r0, r0, r1, asl 24 */
864 0xE3A05000, /* mov r5, #0 */
865 /* loop: */
866 0xE3500000, /* cmp r0, #0 */
867 0xE1A06080, /* mov r6, r0, asl #1 */
868 0xE2855001, /* add r5, r5, #1 */
869 0xE1A00006, /* mov r0, r6 */
870 0xB0260007, /* eorlt r0, r6, r7 */
871 0xE3550008, /* cmp r5, #8 */
872 0x1AFFFFF8, /* bne loop */
873 0xE2844001, /* add r4, r4, #1 */
874 /* ncomp: */
875 0xE1540003, /* cmp r4, r3 */
876 0x1AFFFFF1, /* bne nbyte */
877 /* end: */
878 0xEAFFFFFE, /* b end */
879 /* CRC32XOR: */
880 0x04C11DB7 /* .word 0x04C11DB7 */
881 };
882
883 retval = target_alloc_working_area(target,
884 sizeof(arm_crc_code), &crc_algorithm);
885 if (retval != ERROR_OK)
886 return retval;
887
888 /* convert code into a buffer in target endianness */
889 for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) {
890 retval = target_write_u32(target,
891 crc_algorithm->address + i * sizeof(uint32_t),
892 arm_crc_code[i]);
893 if (retval != ERROR_OK)
894 return retval;
895 }
896
897 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
898 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
899 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
900
901 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
902 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
903
904 buf_set_u32(reg_params[0].value, 0, 32, address);
905 buf_set_u32(reg_params[1].value, 0, 32, count);
906
907 /* 20 second timeout/megabyte */
908 int timeout = 20000 * (1 + (count / (1024 * 1024)));
909
910 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
911 crc_algorithm->address,
912 crc_algorithm->address + sizeof(arm_crc_code) - 8,
913 timeout, &armv4_5_info);
914 if (retval != ERROR_OK) {
915 LOG_ERROR("error executing ARM crc algorithm");
916 destroy_reg_param(&reg_params[0]);
917 destroy_reg_param(&reg_params[1]);
918 target_free_working_area(target, crc_algorithm);
919 return retval;
920 }
921
922 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
923
924 destroy_reg_param(&reg_params[0]);
925 destroy_reg_param(&reg_params[1]);
926
927 target_free_working_area(target, crc_algorithm);
928
929 return ERROR_OK;
930 }
931
932 /**
933 * Runs ARM code in the target to check whether a memory block holds
934 * all ones. NOR flash which has been erased, and thus may be written,
935 * holds all ones.
936 *
937 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
938 */
939 int arm_blank_check_memory(struct target *target,
940 uint32_t address, uint32_t count, uint32_t *blank)
941 {
942 struct working_area *check_algorithm;
943 struct reg_param reg_params[3];
944 struct armv4_5_algorithm armv4_5_info;
945 int retval;
946 uint32_t i;
947
948 static const uint32_t check_code[] = {
949 /* loop: */
950 0xe4d03001, /* ldrb r3, [r0], #1 */
951 0xe0022003, /* and r2, r2, r3 */
952 0xe2511001, /* subs r1, r1, #1 */
953 0x1afffffb, /* bne loop */
954 /* end: */
955 0xeafffffe /* b end */
956 };
957
958 /* make sure we have a working area */
959 retval = target_alloc_working_area(target,
960 sizeof(check_code), &check_algorithm);
961 if (retval != ERROR_OK)
962 return retval;
963
964 /* convert code into a buffer in target endianness */
965 for (i = 0; i < ARRAY_SIZE(check_code); i++) {
966 retval = target_write_u32(target,
967 check_algorithm->address
968 + i * sizeof(uint32_t),
969 check_code[i]);
970 if (retval != ERROR_OK)
971 return retval;
972 }
973
974 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
975 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
976 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
977
978 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
979 buf_set_u32(reg_params[0].value, 0, 32, address);
980
981 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
982 buf_set_u32(reg_params[1].value, 0, 32, count);
983
984 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
985 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
986
987 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
988 check_algorithm->address,
989 check_algorithm->address + sizeof(check_code) - 4,
990 10000, &armv4_5_info);
991 if (retval != ERROR_OK) {
992 destroy_reg_param(&reg_params[0]);
993 destroy_reg_param(&reg_params[1]);
994 destroy_reg_param(&reg_params[2]);
995 target_free_working_area(target, check_algorithm);
996 return retval;
997 }
998
999 *blank = buf_get_u32(reg_params[2].value, 0, 32);
1000
1001 destroy_reg_param(&reg_params[0]);
1002 destroy_reg_param(&reg_params[1]);
1003 destroy_reg_param(&reg_params[2]);
1004
1005 target_free_working_area(target, check_algorithm);
1006
1007 return ERROR_OK;
1008 }
1009
1010 int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
1011 {
1012 target->arch_info = armv4_5;
1013
1014 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
1015 armv4_5->core_state = ARMV4_5_STATE_ARM;
1016 armv4_5->core_mode = ARMV4_5_MODE_USR;
1017
1018 /* core_type may be overridden by subtype logic */
1019 armv4_5->core_type = ARMV4_5_MODE_ANY;
1020
1021 return ERROR_OK;
1022 }

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)