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

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)