mips32: add micromips isa handling
[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 retval = target_write_buffer(target, mem_params[i].address,
465 mem_params[i].size, mem_params[i].value);
466 if (retval != ERROR_OK)
467 return retval;
468 }
469
470 for (int i = 0; i < num_reg_params; i++) {
471 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
472
473 if (!reg) {
474 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
475 return ERROR_COMMAND_SYNTAX_ERROR;
476 }
477
478 if (reg->size != reg_params[i].size) {
479 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
480 reg_params[i].reg_name);
481 return ERROR_COMMAND_SYNTAX_ERROR;
482 }
483
484 mips32_set_core_reg(reg, reg_params[i].value);
485 }
486
487 mips32->isa_mode = mips32_algorithm_info->isa_mode;
488
489 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
490
491 if (retval != ERROR_OK)
492 return retval;
493
494 for (int i = 0; i < num_mem_params; i++) {
495 if (mem_params[i].direction != PARAM_OUT) {
496 retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
497 mem_params[i].value);
498 if (retval != ERROR_OK)
499 return retval;
500 }
501 }
502
503 for (int i = 0; i < num_reg_params; i++) {
504 if (reg_params[i].direction != PARAM_OUT) {
505 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
506 if (!reg) {
507 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
508 return ERROR_COMMAND_SYNTAX_ERROR;
509 }
510
511 if (reg->size != reg_params[i].size) {
512 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
513 reg_params[i].reg_name);
514 return ERROR_COMMAND_SYNTAX_ERROR;
515 }
516
517 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
518 }
519 }
520
521 /* restore everything we saved before */
522 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
523 uint32_t regvalue;
524 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
525 if (regvalue != context[i]) {
526 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
527 mips32->core_cache->reg_list[i].name, context[i]);
528 buf_set_u32(mips32->core_cache->reg_list[i].value,
529 0, 32, context[i]);
530 mips32->core_cache->reg_list[i].valid = 1;
531 mips32->core_cache->reg_list[i].dirty = 1;
532 }
533 }
534
535 mips32->isa_mode = isa_mode;
536
537 return ERROR_OK;
538 }
539
540 int mips32_examine(struct target *target)
541 {
542 struct mips32_common *mips32 = target_to_mips32(target);
543
544 if (!target_was_examined(target)) {
545 target_set_examined(target);
546
547 /* we will configure later */
548 mips32->bp_scanned = 0;
549 mips32->num_inst_bpoints = 0;
550 mips32->num_data_bpoints = 0;
551 mips32->num_inst_bpoints_avail = 0;
552 mips32->num_data_bpoints_avail = 0;
553 }
554
555 return ERROR_OK;
556 }
557
558 static int mips32_configure_ibs(struct target *target)
559 {
560 struct mips32_common *mips32 = target_to_mips32(target);
561 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
562 int retval, i;
563 uint32_t bpinfo;
564
565 /* get number of inst breakpoints */
566 retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
567 if (retval != ERROR_OK)
568 return retval;
569
570 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
571 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
572 mips32->inst_break_list = calloc(mips32->num_inst_bpoints,
573 sizeof(struct mips32_comparator));
574
575 for (i = 0; i < mips32->num_inst_bpoints; i++)
576 mips32->inst_break_list[i].reg_address =
577 ejtag_info->ejtag_iba0_addr +
578 (ejtag_info->ejtag_iba_step_size * i);
579
580 /* clear IBIS reg */
581 retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
582 return retval;
583 }
584
585 static int mips32_configure_dbs(struct target *target)
586 {
587 struct mips32_common *mips32 = target_to_mips32(target);
588 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
589 int retval, i;
590 uint32_t bpinfo;
591
592 /* get number of data breakpoints */
593 retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
594 if (retval != ERROR_OK)
595 return retval;
596
597 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
598 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
599 mips32->data_break_list = calloc(mips32->num_data_bpoints,
600 sizeof(struct mips32_comparator));
601
602 for (i = 0; i < mips32->num_data_bpoints; i++)
603 mips32->data_break_list[i].reg_address =
604 ejtag_info->ejtag_dba0_addr +
605 (ejtag_info->ejtag_dba_step_size * i);
606
607 /* clear DBIS reg */
608 retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
609 return retval;
610 }
611
612 int mips32_configure_break_unit(struct target *target)
613 {
614 /* get pointers to arch-specific information */
615 struct mips32_common *mips32 = target_to_mips32(target);
616 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
617 int retval;
618 uint32_t dcr;
619
620 if (mips32->bp_scanned)
621 return ERROR_OK;
622
623 /* get info about breakpoint support */
624 retval = target_read_u32(target, EJTAG_DCR, &dcr);
625 if (retval != ERROR_OK)
626 return retval;
627
628 /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */
629 if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
630 ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM;
631 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB))
632 ejtag_info->debug_caps |= EJTAG_DCR_IB;
633 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB))
634 ejtag_info->debug_caps |= EJTAG_DCR_DB;
635 } else
636 /* keep debug caps for later use */
637 ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM
638 | EJTAG_DCR_IB | EJTAG_DCR_DB);
639
640
641 if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
642 retval = mips32_configure_ibs(target);
643 if (retval != ERROR_OK)
644 return retval;
645 }
646
647 if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
648 retval = mips32_configure_dbs(target);
649 if (retval != ERROR_OK)
650 return retval;
651 }
652
653 /* check if target endianness settings matches debug control register */
654 if (((ejtag_info->debug_caps & EJTAG_DCR_ENM)
655 && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
656 (!(ejtag_info->debug_caps & EJTAG_DCR_ENM)
657 && (target->endianness == TARGET_BIG_ENDIAN)))
658 LOG_WARNING("DCR endianness settings does not match target settings");
659
660 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
661 mips32->num_data_bpoints);
662
663 mips32->bp_scanned = 1;
664
665 return ERROR_OK;
666 }
667
668 int mips32_enable_interrupts(struct target *target, int enable)
669 {
670 int retval;
671 int update = 0;
672 uint32_t dcr;
673
674 /* read debug control register */
675 retval = target_read_u32(target, EJTAG_DCR, &dcr);
676 if (retval != ERROR_OK)
677 return retval;
678
679 if (enable) {
680 if (!(dcr & EJTAG_DCR_INTE)) {
681 /* enable interrupts */
682 dcr |= EJTAG_DCR_INTE;
683 update = 1;
684 }
685 } else {
686 if (dcr & EJTAG_DCR_INTE) {
687 /* disable interrupts */
688 dcr &= ~EJTAG_DCR_INTE;
689 update = 1;
690 }
691 }
692
693 if (update) {
694 retval = target_write_u32(target, EJTAG_DCR, dcr);
695 if (retval != ERROR_OK)
696 return retval;
697 }
698
699 return ERROR_OK;
700 }
701
702 /* read config to config3 cp0 registers and log isa implementation */
703 int mips32_read_config_regs(struct target *target)
704 {
705 struct mips32_common *mips32 = target_to_mips32(target);
706 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
707
708 if (ejtag_info->config_regs == 0)
709 for (int i = 0; i != 4; i++) {
710 int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
711 if (retval != ERROR_OK) {
712 LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
713 ejtag_info->config_regs = 0;
714 return retval;
715 }
716 ejtag_info->config_regs = i + 1;
717 if ((ejtag_info->config[i] & (1 << 31)) == 0)
718 break; /* no more config registers implemented */
719 }
720 else
721 return ERROR_OK; /* already succesfully read */
722
723 LOG_DEBUG("read %"PRId32" config registers", ejtag_info->config_regs);
724
725 if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
726 mips32->isa_imp = MIPS32_MIPS16;
727 LOG_USER("MIPS32 with MIPS16 support implemented");
728
729 } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
730 unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
731 if (isa_imp == 1) {
732 mips32->isa_imp = MMIPS32_ONLY;
733 LOG_USER("MICRO MIPS32 only implemented");
734
735 } else if (isa_imp != 0) {
736 mips32->isa_imp = MIPS32_MMIPS32;
737 LOG_USER("MIPS32 and MICRO MIPS32 implemented");
738 }
739 }
740
741 if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
742 LOG_USER("MIPS32 only implemented");
743
744 return ERROR_OK;
745 }
746 int mips32_checksum_memory(struct target *target, target_addr_t address,
747 uint32_t count, uint32_t *checksum)
748 {
749 struct working_area *crc_algorithm;
750 struct reg_param reg_params[2];
751 struct mips32_algorithm mips32_info;
752
753 struct mips32_common *mips32 = target_to_mips32(target);
754 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
755
756 /* see contrib/loaders/checksum/mips32.s for src */
757 uint32_t isa = ejtag_info->isa ? 1 : 0;
758
759 uint32_t mips_crc_code[] = {
760 MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */
761 MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */
762 MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */
763 MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */
764 MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */
765 /* nbyte: */
766 MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */
767 MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */
768 MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */
769 MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */
770 MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */
771 MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */
772 MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */
773 /* loop */
774 MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */
775 MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */
776 MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */
777 MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */
778 MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */
779 MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */
780 MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */
781 MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */
782 /* ncomp */
783 MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */
784 MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */
785 MIPS32_SDBBP(isa),
786 };
787
788 /* make sure we have a working area */
789 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
790 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
791
792 pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code));
793
794 /* convert mips crc code into a buffer in target endianness */
795 uint8_t mips_crc_code_8[sizeof(mips_crc_code)];
796 target_buffer_set_u32_array(target, mips_crc_code_8,
797 ARRAY_SIZE(mips_crc_code), mips_crc_code);
798
799 int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8);
800 if (retval != ERROR_OK)
801 return retval;
802
803 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
804 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */
805
806 init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
807 buf_set_u32(reg_params[0].value, 0, 32, address);
808
809 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
810 buf_set_u32(reg_params[1].value, 0, 32, count);
811
812 int timeout = 20000 * (1 + (count / (1024 * 1024)));
813
814 retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
815 crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);
816
817 if (retval == ERROR_OK)
818 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
819
820 destroy_reg_param(&reg_params[0]);
821 destroy_reg_param(&reg_params[1]);
822
823 target_free_working_area(target, crc_algorithm);
824
825 return retval;
826 }
827
828 /** Checks whether a memory region is erased. */
829 int mips32_blank_check_memory(struct target *target,
830 target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
831 {
832 struct working_area *erase_check_algorithm;
833 struct reg_param reg_params[3];
834 struct mips32_algorithm mips32_info;
835
836 struct mips32_common *mips32 = target_to_mips32(target);
837 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
838
839 if (erased_value != 0xff) {
840 LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32",
841 erased_value);
842 return ERROR_FAIL;
843 }
844 uint32_t isa = ejtag_info->isa ? 1 : 0;
845 uint32_t erase_check_code[] = {
846 /* nbyte: */
847 MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */
848 MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */
849 MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */
850 MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */
851 MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */
852 MIPS32_SDBBP(isa) /* sdbbp */
853 };
854
855 /* make sure we have a working area */
856 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
857 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
858
859 pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code));
860
861 /* convert erase check code into a buffer in target endianness */
862 uint8_t erase_check_code_8[sizeof(erase_check_code)];
863 target_buffer_set_u32_array(target, erase_check_code_8,
864 ARRAY_SIZE(erase_check_code), erase_check_code);
865
866 int retval = target_write_buffer(target, erase_check_algorithm->address,
867 sizeof(erase_check_code), erase_check_code_8);
868 if (retval != ERROR_OK)
869 return retval;
870
871 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
872 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
873
874 init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
875 buf_set_u32(reg_params[0].value, 0, 32, address);
876
877 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
878 buf_set_u32(reg_params[1].value, 0, 32, count);
879
880 init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
881 buf_set_u32(reg_params[2].value, 0, 32, erased_value);
882
883 retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
884 erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
885
886 if (retval == ERROR_OK)
887 *blank = buf_get_u32(reg_params[2].value, 0, 32);
888
889 destroy_reg_param(&reg_params[0]);
890 destroy_reg_param(&reg_params[1]);
891 destroy_reg_param(&reg_params[2]);
892
893 target_free_working_area(target, erase_check_algorithm);
894
895 return retval;
896 }
897
898 static int mips32_verify_pointer(struct command_context *cmd_ctx,
899 struct mips32_common *mips32)
900 {
901 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
902 command_print(cmd_ctx, "target is not an MIPS32");
903 return ERROR_TARGET_INVALID;
904 }
905 return ERROR_OK;
906 }
907
908 /**
909 * MIPS32 targets expose command interface
910 * to manipulate CP0 registers
911 */
912 COMMAND_HANDLER(mips32_handle_cp0_command)
913 {
914 int retval;
915 struct target *target = get_current_target(CMD_CTX);
916 struct mips32_common *mips32 = target_to_mips32(target);
917 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
918
919
920 retval = mips32_verify_pointer(CMD_CTX, mips32);
921 if (retval != ERROR_OK)
922 return retval;
923
924 if (target->state != TARGET_HALTED) {
925 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
926 return ERROR_OK;
927 }
928
929 /* two or more argument, access a single register/select (write if third argument is given) */
930 if (CMD_ARGC < 2)
931 return ERROR_COMMAND_SYNTAX_ERROR;
932 else {
933 uint32_t cp0_reg, cp0_sel;
934 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
935 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
936
937 if (CMD_ARGC == 2) {
938 uint32_t value;
939
940 retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
941 if (retval != ERROR_OK) {
942 command_print(CMD_CTX,
943 "couldn't access reg %" PRIi32,
944 cp0_reg);
945 return ERROR_OK;
946 }
947 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
948 cp0_reg, cp0_sel, value);
949
950 } else if (CMD_ARGC == 3) {
951 uint32_t value;
952 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
953 retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
954 if (retval != ERROR_OK) {
955 command_print(CMD_CTX,
956 "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
957 cp0_reg, cp0_sel);
958 return ERROR_OK;
959 }
960 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
961 cp0_reg, cp0_sel, value);
962 }
963 }
964
965 return ERROR_OK;
966 }
967
968 COMMAND_HANDLER(mips32_handle_scan_delay_command)
969 {
970 struct target *target = get_current_target(CMD_CTX);
971 struct mips32_common *mips32 = target_to_mips32(target);
972 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
973
974 if (CMD_ARGC == 1)
975 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
976 else if (CMD_ARGC > 1)
977 return ERROR_COMMAND_SYNTAX_ERROR;
978
979 command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
980 if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {
981 ejtag_info->mode = 0;
982 command_print(CMD_CTX, "running in legacy mode");
983 } else {
984 ejtag_info->mode = 1;
985 command_print(CMD_CTX, "running in fast queued mode");
986 }
987
988 return ERROR_OK;
989 }
990
991 static const struct command_registration mips32_exec_command_handlers[] = {
992 {
993 .name = "cp0",
994 .handler = mips32_handle_cp0_command,
995 .mode = COMMAND_EXEC,
996 .usage = "regnum select [value]",
997 .help = "display/modify cp0 register",
998 },
999 {
1000 .name = "scan_delay",
1001 .handler = mips32_handle_scan_delay_command,
1002 .mode = COMMAND_ANY,
1003 .help = "display/set scan delay in nano seconds",
1004 .usage = "[value]",
1005 },
1006 COMMAND_REGISTRATION_DONE
1007 };
1008
1009 const struct command_registration mips32_command_handlers[] = {
1010 {
1011 .name = "mips32",
1012 .mode = COMMAND_ANY,
1013 .help = "mips32 command group",
1014 .usage = "",
1015 .chain = mips32_exec_command_handlers,
1016 },
1017 COMMAND_REGISTRATION_DONE
1018 };

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)