gdb_server, target: Add target_address_bits()
[openocd.git] / src / target / mips32.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * Copyright (C) 2011 by Drasko DRASKOVIC *
11 * drasko.draskovic@gmail.com *
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 * This program is distributed in the hope that it will be useful, *
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21 * GNU General Public License for more details. *
22 * *
23 * You should have received a copy of the GNU General Public License *
24 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
25 ***************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "mips32.h"
32 #include "breakpoints.h"
33 #include "algorithm.h"
34 #include "register.h"
35
36 static const char *mips_isa_strings[] = {
37 "MIPS32", "MIPS16", "", "MICRO MIPS32",
38 };
39
40 #define MIPS32_GDB_DUMMY_FP_REG 1
41
42 /*
43 * GDB registers
44 * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml
45 */
46 static const struct {
47 unsigned id;
48 const char *name;
49 enum reg_type type;
50 const char *group;
51 const char *feature;
52 int flag;
53 } mips32_regs[] = {
54 { 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
55 { 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
56 { 2, "r2", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
57 { 3, "r3", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
58 { 4, "r4", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
59 { 5, "r5", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
60 { 6, "r6", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
61 { 7, "r7", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
62 { 8, "r8", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
63 { 9, "r9", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
64 { 10, "r10", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
65 { 11, "r11", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
66 { 12, "r12", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
67 { 13, "r13", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
68 { 14, "r14", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
69 { 15, "r15", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
70 { 16, "r16", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
71 { 17, "r17", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
72 { 18, "r18", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
73 { 19, "r19", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
74 { 20, "r20", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
75 { 21, "r21", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
76 { 22, "r22", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
77 { 23, "r23", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
78 { 24, "r24", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
79 { 25, "r25", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
80 { 26, "r26", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
81 { 27, "r27", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
82 { 28, "r28", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
83 { 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
84 { 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
85 { 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
86 { 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
87 { 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
88 { 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
89 { 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
90 { 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
91 { 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
92
93 { 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
94 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
95 { 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
96 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
97 { 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
98 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
99 { 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
100 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
101 { 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
102 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
103 { 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
104 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
105 { 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
106 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
107 { 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
108 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
109 { 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
110 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
111 { 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
112 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
113 { 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
114 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
115 { 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
116 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
117 { 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
118 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
119 { 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
120 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
121 { 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
122 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
123 { 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
124 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
125 { 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
126 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
127 { 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
128 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
129 { 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
130 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
131 { 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
132 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
133 { 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
134 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
135 { 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
136 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
137 { 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
138 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
139 { 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
140 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
141 { 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
142 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
143 { 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
144 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
145 { 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
146 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
147 { 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
148 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
149 { 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
150 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
151 { 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
152 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
153 { 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
154 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
155 { 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
156 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
157 { 70, "fcsr", REG_TYPE_INT, "float",
158 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
159 { 71, "fir", REG_TYPE_INT, "float",
160 "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
161 };
162
163
164 #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
165
166 static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
167
168 static int mips32_get_core_reg(struct reg *reg)
169 {
170 int retval;
171 struct mips32_core_reg *mips32_reg = reg->arch_info;
172 struct target *target = mips32_reg->target;
173 struct mips32_common *mips32_target = target_to_mips32(target);
174
175 if (target->state != TARGET_HALTED)
176 return ERROR_TARGET_NOT_HALTED;
177
178 retval = mips32_target->read_core_reg(target, mips32_reg->num);
179
180 return retval;
181 }
182
183 static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
184 {
185 struct mips32_core_reg *mips32_reg = reg->arch_info;
186 struct target *target = mips32_reg->target;
187 uint32_t value = buf_get_u32(buf, 0, 32);
188
189 if (target->state != TARGET_HALTED)
190 return ERROR_TARGET_NOT_HALTED;
191
192 buf_set_u32(reg->value, 0, 32, value);
193 reg->dirty = 1;
194 reg->valid = 1;
195
196 return ERROR_OK;
197 }
198
199 static int mips32_read_core_reg(struct target *target, unsigned int num)
200 {
201 uint32_t reg_value;
202
203 /* get pointers to arch-specific information */
204 struct mips32_common *mips32 = target_to_mips32(target);
205
206 if (num >= MIPS32_NUM_REGS)
207 return ERROR_COMMAND_SYNTAX_ERROR;
208
209 reg_value = mips32->core_regs[num];
210 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
211 mips32->core_cache->reg_list[num].valid = 1;
212 mips32->core_cache->reg_list[num].dirty = 0;
213
214 return ERROR_OK;
215 }
216
217 static int mips32_write_core_reg(struct target *target, unsigned int num)
218 {
219 uint32_t reg_value;
220
221 /* get pointers to arch-specific information */
222 struct mips32_common *mips32 = target_to_mips32(target);
223
224 if (num >= MIPS32_NUM_REGS)
225 return ERROR_COMMAND_SYNTAX_ERROR;
226
227 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
228 mips32->core_regs[num] = reg_value;
229 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
230 mips32->core_cache->reg_list[num].valid = 1;
231 mips32->core_cache->reg_list[num].dirty = 0;
232
233 return ERROR_OK;
234 }
235
236 int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
237 int *reg_list_size, enum target_register_class reg_class)
238 {
239 /* get pointers to arch-specific information */
240 struct mips32_common *mips32 = target_to_mips32(target);
241 unsigned int i;
242
243 /* include floating point registers */
244 *reg_list_size = MIPS32_NUM_REGS;
245 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
246
247 for (i = 0; i < MIPS32_NUM_REGS; i++)
248 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
249
250 return ERROR_OK;
251 }
252
253 int mips32_save_context(struct target *target)
254 {
255 unsigned int i;
256
257 /* get pointers to arch-specific information */
258 struct mips32_common *mips32 = target_to_mips32(target);
259 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
260
261 /* read core registers */
262 mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
263
264 for (i = 0; i < MIPS32_NUM_REGS; i++) {
265 if (!mips32->core_cache->reg_list[i].valid)
266 mips32->read_core_reg(target, i);
267 }
268
269 return ERROR_OK;
270 }
271
272 int mips32_restore_context(struct target *target)
273 {
274 unsigned int i;
275
276 /* get pointers to arch-specific information */
277 struct mips32_common *mips32 = target_to_mips32(target);
278 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
279
280 for (i = 0; i < MIPS32_NUM_REGS; i++) {
281 if (mips32->core_cache->reg_list[i].dirty)
282 mips32->write_core_reg(target, i);
283 }
284
285 /* write core regs */
286 mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
287
288 return ERROR_OK;
289 }
290
291 int mips32_arch_state(struct target *target)
292 {
293 struct mips32_common *mips32 = target_to_mips32(target);
294
295 LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
296 mips_isa_strings[mips32->isa_mode],
297 debug_reason_name(target),
298 buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
299
300 return ERROR_OK;
301 }
302
303 static const struct reg_arch_type mips32_reg_type = {
304 .get = mips32_get_core_reg,
305 .set = mips32_set_core_reg,
306 };
307
308 struct reg_cache *mips32_build_reg_cache(struct target *target)
309 {
310 /* get pointers to arch-specific information */
311 struct mips32_common *mips32 = target_to_mips32(target);
312
313 int num_regs = MIPS32_NUM_REGS;
314 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
315 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
316 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
317 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
318 struct reg_feature *feature;
319 int i;
320
321 /* Build the process context cache */
322 cache->name = "mips32 registers";
323 cache->next = NULL;
324 cache->reg_list = reg_list;
325 cache->num_regs = num_regs;
326 (*cache_p) = cache;
327 mips32->core_cache = cache;
328
329 for (i = 0; i < num_regs; i++) {
330 arch_info[i].num = mips32_regs[i].id;
331 arch_info[i].target = target;
332 arch_info[i].mips32_common = mips32;
333
334 reg_list[i].name = mips32_regs[i].name;
335 reg_list[i].size = 32;
336
337 if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) {
338 reg_list[i].value = mips32_gdb_dummy_fp_value;
339 reg_list[i].valid = 1;
340 reg_list[i].arch_info = NULL;
341 register_init_dummy(&reg_list[i]);
342 } else {
343 reg_list[i].value = calloc(1, 4);
344 reg_list[i].valid = 0;
345 reg_list[i].type = &mips32_reg_type;
346 reg_list[i].arch_info = &arch_info[i];
347
348 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
349 if (reg_list[i].reg_data_type)
350 reg_list[i].reg_data_type->type = mips32_regs[i].type;
351 else
352 LOG_ERROR("unable to allocate reg type list");
353 }
354
355 reg_list[i].dirty = 0;
356
357 reg_list[i].group = mips32_regs[i].group;
358 reg_list[i].number = i;
359 reg_list[i].exist = true;
360 reg_list[i].caller_save = true; /* gdb defaults to true */
361
362 feature = calloc(1, sizeof(struct reg_feature));
363 if (feature) {
364 feature->name = mips32_regs[i].feature;
365 reg_list[i].feature = feature;
366 } else
367 LOG_ERROR("unable to allocate feature list");
368 }
369
370 return cache;
371 }
372
373 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
374 {
375 target->arch_info = mips32;
376 mips32->common_magic = MIPS32_COMMON_MAGIC;
377 mips32->fast_data_area = NULL;
378 mips32->isa_imp = MIPS32_ONLY; /* default */
379
380 /* has breakpoint/watchpoint unit been scanned */
381 mips32->bp_scanned = 0;
382 mips32->data_break_list = NULL;
383
384 mips32->ejtag_info.tap = tap;
385 mips32->read_core_reg = mips32_read_core_reg;
386 mips32->write_core_reg = mips32_write_core_reg;
387 /* if unknown endianness defaults to little endian, 1 */
388 mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1;
389 mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE;
390 mips32->ejtag_info.mode = 0; /* Initial default value */
391 mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */
392 mips32->ejtag_info.config_regs = 0; /* no config register read */
393 return ERROR_OK;
394 }
395
396 /* run to exit point. return error if exit point was not reached. */
397 static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
398 int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32)
399 {
400 uint32_t pc;
401 int retval;
402 /* This code relies on the target specific resume() and poll()->debug_entry()
403 * sequence to write register values to the processor and the read them back */
404 retval = target_resume(target, 0, entry_point, 0, 1);
405 if (retval != ERROR_OK)
406 return retval;
407
408 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
409 /* If the target fails to halt due to the breakpoint, force a halt */
410 if (retval != ERROR_OK || target->state != TARGET_HALTED) {
411 retval = target_halt(target);
412 if (retval != ERROR_OK)
413 return retval;
414 retval = target_wait_state(target, TARGET_HALTED, 500);
415 if (retval != ERROR_OK)
416 return retval;
417 return ERROR_TARGET_TIMEOUT;
418 }
419
420 pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
421 if (exit_point && (pc != exit_point)) {
422 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
423 return ERROR_TARGET_TIMEOUT;
424 }
425
426 return ERROR_OK;
427 }
428
429 int mips32_run_algorithm(struct target *target, int num_mem_params,
430 struct mem_param *mem_params, int num_reg_params,
431 struct reg_param *reg_params, target_addr_t entry_point,
432 target_addr_t exit_point, int timeout_ms, void *arch_info)
433 {
434 struct mips32_common *mips32 = target_to_mips32(target);
435 struct mips32_algorithm *mips32_algorithm_info = arch_info;
436 enum mips32_isa_mode isa_mode = mips32->isa_mode;
437
438 uint32_t context[MIPS32_NUM_REGS];
439 int retval = ERROR_OK;
440
441 LOG_DEBUG("Running algorithm");
442
443 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
444 * at the exit point */
445
446 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
447 LOG_ERROR("current target isn't a MIPS32 target");
448 return ERROR_TARGET_INVALID;
449 }
450
451 if (target->state != TARGET_HALTED) {
452 LOG_WARNING("target not halted");
453 return ERROR_TARGET_NOT_HALTED;
454 }
455
456 /* refresh core register cache */
457 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
458 if (!mips32->core_cache->reg_list[i].valid)
459 mips32->read_core_reg(target, i);
460 context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
461 }
462
463 for (int i = 0; i < num_mem_params; i++) {
464 if (mem_params[i].direction == PARAM_IN)
465 continue;
466 retval = target_write_buffer(target, mem_params[i].address,
467 mem_params[i].size, mem_params[i].value);
468 if (retval != ERROR_OK)
469 return retval;
470 }
471
472 for (int i = 0; i < num_reg_params; i++) {
473 if (reg_params[i].direction == PARAM_IN)
474 continue;
475
476 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
477
478 if (!reg) {
479 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
480 return ERROR_COMMAND_SYNTAX_ERROR;
481 }
482
483 if (reg->size != reg_params[i].size) {
484 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
485 reg_params[i].reg_name);
486 return ERROR_COMMAND_SYNTAX_ERROR;
487 }
488
489 mips32_set_core_reg(reg, reg_params[i].value);
490 }
491
492 mips32->isa_mode = mips32_algorithm_info->isa_mode;
493
494 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
495
496 if (retval != ERROR_OK)
497 return retval;
498
499 for (int i = 0; i < num_mem_params; i++) {
500 if (mem_params[i].direction != PARAM_OUT) {
501 retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
502 mem_params[i].value);
503 if (retval != ERROR_OK)
504 return retval;
505 }
506 }
507
508 for (int i = 0; i < num_reg_params; i++) {
509 if (reg_params[i].direction != PARAM_OUT) {
510 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
511 if (!reg) {
512 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
513 return ERROR_COMMAND_SYNTAX_ERROR;
514 }
515
516 if (reg->size != reg_params[i].size) {
517 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
518 reg_params[i].reg_name);
519 return ERROR_COMMAND_SYNTAX_ERROR;
520 }
521
522 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
523 }
524 }
525
526 /* restore everything we saved before */
527 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
528 uint32_t regvalue;
529 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
530 if (regvalue != context[i]) {
531 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
532 mips32->core_cache->reg_list[i].name, context[i]);
533 buf_set_u32(mips32->core_cache->reg_list[i].value,
534 0, 32, context[i]);
535 mips32->core_cache->reg_list[i].valid = 1;
536 mips32->core_cache->reg_list[i].dirty = 1;
537 }
538 }
539
540 mips32->isa_mode = isa_mode;
541
542 return ERROR_OK;
543 }
544
545 int mips32_examine(struct target *target)
546 {
547 struct mips32_common *mips32 = target_to_mips32(target);
548
549 if (!target_was_examined(target)) {
550 target_set_examined(target);
551
552 /* we will configure later */
553 mips32->bp_scanned = 0;
554 mips32->num_inst_bpoints = 0;
555 mips32->num_data_bpoints = 0;
556 mips32->num_inst_bpoints_avail = 0;
557 mips32->num_data_bpoints_avail = 0;
558 }
559
560 return ERROR_OK;
561 }
562
563 static int mips32_configure_ibs(struct target *target)
564 {
565 struct mips32_common *mips32 = target_to_mips32(target);
566 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
567 int retval, i;
568 uint32_t bpinfo;
569
570 /* get number of inst breakpoints */
571 retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
572 if (retval != ERROR_OK)
573 return retval;
574
575 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
576 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
577 mips32->inst_break_list = calloc(mips32->num_inst_bpoints,
578 sizeof(struct mips32_comparator));
579
580 for (i = 0; i < mips32->num_inst_bpoints; i++)
581 mips32->inst_break_list[i].reg_address =
582 ejtag_info->ejtag_iba0_addr +
583 (ejtag_info->ejtag_iba_step_size * i);
584
585 /* clear IBIS reg */
586 retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
587 return retval;
588 }
589
590 static int mips32_configure_dbs(struct target *target)
591 {
592 struct mips32_common *mips32 = target_to_mips32(target);
593 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
594 int retval, i;
595 uint32_t bpinfo;
596
597 /* get number of data breakpoints */
598 retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
599 if (retval != ERROR_OK)
600 return retval;
601
602 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
603 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
604 mips32->data_break_list = calloc(mips32->num_data_bpoints,
605 sizeof(struct mips32_comparator));
606
607 for (i = 0; i < mips32->num_data_bpoints; i++)
608 mips32->data_break_list[i].reg_address =
609 ejtag_info->ejtag_dba0_addr +
610 (ejtag_info->ejtag_dba_step_size * i);
611
612 /* clear DBIS reg */
613 retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
614 return retval;
615 }
616
617 int mips32_configure_break_unit(struct target *target)
618 {
619 /* get pointers to arch-specific information */
620 struct mips32_common *mips32 = target_to_mips32(target);
621 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
622 int retval;
623 uint32_t dcr;
624
625 if (mips32->bp_scanned)
626 return ERROR_OK;
627
628 /* get info about breakpoint support */
629 retval = target_read_u32(target, EJTAG_DCR, &dcr);
630 if (retval != ERROR_OK)
631 return retval;
632
633 /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */
634 if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
635 ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM;
636 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB))
637 ejtag_info->debug_caps |= EJTAG_DCR_IB;
638 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB))
639 ejtag_info->debug_caps |= EJTAG_DCR_DB;
640 } else
641 /* keep debug caps for later use */
642 ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM
643 | EJTAG_DCR_IB | EJTAG_DCR_DB);
644
645
646 if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
647 retval = mips32_configure_ibs(target);
648 if (retval != ERROR_OK)
649 return retval;
650 }
651
652 if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
653 retval = mips32_configure_dbs(target);
654 if (retval != ERROR_OK)
655 return retval;
656 }
657
658 /* check if target endianness settings matches debug control register */
659 if (((ejtag_info->debug_caps & EJTAG_DCR_ENM)
660 && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
661 (!(ejtag_info->debug_caps & EJTAG_DCR_ENM)
662 && (target->endianness == TARGET_BIG_ENDIAN)))
663 LOG_WARNING("DCR endianness settings does not match target settings");
664
665 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
666 mips32->num_data_bpoints);
667
668 mips32->bp_scanned = 1;
669
670 return ERROR_OK;
671 }
672
673 int mips32_enable_interrupts(struct target *target, int enable)
674 {
675 int retval;
676 int update = 0;
677 uint32_t dcr;
678
679 /* read debug control register */
680 retval = target_read_u32(target, EJTAG_DCR, &dcr);
681 if (retval != ERROR_OK)
682 return retval;
683
684 if (enable) {
685 if (!(dcr & EJTAG_DCR_INTE)) {
686 /* enable interrupts */
687 dcr |= EJTAG_DCR_INTE;
688 update = 1;
689 }
690 } else {
691 if (dcr & EJTAG_DCR_INTE) {
692 /* disable interrupts */
693 dcr &= ~EJTAG_DCR_INTE;
694 update = 1;
695 }
696 }
697
698 if (update) {
699 retval = target_write_u32(target, EJTAG_DCR, dcr);
700 if (retval != ERROR_OK)
701 return retval;
702 }
703
704 return ERROR_OK;
705 }
706
707 /* read config to config3 cp0 registers and log isa implementation */
708 int mips32_read_config_regs(struct target *target)
709 {
710 struct mips32_common *mips32 = target_to_mips32(target);
711 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
712
713 if (ejtag_info->config_regs == 0)
714 for (int i = 0; i != 4; i++) {
715 int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
716 if (retval != ERROR_OK) {
717 LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
718 ejtag_info->config_regs = 0;
719 return retval;
720 }
721 ejtag_info->config_regs = i + 1;
722 if ((ejtag_info->config[i] & (1 << 31)) == 0)
723 break; /* no more config registers implemented */
724 }
725 else
726 return ERROR_OK; /* already succesfully read */
727
728 LOG_DEBUG("read %"PRId32" config registers", ejtag_info->config_regs);
729
730 if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
731 mips32->isa_imp = MIPS32_MIPS16;
732 LOG_USER("MIPS32 with MIPS16 support implemented");
733
734 } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
735 unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
736 if (isa_imp == 1) {
737 mips32->isa_imp = MMIPS32_ONLY;
738 LOG_USER("MICRO MIPS32 only implemented");
739
740 } else if (isa_imp != 0) {
741 mips32->isa_imp = MIPS32_MMIPS32;
742 LOG_USER("MIPS32 and MICRO MIPS32 implemented");
743 }
744 }
745
746 if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
747 LOG_USER("MIPS32 only implemented");
748
749 return ERROR_OK;
750 }
751 int mips32_checksum_memory(struct target *target, target_addr_t address,
752 uint32_t count, uint32_t *checksum)
753 {
754 struct working_area *crc_algorithm;
755 struct reg_param reg_params[2];
756 struct mips32_algorithm mips32_info;
757
758 struct mips32_common *mips32 = target_to_mips32(target);
759 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
760
761 /* see contrib/loaders/checksum/mips32.s for src */
762 uint32_t isa = ejtag_info->isa ? 1 : 0;
763
764 uint32_t mips_crc_code[] = {
765 MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */
766 MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */
767 MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */
768 MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */
769 MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */
770 /* nbyte: */
771 MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */
772 MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */
773 MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */
774 MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */
775 MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */
776 MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */
777 MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */
778 /* loop */
779 MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */
780 MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */
781 MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */
782 MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */
783 MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */
784 MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */
785 MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */
786 MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */
787 /* ncomp */
788 MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */
789 MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */
790 MIPS32_SDBBP(isa),
791 };
792
793 /* make sure we have a working area */
794 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
795 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
796
797 pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code));
798
799 /* convert mips crc code into a buffer in target endianness */
800 uint8_t mips_crc_code_8[sizeof(mips_crc_code)];
801 target_buffer_set_u32_array(target, mips_crc_code_8,
802 ARRAY_SIZE(mips_crc_code), mips_crc_code);
803
804 int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8);
805 if (retval != ERROR_OK)
806 return retval;
807
808 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
809 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */
810
811 init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
812 buf_set_u32(reg_params[0].value, 0, 32, address);
813
814 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
815 buf_set_u32(reg_params[1].value, 0, 32, count);
816
817 int timeout = 20000 * (1 + (count / (1024 * 1024)));
818
819 retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
820 crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);
821
822 if (retval == ERROR_OK)
823 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
824
825 destroy_reg_param(&reg_params[0]);
826 destroy_reg_param(&reg_params[1]);
827
828 target_free_working_area(target, crc_algorithm);
829
830 return retval;
831 }
832
833 /** Checks whether a memory region is erased. */
834 int mips32_blank_check_memory(struct target *target,
835 struct target_memory_check_block *blocks, int num_blocks,
836 uint8_t erased_value)
837 {
838 struct working_area *erase_check_algorithm;
839 struct reg_param reg_params[3];
840 struct mips32_algorithm mips32_info;
841
842 struct mips32_common *mips32 = target_to_mips32(target);
843 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
844
845 if (erased_value != 0xff) {
846 LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32",
847 erased_value);
848 return ERROR_FAIL;
849 }
850 uint32_t isa = ejtag_info->isa ? 1 : 0;
851 uint32_t erase_check_code[] = {
852 /* nbyte: */
853 MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */
854 MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */
855 MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */
856 MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */
857 MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */
858 MIPS32_SDBBP(isa) /* sdbbp */
859 };
860
861 /* make sure we have a working area */
862 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
863 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
864
865 pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code));
866
867 /* convert erase check code into a buffer in target endianness */
868 uint8_t erase_check_code_8[sizeof(erase_check_code)];
869 target_buffer_set_u32_array(target, erase_check_code_8,
870 ARRAY_SIZE(erase_check_code), erase_check_code);
871
872 int retval = target_write_buffer(target, erase_check_algorithm->address,
873 sizeof(erase_check_code), erase_check_code_8);
874 if (retval != ERROR_OK)
875 goto cleanup;
876
877 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
878 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
879
880 init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
881 buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
882
883 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
884 buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
885
886 init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
887 buf_set_u32(reg_params[2].value, 0, 32, erased_value);
888
889 retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
890 erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
891
892 if (retval == ERROR_OK)
893 blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
894
895 destroy_reg_param(&reg_params[0]);
896 destroy_reg_param(&reg_params[1]);
897 destroy_reg_param(&reg_params[2]);
898
899 cleanup:
900 target_free_working_area(target, erase_check_algorithm);
901
902 if (retval != ERROR_OK)
903 return retval;
904
905 return 1; /* only one block has been checked */
906 }
907
908 static int mips32_verify_pointer(struct command_context *cmd_ctx,
909 struct mips32_common *mips32)
910 {
911 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
912 command_print(cmd_ctx, "target is not an MIPS32");
913 return ERROR_TARGET_INVALID;
914 }
915 return ERROR_OK;
916 }
917
918 /**
919 * MIPS32 targets expose command interface
920 * to manipulate CP0 registers
921 */
922 COMMAND_HANDLER(mips32_handle_cp0_command)
923 {
924 int retval;
925 struct target *target = get_current_target(CMD_CTX);
926 struct mips32_common *mips32 = target_to_mips32(target);
927 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
928
929
930 retval = mips32_verify_pointer(CMD_CTX, mips32);
931 if (retval != ERROR_OK)
932 return retval;
933
934 if (target->state != TARGET_HALTED) {
935 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
936 return ERROR_OK;
937 }
938
939 /* two or more argument, access a single register/select (write if third argument is given) */
940 if (CMD_ARGC < 2)
941 return ERROR_COMMAND_SYNTAX_ERROR;
942 else {
943 uint32_t cp0_reg, cp0_sel;
944 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
945 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
946
947 if (CMD_ARGC == 2) {
948 uint32_t value;
949
950 retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
951 if (retval != ERROR_OK) {
952 command_print(CMD_CTX,
953 "couldn't access reg %" PRIi32,
954 cp0_reg);
955 return ERROR_OK;
956 }
957 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
958 cp0_reg, cp0_sel, value);
959
960 } else if (CMD_ARGC == 3) {
961 uint32_t value;
962 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
963 retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
964 if (retval != ERROR_OK) {
965 command_print(CMD_CTX,
966 "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
967 cp0_reg, cp0_sel);
968 return ERROR_OK;
969 }
970 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
971 cp0_reg, cp0_sel, value);
972 }
973 }
974
975 return ERROR_OK;
976 }
977
978 COMMAND_HANDLER(mips32_handle_scan_delay_command)
979 {
980 struct target *target = get_current_target(CMD_CTX);
981 struct mips32_common *mips32 = target_to_mips32(target);
982 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
983
984 if (CMD_ARGC == 1)
985 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
986 else if (CMD_ARGC > 1)
987 return ERROR_COMMAND_SYNTAX_ERROR;
988
989 command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
990 if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {
991 ejtag_info->mode = 0;
992 command_print(CMD_CTX, "running in legacy mode");
993 } else {
994 ejtag_info->mode = 1;
995 command_print(CMD_CTX, "running in fast queued mode");
996 }
997
998 return ERROR_OK;
999 }
1000
1001 static const struct command_registration mips32_exec_command_handlers[] = {
1002 {
1003 .name = "cp0",
1004 .handler = mips32_handle_cp0_command,
1005 .mode = COMMAND_EXEC,
1006 .usage = "regnum select [value]",
1007 .help = "display/modify cp0 register",
1008 },
1009 {
1010 .name = "scan_delay",
1011 .handler = mips32_handle_scan_delay_command,
1012 .mode = COMMAND_ANY,
1013 .help = "display/set scan delay in nano seconds",
1014 .usage = "[value]",
1015 },
1016 COMMAND_REGISTRATION_DONE
1017 };
1018
1019 const struct command_registration mips32_command_handlers[] = {
1020 {
1021 .name = "mips32",
1022 .mode = COMMAND_ANY,
1023 .help = "mips32 command group",
1024 .usage = "",
1025 .chain = mips32_exec_command_handlers,
1026 },
1027 COMMAND_REGISTRATION_DONE
1028 };

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)