- prepare OpenOCD for branching, created ./trunk/
[openocd.git] / src / target / armv4_5.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include "config.h"
21
22 #include "armv4_5.h"
23
24 #include "target.h"
25 #include "register.h"
26 #include "log.h"
27 #include "binarybuffer.h"
28 #include "command.h"
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 bitfield_desc_t armv4_5_psr_bitfield_desc[] =
35 {
36 {"M[4:0]", 5},
37 {"T", 1},
38 {"F", 1},
39 {"I", 1},
40 {"reserved", 16},
41 {"J", 1},
42 {"reserved", 2},
43 {"Q", 1},
44 {"V", 1},
45 {"C", 1},
46 {"Z", 1},
47 {"N", 1},
48 };
49
50 char* armv4_5_core_reg_list[] =
51 {
52 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
53
54 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
55
56 "r13_irq", "lr_irq",
57
58 "r13_svc", "lr_svc",
59
60 "r13_abt", "lr_abt",
61
62 "r13_und", "lr_und",
63
64 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
65 };
66
67 char* armv4_5_mode_strings[] =
68 {
69 "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
70 };
71
72 char* armv4_5_state_strings[] =
73 {
74 "ARM", "Thumb", "Jazelle"
75 };
76
77 int armv4_5_core_reg_arch_type = -1;
78
79 armv4_5_core_reg_t armv4_5_core_reg_list_arch_info[] =
80 {
81 {0, ARMV4_5_MODE_ANY, NULL, NULL},
82 {1, ARMV4_5_MODE_ANY, NULL, NULL},
83 {2, ARMV4_5_MODE_ANY, NULL, NULL},
84 {3, ARMV4_5_MODE_ANY, NULL, NULL},
85 {4, ARMV4_5_MODE_ANY, NULL, NULL},
86 {5, ARMV4_5_MODE_ANY, NULL, NULL},
87 {6, ARMV4_5_MODE_ANY, NULL, NULL},
88 {7, ARMV4_5_MODE_ANY, NULL, NULL},
89 {8, ARMV4_5_MODE_ANY, NULL, NULL},
90 {9, ARMV4_5_MODE_ANY, NULL, NULL},
91 {10, ARMV4_5_MODE_ANY, NULL, NULL},
92 {11, ARMV4_5_MODE_ANY, NULL, NULL},
93 {12, ARMV4_5_MODE_ANY, NULL, NULL},
94 {13, ARMV4_5_MODE_USR, NULL, NULL},
95 {14, ARMV4_5_MODE_USR, NULL, NULL},
96 {15, ARMV4_5_MODE_ANY, NULL, NULL},
97
98 {8, ARMV4_5_MODE_FIQ, NULL, NULL},
99 {9, ARMV4_5_MODE_FIQ, NULL, NULL},
100 {10, ARMV4_5_MODE_FIQ, NULL, NULL},
101 {11, ARMV4_5_MODE_FIQ, NULL, NULL},
102 {12, ARMV4_5_MODE_FIQ, NULL, NULL},
103 {13, ARMV4_5_MODE_FIQ, NULL, NULL},
104 {14, ARMV4_5_MODE_FIQ, NULL, NULL},
105
106 {13, ARMV4_5_MODE_IRQ, NULL, NULL},
107 {14, ARMV4_5_MODE_IRQ, NULL, NULL},
108
109 {13, ARMV4_5_MODE_SVC, NULL, NULL},
110 {14, ARMV4_5_MODE_SVC, NULL, NULL},
111
112 {13, ARMV4_5_MODE_ABT, NULL, NULL},
113 {14, ARMV4_5_MODE_ABT, NULL, NULL},
114
115 {13, ARMV4_5_MODE_UND, NULL, NULL},
116 {14, ARMV4_5_MODE_UND, NULL, NULL},
117
118 {16, ARMV4_5_MODE_ANY, NULL, NULL},
119 {16, ARMV4_5_MODE_FIQ, NULL, NULL},
120 {16, ARMV4_5_MODE_IRQ, NULL, NULL},
121 {16, ARMV4_5_MODE_SVC, NULL, NULL},
122 {16, ARMV4_5_MODE_ABT, NULL, NULL},
123 {16, ARMV4_5_MODE_UND, NULL, NULL}
124 };
125
126 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
127 int armv4_5_core_reg_map[7][17] =
128 {
129 { /* USR */
130 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
131 },
132 { /* FIQ */
133 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
134 },
135 { /* IRQ */
136 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
137 },
138 { /* SVC */
139 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
140 },
141 { /* ABT */
142 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
143 },
144 { /* UND */
145 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
146 },
147 { /* SYS */
148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
149 }
150 };
151
152 u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
153
154 reg_t armv4_5_gdb_dummy_fp_reg =
155 {
156 "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
157 };
158
159 u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
160
161 reg_t armv4_5_gdb_dummy_fps_reg =
162 {
163 "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
164 };
165
166 /* map psr mode bits to linear number */
167 int armv4_5_mode_to_number(enum armv4_5_mode mode)
168 {
169 switch (mode)
170 {
171 case 16: return 0; break;
172 case 17: return 1; break;
173 case 18: return 2; break;
174 case 19: return 3; break;
175 case 23: return 4; break;
176 case 27: return 5; break;
177 case 31: return 6; break;
178 case -1: return 0; break; /* map MODE_ANY to user mode */
179 default:
180 ERROR("invalid mode value encountered");
181 return -1;
182 }
183 }
184
185 /* map linear number to mode bits */
186 enum armv4_5_mode armv4_5_number_to_mode(int number)
187 {
188 switch(number)
189 {
190 case 0: return ARMV4_5_MODE_USR; break;
191 case 1: return ARMV4_5_MODE_FIQ; break;
192 case 2: return ARMV4_5_MODE_IRQ; break;
193 case 3: return ARMV4_5_MODE_SVC; break;
194 case 4: return ARMV4_5_MODE_ABT; break;
195 case 5: return ARMV4_5_MODE_UND; break;
196 case 6: return ARMV4_5_MODE_SYS; break;
197 default:
198 ERROR("mode index out of bounds");
199 return -1;
200 }
201 };
202
203 int armv4_5_get_core_reg(reg_t *reg)
204 {
205 int retval;
206 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
207 target_t *target = armv4_5->target;
208
209 if (target->state != TARGET_HALTED)
210 {
211 return ERROR_TARGET_NOT_HALTED;
212 }
213
214 //retval = armv4_5->armv4_5_common->full_context(target);
215 retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
216
217 return retval;
218 }
219
220 int armv4_5_set_core_reg(reg_t *reg, u32 value)
221 {
222 armv4_5_core_reg_t *armv4_5 = reg->arch_info;
223 target_t *target = armv4_5->target;
224
225 if (target->state != TARGET_HALTED)
226 {
227 return ERROR_TARGET_NOT_HALTED;
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(target_t *target)
238 {
239 armv4_5_common_t *armv4_5 = target->arch_info;
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 reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5_common)
252 {
253 int num_regs = 37;
254 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
255 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
256 armv4_5_core_reg_t *arch_info = malloc(sizeof(reg_t) * 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 for (i = 0; i < 37; i++)
268 {
269 arch_info[i] = armv4_5_core_reg_list_arch_info[i];
270 arch_info[i].target = target;
271 arch_info[i].armv4_5_common = armv4_5_common;
272 reg_list[i].name = armv4_5_core_reg_list[i];
273 reg_list[i].size = 32;
274 reg_list[i].value = calloc(1, 4);
275 reg_list[i].dirty = 0;
276 reg_list[i].valid = 0;
277 reg_list[i].bitfield_desc = NULL;
278 reg_list[i].num_bitfields = 0;
279 reg_list[i].arch_type = armv4_5_core_reg_arch_type;
280 reg_list[i].arch_info = &arch_info[i];
281 }
282
283 return cache;
284 }
285
286 int armv4_5_arch_state(struct target_s *target, char *buf, int buf_size)
287 {
288 armv4_5_common_t *armv4_5 = target->arch_info;
289
290 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
291 {
292 ERROR("BUG: called for a non-ARMv4/5 target");
293 exit(-1);
294 }
295
296 snprintf(buf, buf_size,
297 "target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x",
298 armv4_5_state_strings[armv4_5->core_state],
299 target_debug_reason_strings[target->debug_reason],
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 int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
308 {
309 char output[128];
310 int output_len;
311 int mode, num;
312 target_t *target = get_current_target(cmd_ctx);
313 armv4_5_common_t *armv4_5 = target->arch_info;
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 for (num = 0; num <= 15; num++)
328 {
329 output_len = 0;
330 for (mode = 0; mode < 6; mode++)
331 {
332 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).valid)
333 {
334 armv4_5->full_context(target);
335 }
336 output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
337 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
338 }
339 command_print(cmd_ctx, output);
340 }
341 command_print(cmd_ctx, " cpsr: %8.8x spsr_fiq: %8.8x spsr_irq: %8.8x spsr_svc: %8.8x spsr_abt: %8.8x spsr_und: %8.8x",
342 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
343 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
344 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32),
345 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_SVC].value, 0, 32),
346 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_ABT].value, 0, 32),
347 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_UND].value, 0, 32));
348
349 return ERROR_OK;
350 }
351
352 int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
353 {
354 target_t *target = get_current_target(cmd_ctx);
355 armv4_5_common_t *armv4_5 = target->arch_info;
356
357 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
358 {
359 command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
360 return ERROR_OK;
361 }
362
363 if (argc > 0)
364 {
365 if (strcmp(args[0], "arm") == 0)
366 {
367 armv4_5->core_state = ARMV4_5_STATE_ARM;
368 }
369 if (strcmp(args[0], "thumb") == 0)
370 {
371 armv4_5->core_state = ARMV4_5_STATE_THUMB;
372 }
373 }
374
375 command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
376
377 return ERROR_OK;
378 }
379
380 int armv4_5_register_commands(struct command_context_s *cmd_ctx)
381 {
382 command_t *armv4_5_cmd;
383
384 armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, NULL);
385
386 register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
387 register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
388
389 return ERROR_OK;
390 }
391
392 int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
393 {
394 armv4_5_common_t *armv4_5 = target->arch_info;
395 int i;
396
397 if (target->state != TARGET_HALTED)
398 {
399 return ERROR_TARGET_NOT_HALTED;
400 }
401
402 *reg_list_size = 26;
403 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
404
405 for (i = 0; i < 16; i++)
406 {
407 (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
408 }
409
410 for (i = 16; i < 24; i++)
411 {
412 (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
413 }
414
415 (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
416 (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
417
418 return ERROR_OK;
419 }
420
421 int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
422 {
423 armv4_5_common_t *armv4_5 = target->arch_info;
424 armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info;
425 enum armv4_5_state core_state = armv4_5->core_state;
426 enum armv4_5_mode core_mode = armv4_5->core_mode;
427 u32 context[17];
428 u32 cpsr;
429 int exit_breakpoint_size = 0;
430 int i;
431 int retval = ERROR_OK;
432
433 if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
434 {
435 ERROR("current target isn't an ARMV4/5 target");
436 return ERROR_TARGET_INVALID;
437 }
438
439 if (target->state != TARGET_HALTED)
440 {
441 WARNING("target not halted");
442 return ERROR_TARGET_NOT_HALTED;
443 }
444
445 for (i = 0; i <= 16; i++)
446 {
447 if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
448 armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
449 context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
450 }
451 cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
452
453 for (i = 0; i < num_mem_params; i++)
454 {
455 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
456 }
457
458 for (i = 0; i < num_reg_params; i++)
459 {
460 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
461 if (!reg)
462 {
463 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
464 exit(-1);
465 }
466
467 if (reg->size != reg_params[i].size)
468 {
469 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
470 exit(-1);
471 }
472
473 armv4_5_set_core_reg(reg, buf_get_u32(reg_params[i].value, 0, 32));
474 }
475
476 armv4_5->core_state = armv4_5_algorithm_info->core_state;
477 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
478 exit_breakpoint_size = 4;
479 else if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
480 exit_breakpoint_size = 2;
481 else
482 {
483 ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
484 exit(-1);
485 }
486
487 if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
488 {
489 DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info->core_mode);
490 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 5, armv4_5_algorithm_info->core_mode);
491 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
492 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
493 }
494
495 if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
496 {
497 ERROR("can't add breakpoint to finish algorithm execution");
498 return ERROR_TARGET_FAILURE;
499 }
500
501 target->type->resume(target, 0, entry_point, 1, 1);
502 target->type->poll(target);
503
504 while (target->state != TARGET_HALTED)
505 {
506 usleep(10000);
507 target->type->poll(target);
508 if ((timeout_ms -= 10) <= 0)
509 {
510 ERROR("timeout waiting for algorithm to complete, trying to halt target");
511 target->type->halt(target);
512 timeout_ms = 1000;
513 while (target->state != TARGET_HALTED)
514 {
515 usleep(10000);
516 target->type->poll(target);
517 if ((timeout_ms -= 10) <= 0)
518 {
519 ERROR("target didn't reenter debug state, exiting");
520 exit(-1);
521 }
522 }
523 retval = ERROR_TARGET_TIMEOUT;
524 }
525 }
526
527 breakpoint_remove(target, exit_point);
528
529 for (i = 0; i < num_mem_params; i++)
530 {
531 if (mem_params[i].direction != PARAM_OUT)
532 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
533 }
534
535 for (i = 0; i < num_reg_params; i++)
536 {
537 if (reg_params[i].direction != PARAM_OUT)
538 {
539
540 reg_t *reg = register_get_by_name(armv4_5->core_cache, reg_params[i].reg_name, 0);
541 if (!reg)
542 {
543 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
544 exit(-1);
545 }
546
547 if (reg->size != reg_params[i].size)
548 {
549 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
550 exit(-1);
551 }
552
553 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
554 }
555 }
556
557 for (i = 0; i <= 16; i++)
558 {
559 DEBUG("restoring register %s with value 0x%8.8x", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32));
560 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
561 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
562 ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
563 }
564 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr);
565 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
566 armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
567
568 armv4_5->core_state = core_state;
569 armv4_5->core_mode = core_mode;
570
571 return retval;
572 }
573
574 int armv4_5_init_arch_info(target_t *target, armv4_5_common_t *armv4_5)
575 {
576 target->arch_info = armv4_5;
577
578 armv4_5->common_magic = ARMV4_5_COMMON_MAGIC;
579 armv4_5->core_state = ARMV4_5_STATE_ARM;
580 armv4_5->core_mode = ARMV4_5_MODE_USR;
581
582 return ERROR_OK;
583 }

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)