The "arm9tdmi.c" file is more of a generic ARM9 support file:
[openocd.git] / src / target / arm9tdmi.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 Hongtao Zheng *
9 * hontor@126.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 "arm9tdmi.h"
31 #include "target_type.h"
32
33
34 /*
35 * NOTE: this holds code that's used with multiple ARM9 processors:
36 * - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
37 * - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores
38 * - ARM9EJS (ARMv5TEJ) ... in ARM926 core
39 *
40 * In short, the file name is a misnomer ... it is NOT specific to
41 * that first generation ARM9 processor, or cores using it.
42 */
43
44 #if 0
45 #define _DEBUG_INSTRUCTION_EXECUTION_
46 #endif
47
48 /* cli handling */
49 int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
50
51 /* forward declarations */
52 int arm9tdmi_target_create(struct target_s *target, Jim_Interp *interp);
53
54 int arm9tdmi_quit(void);
55
56 target_type_t arm9tdmi_target =
57 {
58 .name = "arm9tdmi",
59
60 .poll = arm7_9_poll,
61 .arch_state = armv4_5_arch_state,
62
63 .target_request_data = arm7_9_target_request_data,
64
65 .halt = arm7_9_halt,
66 .resume = arm7_9_resume,
67 .step = arm7_9_step,
68
69 .assert_reset = arm7_9_assert_reset,
70 .deassert_reset = arm7_9_deassert_reset,
71 .soft_reset_halt = arm7_9_soft_reset_halt,
72
73 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
74
75 .read_memory = arm7_9_read_memory,
76 .write_memory = arm7_9_write_memory,
77 .bulk_write_memory = arm7_9_bulk_write_memory,
78 .checksum_memory = arm7_9_checksum_memory,
79 .blank_check_memory = arm7_9_blank_check_memory,
80
81 .run_algorithm = armv4_5_run_algorithm,
82
83 .add_breakpoint = arm7_9_add_breakpoint,
84 .remove_breakpoint = arm7_9_remove_breakpoint,
85 .add_watchpoint = arm7_9_add_watchpoint,
86 .remove_watchpoint = arm7_9_remove_watchpoint,
87
88 .register_commands = arm9tdmi_register_commands,
89 .target_create = arm9tdmi_target_create,
90 .init_target = arm9tdmi_init_target,
91 .examine = arm9tdmi_examine,
92 .quit = arm9tdmi_quit
93 };
94
95 arm9tdmi_vector_t arm9tdmi_vectors[] =
96 {
97 {"reset", ARM9TDMI_RESET_VECTOR},
98 {"undef", ARM9TDMI_UNDEF_VECTOR},
99 {"swi", ARM9TDMI_SWI_VECTOR},
100 {"pabt", ARM9TDMI_PABT_VECTOR},
101 {"dabt", ARM9TDMI_DABT_VECTOR},
102 {"reserved", ARM9TDMI_RESERVED_VECTOR},
103 {"irq", ARM9TDMI_IRQ_VECTOR},
104 {"fiq", ARM9TDMI_FIQ_VECTOR},
105 {0, 0},
106 };
107
108 int arm9tdmi_examine_debug_reason(target_t *target)
109 {
110 int retval = ERROR_OK;
111 /* get pointers to arch-specific information */
112 armv4_5_common_t *armv4_5 = target->arch_info;
113 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
114
115 /* only check the debug reason if we don't know it already */
116 if ((target->debug_reason != DBG_REASON_DBGRQ)
117 && (target->debug_reason != DBG_REASON_SINGLESTEP))
118 {
119 scan_field_t fields[3];
120 uint8_t databus[4];
121 uint8_t instructionbus[4];
122 uint8_t debug_reason;
123
124 jtag_set_end_state(TAP_DRPAUSE);
125
126 fields[0].tap = arm7_9->jtag_info.tap;
127 fields[0].num_bits = 32;
128 fields[0].out_value = NULL;
129 fields[0].in_value = databus;
130
131 fields[1].tap = arm7_9->jtag_info.tap;
132 fields[1].num_bits = 3;
133 fields[1].out_value = NULL;
134 fields[1].in_value = &debug_reason;
135
136 fields[2].tap = arm7_9->jtag_info.tap;
137 fields[2].num_bits = 32;
138 fields[2].out_value = NULL;
139 fields[2].in_value = instructionbus;
140
141 if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1)) != ERROR_OK)
142 {
143 return retval;
144 }
145 arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
146
147 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
148 if ((retval = jtag_execute_queue()) != ERROR_OK)
149 {
150 return retval;
151 }
152
153 fields[0].in_value = NULL;
154 fields[0].out_value = databus;
155 fields[1].in_value = NULL;
156 fields[1].out_value = &debug_reason;
157 fields[2].in_value = NULL;
158 fields[2].out_value = instructionbus;
159
160 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
161
162 if (debug_reason & 0x4)
163 if (debug_reason & 0x2)
164 target->debug_reason = DBG_REASON_WPTANDBKPT;
165 else
166 target->debug_reason = DBG_REASON_WATCHPOINT;
167 else
168 target->debug_reason = DBG_REASON_BREAKPOINT;
169 }
170
171 return ERROR_OK;
172 }
173
174 /* put an instruction in the ARM9TDMI pipeline or write the data bus, and optionally read data */
175 int arm9tdmi_clock_out(arm_jtag_t *jtag_info, uint32_t instr, uint32_t out, uint32_t *in, int sysspeed)
176 {
177 int retval = ERROR_OK;
178 scan_field_t fields[3];
179 uint8_t out_buf[4];
180 uint8_t instr_buf[4];
181 uint8_t sysspeed_buf = 0x0;
182
183 /* prepare buffer */
184 buf_set_u32(out_buf, 0, 32, out);
185
186 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
187
188 if (sysspeed)
189 buf_set_u32(&sysspeed_buf, 2, 1, 1);
190
191 jtag_set_end_state(TAP_DRPAUSE);
192 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
193 {
194 return retval;
195 }
196
197 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
198
199 fields[0].tap = jtag_info->tap;
200 fields[0].num_bits = 32;
201 fields[0].out_value = out_buf;
202 fields[0].in_value = NULL;
203
204 fields[1].tap = jtag_info->tap;
205 fields[1].num_bits = 3;
206 fields[1].out_value = &sysspeed_buf;
207 fields[1].in_value = NULL;
208
209 fields[2].tap = jtag_info->tap;
210 fields[2].num_bits = 32;
211 fields[2].out_value = instr_buf;
212 fields[2].in_value = NULL;
213
214 if (in)
215 {
216 fields[0].in_value = (uint8_t *)in;
217 jtag_add_dr_scan(3, fields, jtag_get_end_state());
218
219 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
220 }
221 else
222 {
223 jtag_add_dr_scan(3, fields, jtag_get_end_state());
224 }
225
226 jtag_add_runtest(0, jtag_get_end_state());
227
228 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
229 {
230 if ((retval = jtag_execute_queue()) != ERROR_OK)
231 {
232 return retval;
233 }
234
235 if (in)
236 {
237 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
238 }
239 else
240 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
241 }
242 #endif
243
244 return ERROR_OK;
245 }
246
247 /* just read data (instruction and data-out = don't care) */
248 int arm9tdmi_clock_data_in(arm_jtag_t *jtag_info, uint32_t *in)
249 {
250 int retval = ERROR_OK;;
251 scan_field_t fields[3];
252
253 jtag_set_end_state(TAP_DRPAUSE);
254 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
255 {
256 return retval;
257 }
258
259 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
260
261 fields[0].tap = jtag_info->tap;
262 fields[0].num_bits = 32;
263 fields[0].out_value = NULL;
264 fields[0].in_value = (uint8_t *)in;
265
266 fields[1].tap = jtag_info->tap;
267 fields[1].num_bits = 3;
268 fields[1].out_value = NULL;
269 fields[1].in_value = NULL;
270
271 fields[2].tap = jtag_info->tap;
272 fields[2].num_bits = 32;
273 fields[2].out_value = NULL;
274 fields[2].in_value = NULL;
275
276 jtag_add_dr_scan(3, fields, jtag_get_end_state());
277
278 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
279
280 jtag_add_runtest(0, jtag_get_end_state());
281
282 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
283 {
284 if ((retval = jtag_execute_queue()) != ERROR_OK)
285 {
286 return retval;
287 }
288
289 if (in)
290 {
291 LOG_DEBUG("in: 0x%8.8x", *in);
292 }
293 else
294 {
295 LOG_ERROR("BUG: called with in == NULL");
296 }
297 }
298 #endif
299
300 return ERROR_OK;
301 }
302
303 extern void arm_endianness(uint8_t *tmp, void *in, int size, int be, int flip);
304
305 static int arm9endianness(jtag_callback_data_t arg, jtag_callback_data_t size, jtag_callback_data_t be, jtag_callback_data_t captured)
306 {
307 uint8_t *in = (uint8_t *)arg;
308 arm_endianness((uint8_t *)captured, in, (int)size, (int)be, 0);
309 return ERROR_OK;
310 }
311
312 /* clock the target, and read the databus
313 * the *in pointer points to a buffer where elements of 'size' bytes
314 * are stored in big (be == 1) or little (be == 0) endianness
315 */
316 int arm9tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
317 {
318 int retval = ERROR_OK;
319 scan_field_t fields[3];
320
321 jtag_set_end_state(TAP_DRPAUSE);
322 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
323 {
324 return retval;
325 }
326
327 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
328
329 fields[0].tap = jtag_info->tap;
330 fields[0].num_bits = 32;
331 fields[0].out_value = NULL;
332 jtag_alloc_in_value32(&fields[0]);
333
334 fields[1].tap = jtag_info->tap;
335 fields[1].num_bits = 3;
336 fields[1].out_value = NULL;
337 fields[1].in_value = NULL;
338
339 fields[2].tap = jtag_info->tap;
340 fields[2].num_bits = 32;
341 fields[2].out_value = NULL;
342 fields[2].in_value = NULL;
343
344 jtag_add_dr_scan(3, fields, jtag_get_end_state());
345
346 jtag_add_callback4(arm9endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[0].in_value);
347
348 jtag_add_runtest(0, jtag_get_end_state());
349
350 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
351 {
352 if ((retval = jtag_execute_queue()) != ERROR_OK)
353 {
354 return retval;
355 }
356
357 if (in)
358 {
359 LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
360 }
361 else
362 {
363 LOG_ERROR("BUG: called with in == NULL");
364 }
365 }
366 #endif
367
368 return ERROR_OK;
369 }
370
371 void arm9tdmi_change_to_arm(target_t *target, uint32_t *r0, uint32_t *pc)
372 {
373 int retval = ERROR_OK;
374 /* get pointers to arch-specific information */
375 armv4_5_common_t *armv4_5 = target->arch_info;
376 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
377 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
378
379 /* save r0 before using it and put system in ARM state
380 * to allow common handling of ARM and THUMB debugging */
381
382 /* fetch STR r0, [r0] */
383 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
384 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
385 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
386 /* STR r0, [r0] in Memory */
387 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
388
389 /* MOV r0, r15 fetched, STR in Decode */
390 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
391 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
392 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
393 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
395 /* nothing fetched, STR r0, [r0] in Memory */
396 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
397
398 /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
399 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
400 /* LDR in Decode */
401 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
402 /* LDR in Execute */
403 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
404 /* LDR in Memory (to account for interlock) */
405 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
406
407 /* fetch BX */
408 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
409 /* NOP fetched, BX in Decode, MOV in Execute */
410 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
411 /* NOP fetched, BX in Execute (1) */
412 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
413
414 if ((retval = jtag_execute_queue()) != ERROR_OK)
415 {
416 return;
417 }
418
419 /* fix program counter:
420 * MOV r0, r15 was the 5th instruction (+8)
421 * reading PC in Thumb state gives address of instruction + 4
422 */
423 *pc -= 0xc;
424 }
425
426 void arm9tdmi_read_core_regs(target_t *target, uint32_t mask, uint32_t* core_regs[16])
427 {
428 int i;
429 /* get pointers to arch-specific information */
430 armv4_5_common_t *armv4_5 = target->arch_info;
431 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
432 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
433
434 /* STMIA r0-15, [r0] at debug speed
435 * register values will start to appear on 4th DCLK
436 */
437 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
438
439 /* fetch NOP, STM in DECODE stage */
440 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
441 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
442 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
443
444 for (i = 0; i <= 15; i++)
445 {
446 if (mask & (1 << i))
447 /* nothing fetched, STM in MEMORY (i'th cycle) */
448 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
449 }
450 }
451
452 void arm9tdmi_read_core_regs_target_buffer(target_t *target, uint32_t mask, void* buffer, int size)
453 {
454 int i;
455 /* get pointers to arch-specific information */
456 armv4_5_common_t *armv4_5 = target->arch_info;
457 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
458 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
459 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
460 uint32_t *buf_u32 = buffer;
461 uint16_t *buf_u16 = buffer;
462 uint8_t *buf_u8 = buffer;
463
464 /* STMIA r0-15, [r0] at debug speed
465 * register values will start to appear on 4th DCLK
466 */
467 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
468
469 /* fetch NOP, STM in DECODE stage */
470 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
471 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
472 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
473
474 for (i = 0; i <= 15; i++)
475 {
476 if (mask & (1 << i))
477 /* nothing fetched, STM in MEMORY (i'th cycle) */
478 switch (size)
479 {
480 case 4:
481 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
482 break;
483 case 2:
484 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
485 break;
486 case 1:
487 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
488 break;
489 }
490 }
491 }
492
493 void arm9tdmi_read_xpsr(target_t *target, uint32_t *xpsr, int spsr)
494 {
495 /* get pointers to arch-specific information */
496 armv4_5_common_t *armv4_5 = target->arch_info;
497 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
498 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
499
500 /* MRS r0, cpsr */
501 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
502 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
503 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
504 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
505 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
506
507 /* STR r0, [r15] */
508 arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
509 /* fetch NOP, STR in DECODE stage */
510 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
511 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
512 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
513 /* nothing fetched, STR in MEMORY */
514 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
515 }
516
517 void arm9tdmi_write_xpsr(target_t *target, uint32_t xpsr, int spsr)
518 {
519 /* get pointers to arch-specific information */
520 armv4_5_common_t *armv4_5 = target->arch_info;
521 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
522 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
523
524 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
525
526 /* MSR1 fetched */
527 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
528 /* MSR2 fetched, MSR1 in DECODE */
529 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
530 /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
531 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
532 /* nothing fetched, MSR1 in EXECUTE (2) */
533 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
534 /* nothing fetched, MSR1 in EXECUTE (3) */
535 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
536 /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
537 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
538 /* nothing fetched, MSR2 in EXECUTE (2) */
539 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
540 /* nothing fetched, MSR2 in EXECUTE (3) */
541 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
542 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
543 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
544 /* nothing fetched, MSR3 in EXECUTE (2) */
545 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
546 /* nothing fetched, MSR3 in EXECUTE (3) */
547 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
548 /* NOP fetched, MSR4 in EXECUTE (1) */
549 /* last MSR writes flags, which takes only one cycle */
550 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
551 }
552
553 void arm9tdmi_write_xpsr_im8(target_t *target, uint8_t xpsr_im, int rot, int spsr)
554 {
555 /* get pointers to arch-specific information */
556 armv4_5_common_t *armv4_5 = target->arch_info;
557 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
558 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
559
560 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
561
562 /* MSR fetched */
563 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
564 /* NOP fetched, MSR in DECODE */
565 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
566 /* NOP fetched, MSR in EXECUTE (1) */
567 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
568
569 /* rot == 4 writes flags, which takes only one cycle */
570 if (rot != 4)
571 {
572 /* nothing fetched, MSR in EXECUTE (2) */
573 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
574 /* nothing fetched, MSR in EXECUTE (3) */
575 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
576 }
577 }
578
579 void arm9tdmi_write_core_regs(target_t *target, uint32_t mask, uint32_t core_regs[16])
580 {
581 int i;
582 /* get pointers to arch-specific information */
583 armv4_5_common_t *armv4_5 = target->arch_info;
584 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
585 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
586
587 /* LDMIA r0-15, [r0] at debug speed
588 * register values will start to appear on 4th DCLK
589 */
590 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
591
592 /* fetch NOP, LDM in DECODE stage */
593 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
594 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
595 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
596
597 for (i = 0; i <= 15; i++)
598 {
599 if (mask & (1 << i))
600 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
601 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
602 }
603 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
604 }
605
606 void arm9tdmi_load_word_regs(target_t *target, uint32_t mask)
607 {
608 /* get pointers to arch-specific information */
609 armv4_5_common_t *armv4_5 = target->arch_info;
610 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
611 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
612
613 /* put system-speed load-multiple into the pipeline */
614 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
615 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
616 }
617
618 void arm9tdmi_load_hword_reg(target_t *target, int num)
619 {
620 /* get pointers to arch-specific information */
621 armv4_5_common_t *armv4_5 = target->arch_info;
622 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
623 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
624
625 /* put system-speed load half-word into the pipeline */
626 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
627 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
628 }
629
630 void arm9tdmi_load_byte_reg(target_t *target, int num)
631 {
632 /* get pointers to arch-specific information */
633 armv4_5_common_t *armv4_5 = target->arch_info;
634 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
635 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
636
637 /* put system-speed load byte into the pipeline */
638 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
639 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
640 }
641
642 void arm9tdmi_store_word_regs(target_t *target, uint32_t mask)
643 {
644 /* get pointers to arch-specific information */
645 armv4_5_common_t *armv4_5 = target->arch_info;
646 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
647 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
648
649 /* put system-speed store-multiple into the pipeline */
650 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
651 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
652 }
653
654 void arm9tdmi_store_hword_reg(target_t *target, int num)
655 {
656 /* get pointers to arch-specific information */
657 armv4_5_common_t *armv4_5 = target->arch_info;
658 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
659 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
660
661 /* put system-speed store half-word into the pipeline */
662 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
663 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
664 }
665
666 void arm9tdmi_store_byte_reg(target_t *target, int num)
667 {
668 /* get pointers to arch-specific information */
669 armv4_5_common_t *armv4_5 = target->arch_info;
670 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
671 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
672
673 /* put system-speed store byte into the pipeline */
674 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
675 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
676 }
677
678 void arm9tdmi_write_pc(target_t *target, uint32_t pc)
679 {
680 /* get pointers to arch-specific information */
681 armv4_5_common_t *armv4_5 = target->arch_info;
682 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
683 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
684
685 /* LDMIA r0-15, [r0] at debug speed
686 * register values will start to appear on 4th DCLK
687 */
688 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
689
690 /* fetch NOP, LDM in DECODE stage */
691 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
692 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
693 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
694 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
695 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
696 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
697 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
698 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
699 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
700 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
701 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
702 }
703
704 void arm9tdmi_branch_resume(target_t *target)
705 {
706 /* get pointers to arch-specific information */
707 armv4_5_common_t *armv4_5 = target->arch_info;
708 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
709 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
710
711 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
712 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
713 }
714
715 void arm9tdmi_branch_resume_thumb(target_t *target)
716 {
717 LOG_DEBUG("-");
718
719 /* get pointers to arch-specific information */
720 armv4_5_common_t *armv4_5 = target->arch_info;
721 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
722 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
723 reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
724
725 /* LDMIA r0-15, [r0] at debug speed
726 * register values will start to appear on 4th DCLK
727 */
728 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
729
730 /* fetch NOP, LDM in DECODE stage */
731 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
732 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
733 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
734 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
735 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
736 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
737 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
738
739 /* Branch and eXchange */
740 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
741
742 embeddedice_read_reg(dbg_stat);
743
744 /* fetch NOP, BX in DECODE stage */
745 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
746
747 embeddedice_read_reg(dbg_stat);
748
749 /* fetch NOP, BX in EXECUTE stage (1st cycle) */
750 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
751
752 /* target is now in Thumb state */
753 embeddedice_read_reg(dbg_stat);
754
755 /* load r0 value, MOV_IM in Decode*/
756 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
757 /* fetch NOP, LDR in Decode, MOV_IM in Execute */
758 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
759 /* fetch NOP, LDR in Execute */
760 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
761 /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
762 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
763 /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
764 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
765
766 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
767 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
768
769 embeddedice_read_reg(dbg_stat);
770
771 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
772 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
773 }
774
775 void arm9tdmi_enable_single_step(target_t *target, uint32_t next_pc)
776 {
777 /* get pointers to arch-specific information */
778 armv4_5_common_t *armv4_5 = target->arch_info;
779 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
780
781 if (arm7_9->has_single_step)
782 {
783 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
784 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
785 }
786 else
787 {
788 arm7_9_enable_eice_step(target, next_pc);
789 }
790 }
791
792 void arm9tdmi_disable_single_step(target_t *target)
793 {
794 /* get pointers to arch-specific information */
795 armv4_5_common_t *armv4_5 = target->arch_info;
796 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
797
798 if (arm7_9->has_single_step)
799 {
800 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
801 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
802 }
803 else
804 {
805 arm7_9_disable_eice_step(target);
806 }
807 }
808
809 void arm9tdmi_build_reg_cache(target_t *target)
810 {
811 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
812 /* get pointers to arch-specific information */
813 armv4_5_common_t *armv4_5 = target->arch_info;
814
815 (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
816 armv4_5->core_cache = (*cache_p);
817 }
818
819 int arm9tdmi_examine(struct target_s *target)
820 {
821 /* get pointers to arch-specific information */
822 int retval;
823 armv4_5_common_t *armv4_5 = target->arch_info;
824 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
825 if (!target_was_examined(target))
826 {
827 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
828 reg_cache_t *t;
829 /* one extra register (vector catch) */
830 t = embeddedice_build_reg_cache(target, arm7_9);
831 if (t == NULL)
832 return ERROR_FAIL;
833 (*cache_p) = t;
834 arm7_9->eice_cache = (*cache_p);
835
836 if (arm7_9->etm_ctx)
837 {
838 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
839 (*cache_p)->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
840 arm7_9->etm_ctx->reg_cache = (*cache_p)->next;
841 }
842 target_set_examined(target);
843 }
844 if ((retval = embeddedice_setup(target)) != ERROR_OK)
845 return retval;
846 if ((retval = arm7_9_setup(target)) != ERROR_OK)
847 return retval;
848 if (arm7_9->etm_ctx)
849 {
850 if ((retval = etm_setup(target)) != ERROR_OK)
851 return retval;
852 }
853 return ERROR_OK;
854 }
855
856 int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
857 {
858
859 arm9tdmi_build_reg_cache(target);
860
861 return ERROR_OK;
862 }
863
864 int arm9tdmi_quit(void)
865 {
866 return ERROR_OK;
867 }
868
869 int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, jtag_tap_t *tap)
870 {
871 armv4_5_common_t *armv4_5;
872 arm7_9_common_t *arm7_9;
873
874 arm7_9 = &arm9tdmi->arm7_9_common;
875 armv4_5 = &arm7_9->armv4_5_common;
876
877 /* prepare JTAG information for the new target */
878 arm7_9->jtag_info.tap = tap;
879 arm7_9->jtag_info.scann_size = 5;
880
881 /* register arch-specific functions */
882 arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
883 arm7_9->change_to_arm = arm9tdmi_change_to_arm;
884 arm7_9->read_core_regs = arm9tdmi_read_core_regs;
885 arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
886 arm7_9->read_xpsr = arm9tdmi_read_xpsr;
887
888 arm7_9->write_xpsr = arm9tdmi_write_xpsr;
889 arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
890 arm7_9->write_core_regs = arm9tdmi_write_core_regs;
891
892 arm7_9->load_word_regs = arm9tdmi_load_word_regs;
893 arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
894 arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
895
896 arm7_9->store_word_regs = arm9tdmi_store_word_regs;
897 arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
898 arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
899
900 arm7_9->write_pc = arm9tdmi_write_pc;
901 arm7_9->branch_resume = arm9tdmi_branch_resume;
902 arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
903
904 arm7_9->enable_single_step = arm9tdmi_enable_single_step;
905 arm7_9->disable_single_step = arm9tdmi_disable_single_step;
906
907 arm7_9->pre_debug_entry = NULL;
908 arm7_9->post_debug_entry = NULL;
909
910 arm7_9->pre_restore_context = NULL;
911 arm7_9->post_restore_context = NULL;
912
913 /* initialize arch-specific breakpoint handling */
914 arm7_9->arm_bkpt = 0xdeeedeee;
915 arm7_9->thumb_bkpt = 0xdeee;
916
917 arm7_9->dbgreq_adjust_pc = 3;
918 arm7_9->arch_info = arm9tdmi;
919
920 arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;
921 arm9tdmi->arch_info = NULL;
922
923 arm7_9_init_arch_info(target, arm7_9);
924
925 /* override use of DBGRQ, this is safe on ARM9TDMI */
926 arm7_9->use_dbgrq = 1;
927
928 /* all ARM9s have the vector catch register */
929 arm7_9->has_vector_catch = 1;
930
931 return ERROR_OK;
932 }
933
934 int arm9tdmi_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p)
935 {
936 armv4_5_common_t *armv4_5 = target->arch_info;
937 arm7_9_common_t *arm7_9;
938 arm9tdmi_common_t *arm9tdmi;
939
940 if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
941 {
942 return -1;
943 }
944
945 arm7_9 = armv4_5->arch_info;
946 if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
947 {
948 return -1;
949 }
950
951 arm9tdmi = arm7_9->arch_info;
952 if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
953 {
954 return -1;
955 }
956
957 *armv4_5_p = armv4_5;
958 *arm7_9_p = arm7_9;
959 *arm9tdmi_p = arm9tdmi;
960
961 return ERROR_OK;
962 }
963
964 int arm9tdmi_target_create(struct target_s *target, Jim_Interp *interp)
965 {
966 arm9tdmi_common_t *arm9tdmi = calloc(1,sizeof(arm9tdmi_common_t));
967
968 arm9tdmi_init_arch_info(target, arm9tdmi, target->tap);
969 arm9tdmi->arm7_9_common.armv4_5_common.is_armv4 = true;
970
971 return ERROR_OK;
972 }
973
974 int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)
975 {
976 int retval;
977 command_t *arm9tdmi_cmd;
978
979 retval = arm7_9_register_commands(cmd_ctx);
980 arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9tdmi",
981 NULL, COMMAND_ANY,
982 "arm9tdmi specific commands");
983 register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch",
984 handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC,
985 "catch arm9 vectors ['all'|'none'|'<vec1 vec2 ...>']");
986
987 return retval;
988 }
989
990 int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
991 {
992 target_t *target = get_current_target(cmd_ctx);
993 armv4_5_common_t *armv4_5;
994 arm7_9_common_t *arm7_9;
995 arm9tdmi_common_t *arm9tdmi;
996 reg_t *vector_catch;
997 uint32_t vector_catch_value;
998 int i, j;
999
1000 if (arm9tdmi_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi) != ERROR_OK)
1001 {
1002 command_print(cmd_ctx, "current target isn't an ARM9 based target");
1003 return ERROR_OK;
1004 }
1005
1006 vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
1007
1008 /* read the vector catch register if necessary */
1009 if (!vector_catch->valid)
1010 embeddedice_read_reg(vector_catch);
1011
1012 /* get the current setting */
1013 vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
1014
1015 if (argc > 0)
1016 {
1017 vector_catch_value = 0x0;
1018 if (strcmp(args[0], "all") == 0)
1019 {
1020 vector_catch_value = 0xdf;
1021 }
1022 else if (strcmp(args[0], "none") == 0)
1023 {
1024 /* do nothing */
1025 }
1026 else
1027 {
1028 for (i = 0; i < argc; i++)
1029 {
1030 /* go through list of vectors */
1031 for (j = 0; arm9tdmi_vectors[j].name; j++)
1032 {
1033 if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
1034 {
1035 vector_catch_value |= arm9tdmi_vectors[j].value;
1036 break;
1037 }
1038 }
1039
1040 /* complain if vector wasn't found */
1041 if (!arm9tdmi_vectors[j].name)
1042 {
1043 command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
1044
1045 /* reread current setting */
1046 vector_catch_value = buf_get_u32(
1047 vector_catch->value,
1048 0, 8);
1049
1050 break;
1051 }
1052 }
1053 }
1054
1055 /* store new settings */
1056 buf_set_u32(vector_catch->value, 0, 8, vector_catch_value);
1057 embeddedice_store_reg(vector_catch);
1058 }
1059
1060 /* output current settings (skip RESERVED vector) */
1061 for (i = 0; i < 8; i++)
1062 {
1063 if (i != 5)
1064 {
1065 command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
1066 (vector_catch_value & (1 << i)) ? "catch" : "don't catch");
1067 }
1068 }
1069
1070 return ERROR_OK;
1071 }

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)