build: cleanup src/target directory
[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, write to the *
25 * Free Software Foundation, Inc., *
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
27 ***************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "mips32.h"
34 #include "breakpoints.h"
35 #include "algorithm.h"
36 #include "register.h"
37
38 static char *mips32_core_reg_list[] = {
39 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
40 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
41 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
42 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
43 "status", "lo", "hi", "badvaddr", "cause", "pc"
44 };
45
46 static const char *mips_isa_strings[] = {
47 "MIPS32", "MIPS16e"
48 };
49
50 static struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] = {
51 {0, NULL, NULL},
52 {1, NULL, NULL},
53 {2, NULL, NULL},
54 {3, NULL, NULL},
55 {4, NULL, NULL},
56 {5, NULL, NULL},
57 {6, NULL, NULL},
58 {7, NULL, NULL},
59 {8, NULL, NULL},
60 {9, NULL, NULL},
61 {10, NULL, NULL},
62 {11, NULL, NULL},
63 {12, NULL, NULL},
64 {13, NULL, NULL},
65 {14, NULL, NULL},
66 {15, NULL, NULL},
67 {16, NULL, NULL},
68 {17, NULL, NULL},
69 {18, NULL, NULL},
70 {19, NULL, NULL},
71 {20, NULL, NULL},
72 {21, NULL, NULL},
73 {22, NULL, NULL},
74 {23, NULL, NULL},
75 {24, NULL, NULL},
76 {25, NULL, NULL},
77 {26, NULL, NULL},
78 {27, NULL, NULL},
79 {28, NULL, NULL},
80 {29, NULL, NULL},
81 {30, NULL, NULL},
82 {31, NULL, NULL},
83
84 {32, NULL, NULL},
85 {33, NULL, NULL},
86 {34, NULL, NULL},
87 {35, NULL, NULL},
88 {36, NULL, NULL},
89 {37, NULL, NULL},
90 };
91
92 /* number of mips dummy fp regs fp0 - fp31 + fsr and fir
93 * we also add 18 unknown registers to handle gdb requests */
94
95 #define MIPS32NUMFPREGS (34 + 18)
96
97 static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
98
99 static struct reg mips32_gdb_dummy_fp_reg = {
100 .name = "GDB dummy floating-point register",
101 .value = mips32_gdb_dummy_fp_value,
102 .dirty = 0,
103 .valid = 1,
104 .size = 32,
105 .arch_info = NULL,
106 };
107
108 static int mips32_get_core_reg(struct reg *reg)
109 {
110 int retval;
111 struct mips32_core_reg *mips32_reg = reg->arch_info;
112 struct target *target = mips32_reg->target;
113 struct mips32_common *mips32_target = target_to_mips32(target);
114
115 if (target->state != TARGET_HALTED)
116 return ERROR_TARGET_NOT_HALTED;
117
118 retval = mips32_target->read_core_reg(target, mips32_reg->num);
119
120 return retval;
121 }
122
123 static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
124 {
125 struct mips32_core_reg *mips32_reg = reg->arch_info;
126 struct target *target = mips32_reg->target;
127 uint32_t value = buf_get_u32(buf, 0, 32);
128
129 if (target->state != TARGET_HALTED)
130 return ERROR_TARGET_NOT_HALTED;
131
132 buf_set_u32(reg->value, 0, 32, value);
133 reg->dirty = 1;
134 reg->valid = 1;
135
136 return ERROR_OK;
137 }
138
139 static int mips32_read_core_reg(struct target *target, int num)
140 {
141 uint32_t reg_value;
142
143 /* get pointers to arch-specific information */
144 struct mips32_common *mips32 = target_to_mips32(target);
145
146 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
147 return ERROR_COMMAND_SYNTAX_ERROR;
148
149 reg_value = mips32->core_regs[num];
150 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
151 mips32->core_cache->reg_list[num].valid = 1;
152 mips32->core_cache->reg_list[num].dirty = 0;
153
154 return ERROR_OK;
155 }
156
157 static int mips32_write_core_reg(struct target *target, int num)
158 {
159 uint32_t reg_value;
160
161 /* get pointers to arch-specific information */
162 struct mips32_common *mips32 = target_to_mips32(target);
163
164 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
165 return ERROR_COMMAND_SYNTAX_ERROR;
166
167 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
168 mips32->core_regs[num] = reg_value;
169 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
170 mips32->core_cache->reg_list[num].valid = 1;
171 mips32->core_cache->reg_list[num].dirty = 0;
172
173 return ERROR_OK;
174 }
175
176 int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
177 {
178 /* get pointers to arch-specific information */
179 struct mips32_common *mips32 = target_to_mips32(target);
180 int i;
181
182 /* include floating point registers */
183 *reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
184 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
185
186 for (i = 0; i < MIPS32NUMCOREREGS; i++)
187 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
188
189 /* add dummy floating points regs */
190 for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
191 (*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
192
193 return ERROR_OK;
194 }
195
196 int mips32_save_context(struct target *target)
197 {
198 int i;
199
200 /* get pointers to arch-specific information */
201 struct mips32_common *mips32 = target_to_mips32(target);
202 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
203
204 /* read core registers */
205 mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
206
207 for (i = 0; i < MIPS32NUMCOREREGS; i++) {
208 if (!mips32->core_cache->reg_list[i].valid)
209 mips32->read_core_reg(target, i);
210 }
211
212 return ERROR_OK;
213 }
214
215 int mips32_restore_context(struct target *target)
216 {
217 int i;
218
219 /* get pointers to arch-specific information */
220 struct mips32_common *mips32 = target_to_mips32(target);
221 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
222
223 for (i = 0; i < MIPS32NUMCOREREGS; i++) {
224 if (mips32->core_cache->reg_list[i].dirty)
225 mips32->write_core_reg(target, i);
226 }
227
228 /* write core regs */
229 mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
230
231 return ERROR_OK;
232 }
233
234 int mips32_arch_state(struct target *target)
235 {
236 struct mips32_common *mips32 = target_to_mips32(target);
237
238 LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
239 mips_isa_strings[mips32->isa_mode],
240 debug_reason_name(target),
241 buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
242
243 return ERROR_OK;
244 }
245
246 static const struct reg_arch_type mips32_reg_type = {
247 .get = mips32_get_core_reg,
248 .set = mips32_set_core_reg,
249 };
250
251 struct reg_cache *mips32_build_reg_cache(struct target *target)
252 {
253 /* get pointers to arch-specific information */
254 struct mips32_common *mips32 = target_to_mips32(target);
255
256 int num_regs = MIPS32NUMCOREREGS;
257 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
258 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
259 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
260 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
261 int i;
262
263 register_init_dummy(&mips32_gdb_dummy_fp_reg);
264
265 /* Build the process context cache */
266 cache->name = "mips32 registers";
267 cache->next = NULL;
268 cache->reg_list = reg_list;
269 cache->num_regs = num_regs;
270 (*cache_p) = cache;
271 mips32->core_cache = cache;
272
273 for (i = 0; i < num_regs; i++) {
274 arch_info[i] = mips32_core_reg_list_arch_info[i];
275 arch_info[i].target = target;
276 arch_info[i].mips32_common = mips32;
277 reg_list[i].name = mips32_core_reg_list[i];
278 reg_list[i].size = 32;
279 reg_list[i].value = calloc(1, 4);
280 reg_list[i].dirty = 0;
281 reg_list[i].valid = 0;
282 reg_list[i].type = &mips32_reg_type;
283 reg_list[i].arch_info = &arch_info[i];
284 }
285
286 return cache;
287 }
288
289 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
290 {
291 target->arch_info = mips32;
292 mips32->common_magic = MIPS32_COMMON_MAGIC;
293 mips32->fast_data_area = NULL;
294
295 /* has breakpoint/watchpint unit been scanned */
296 mips32->bp_scanned = 0;
297 mips32->data_break_list = NULL;
298
299 mips32->ejtag_info.tap = tap;
300 mips32->read_core_reg = mips32_read_core_reg;
301 mips32->write_core_reg = mips32_write_core_reg;
302
303 return ERROR_OK;
304 }
305
306 /* run to exit point. return error if exit point was not reached. */
307 static int mips32_run_and_wait(struct target *target, uint32_t entry_point,
308 int timeout_ms, uint32_t exit_point, struct mips32_common *mips32)
309 {
310 uint32_t pc;
311 int retval;
312 /* This code relies on the target specific resume() and poll()->debug_entry()
313 * sequence to write register values to the processor and the read them back */
314 retval = target_resume(target, 0, entry_point, 0, 1);
315 if (retval != ERROR_OK)
316 return retval;
317
318 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
319 /* If the target fails to halt due to the breakpoint, force a halt */
320 if (retval != ERROR_OK || target->state != TARGET_HALTED) {
321 retval = target_halt(target);
322 if (retval != ERROR_OK)
323 return retval;
324 retval = target_wait_state(target, TARGET_HALTED, 500);
325 if (retval != ERROR_OK)
326 return retval;
327 return ERROR_TARGET_TIMEOUT;
328 }
329
330 pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
331 if (exit_point && (pc != exit_point)) {
332 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
333 return ERROR_TARGET_TIMEOUT;
334 }
335
336 return ERROR_OK;
337 }
338
339 int mips32_run_algorithm(struct target *target, int num_mem_params,
340 struct mem_param *mem_params, int num_reg_params,
341 struct reg_param *reg_params, uint32_t entry_point,
342 uint32_t exit_point, int timeout_ms, void *arch_info)
343 {
344 struct mips32_common *mips32 = target_to_mips32(target);
345 struct mips32_algorithm *mips32_algorithm_info = arch_info;
346 enum mips32_isa_mode isa_mode = mips32->isa_mode;
347
348 uint32_t context[MIPS32NUMCOREREGS];
349 int i;
350 int retval = ERROR_OK;
351
352 LOG_DEBUG("Running algorithm");
353
354 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
355 * at the exit point */
356
357 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
358 LOG_ERROR("current target isn't a MIPS32 target");
359 return ERROR_TARGET_INVALID;
360 }
361
362 if (target->state != TARGET_HALTED) {
363 LOG_WARNING("target not halted");
364 return ERROR_TARGET_NOT_HALTED;
365 }
366
367 /* refresh core register cache */
368 for (i = 0; i < MIPS32NUMCOREREGS; i++) {
369 if (!mips32->core_cache->reg_list[i].valid)
370 mips32->read_core_reg(target, i);
371 context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
372 }
373
374 for (i = 0; i < num_mem_params; i++) {
375 retval = target_write_buffer(target, mem_params[i].address,
376 mem_params[i].size, mem_params[i].value);
377 if (retval != ERROR_OK)
378 return retval;
379 }
380
381 for (i = 0; i < num_reg_params; i++) {
382 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
383
384 if (!reg) {
385 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
386 return ERROR_COMMAND_SYNTAX_ERROR;
387 }
388
389 if (reg->size != reg_params[i].size) {
390 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
391 reg_params[i].reg_name);
392 return ERROR_COMMAND_SYNTAX_ERROR;
393 }
394
395 mips32_set_core_reg(reg, reg_params[i].value);
396 }
397
398 mips32->isa_mode = mips32_algorithm_info->isa_mode;
399
400 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
401
402 if (retval != ERROR_OK)
403 return retval;
404
405 for (i = 0; i < num_mem_params; i++) {
406 if (mem_params[i].direction != PARAM_OUT) {
407 retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
408 mem_params[i].value);
409 if (retval != ERROR_OK)
410 return retval;
411 }
412 }
413
414 for (i = 0; i < num_reg_params; i++) {
415 if (reg_params[i].direction != PARAM_OUT) {
416 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
417 if (!reg) {
418 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
419 return ERROR_COMMAND_SYNTAX_ERROR;
420 }
421
422 if (reg->size != reg_params[i].size) {
423 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
424 reg_params[i].reg_name);
425 return ERROR_COMMAND_SYNTAX_ERROR;
426 }
427
428 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
429 }
430 }
431
432 /* restore everything we saved before */
433 for (i = 0; i < MIPS32NUMCOREREGS; i++) {
434 uint32_t regvalue;
435 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
436 if (regvalue != context[i]) {
437 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
438 mips32->core_cache->reg_list[i].name, context[i]);
439 buf_set_u32(mips32->core_cache->reg_list[i].value,
440 0, 32, context[i]);
441 mips32->core_cache->reg_list[i].valid = 1;
442 mips32->core_cache->reg_list[i].dirty = 1;
443 }
444 }
445
446 mips32->isa_mode = isa_mode;
447
448 return ERROR_OK;
449 }
450
451 int mips32_examine(struct target *target)
452 {
453 struct mips32_common *mips32 = target_to_mips32(target);
454
455 if (!target_was_examined(target)) {
456 target_set_examined(target);
457
458 /* we will configure later */
459 mips32->bp_scanned = 0;
460 mips32->num_inst_bpoints = 0;
461 mips32->num_data_bpoints = 0;
462 mips32->num_inst_bpoints_avail = 0;
463 mips32->num_data_bpoints_avail = 0;
464 }
465
466 return ERROR_OK;
467 }
468
469 int mips32_configure_break_unit(struct target *target)
470 {
471 /* get pointers to arch-specific information */
472 struct mips32_common *mips32 = target_to_mips32(target);
473 int retval;
474 uint32_t dcr, bpinfo;
475 int i;
476
477 if (mips32->bp_scanned)
478 return ERROR_OK;
479
480 /* get info about breakpoint support */
481 retval = target_read_u32(target, EJTAG_DCR, &dcr);
482 if (retval != ERROR_OK)
483 return retval;
484
485 if (dcr & EJTAG_DCR_IB) {
486 /* get number of inst breakpoints */
487 retval = target_read_u32(target, EJTAG_IBS, &bpinfo);
488 if (retval != ERROR_OK)
489 return retval;
490
491 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
492 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
493 mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator));
494 for (i = 0; i < mips32->num_inst_bpoints; i++)
495 mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
496
497 /* clear IBIS reg */
498 retval = target_write_u32(target, EJTAG_IBS, 0);
499 if (retval != ERROR_OK)
500 return retval;
501 }
502
503 if (dcr & EJTAG_DCR_DB) {
504 /* get number of data breakpoints */
505 retval = target_read_u32(target, EJTAG_DBS, &bpinfo);
506 if (retval != ERROR_OK)
507 return retval;
508
509 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
510 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
511 mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator));
512 for (i = 0; i < mips32->num_data_bpoints; i++)
513 mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
514
515 /* clear DBIS reg */
516 retval = target_write_u32(target, EJTAG_DBS, 0);
517 if (retval != ERROR_OK)
518 return retval;
519 }
520
521 /* check if target endianness settings matches debug control register */
522 if (((dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
523 (!(dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_BIG_ENDIAN)))
524 LOG_WARNING("DCR endianness settings does not match target settings");
525
526 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
527 mips32->num_data_bpoints);
528
529 mips32->bp_scanned = 1;
530
531 return ERROR_OK;
532 }
533
534 int mips32_enable_interrupts(struct target *target, int enable)
535 {
536 int retval;
537 int update = 0;
538 uint32_t dcr;
539
540 /* read debug control register */
541 retval = target_read_u32(target, EJTAG_DCR, &dcr);
542 if (retval != ERROR_OK)
543 return retval;
544
545 if (enable) {
546 if (!(dcr & EJTAG_DCR_INTE)) {
547 /* enable interrupts */
548 dcr |= EJTAG_DCR_INTE;
549 update = 1;
550 }
551 } else {
552 if (dcr & EJTAG_DCR_INTE) {
553 /* disable interrupts */
554 dcr &= ~EJTAG_DCR_INTE;
555 update = 1;
556 }
557 }
558
559 if (update) {
560 retval = target_write_u32(target, EJTAG_DCR, dcr);
561 if (retval != ERROR_OK)
562 return retval;
563 }
564
565 return ERROR_OK;
566 }
567
568 int mips32_checksum_memory(struct target *target, uint32_t address,
569 uint32_t count, uint32_t *checksum)
570 {
571 struct working_area *crc_algorithm;
572 struct reg_param reg_params[2];
573 struct mips32_algorithm mips32_info;
574 int retval;
575 uint32_t i;
576
577 /* see contib/loaders/checksum/mips32.s for src */
578
579 static const uint32_t mips_crc_code[] = {
580 0x248C0000, /* addiu $t4, $a0, 0 */
581 0x24AA0000, /* addiu $t2, $a1, 0 */
582 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */
583 0x10000010, /* beq $zero, $zero, ncomp */
584 0x240B0000, /* addiu $t3, $zero, 0 */
585 /* nbyte: */
586 0x81850000, /* lb $a1, ($t4) */
587 0x218C0001, /* addi $t4, $t4, 1 */
588 0x00052E00, /* sll $a1, $a1, 24 */
589 0x3C0204C1, /* lui $v0, 0x04c1 */
590 0x00852026, /* xor $a0, $a0, $a1 */
591 0x34471DB7, /* ori $a3, $v0, 0x1db7 */
592 0x00003021, /* addu $a2, $zero, $zero */
593 /* loop: */
594 0x00044040, /* sll $t0, $a0, 1 */
595 0x24C60001, /* addiu $a2, $a2, 1 */
596 0x28840000, /* slti $a0, $a0, 0 */
597 0x01074826, /* xor $t1, $t0, $a3 */
598 0x0124400B, /* movn $t0, $t1, $a0 */
599 0x28C30008, /* slti $v1, $a2, 8 */
600 0x1460FFF9, /* bne $v1, $zero, loop */
601 0x01002021, /* addu $a0, $t0, $zero */
602 /* ncomp: */
603 0x154BFFF0, /* bne $t2, $t3, nbyte */
604 0x256B0001, /* addiu $t3, $t3, 1 */
605 0x7000003F, /* sdbbp */
606 };
607
608 /* make sure we have a working area */
609 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
610 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
611
612 /* convert flash writing code into a buffer in target endianness */
613 for (i = 0; i < ARRAY_SIZE(mips_crc_code); i++)
614 target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), mips_crc_code[i]);
615
616 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
617 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
618
619 init_reg_param(&reg_params[0], "a0", 32, PARAM_IN_OUT);
620 buf_set_u32(reg_params[0].value, 0, 32, address);
621
622 init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
623 buf_set_u32(reg_params[1].value, 0, 32, count);
624
625 int timeout = 20000 * (1 + (count / (1024 * 1024)));
626
627 retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
628 crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code)-4), timeout,
629 &mips32_info);
630 if (retval != ERROR_OK) {
631 destroy_reg_param(&reg_params[0]);
632 destroy_reg_param(&reg_params[1]);
633 target_free_working_area(target, crc_algorithm);
634 return 0;
635 }
636
637 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
638
639 destroy_reg_param(&reg_params[0]);
640 destroy_reg_param(&reg_params[1]);
641
642 target_free_working_area(target, crc_algorithm);
643
644 return ERROR_OK;
645 }
646
647 /** Checks whether a memory region is zeroed. */
648 int mips32_blank_check_memory(struct target *target,
649 uint32_t address, uint32_t count, uint32_t *blank)
650 {
651 struct working_area *erase_check_algorithm;
652 struct reg_param reg_params[3];
653 struct mips32_algorithm mips32_info;
654 int retval;
655 uint32_t i;
656
657 static const uint32_t erase_check_code[] = {
658 /* nbyte: */
659 0x80880000, /* lb $t0, ($a0) */
660 0x00C83024, /* and $a2, $a2, $t0 */
661 0x24A5FFFF, /* addiu $a1, $a1, -1 */
662 0x14A0FFFC, /* bne $a1, $zero, nbyte */
663 0x24840001, /* addiu $a0, $a0, 1 */
664 0x7000003F /* sdbbp */
665 };
666
667 /* make sure we have a working area */
668 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
669 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
670
671 /* convert flash writing code into a buffer in target endianness */
672 for (i = 0; i < ARRAY_SIZE(erase_check_code); i++) {
673 target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t),
674 erase_check_code[i]);
675 }
676
677 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
678 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
679
680 init_reg_param(&reg_params[0], "a0", 32, PARAM_OUT);
681 buf_set_u32(reg_params[0].value, 0, 32, address);
682
683 init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
684 buf_set_u32(reg_params[1].value, 0, 32, count);
685
686 init_reg_param(&reg_params[2], "a2", 32, PARAM_IN_OUT);
687 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
688
689 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
690 erase_check_algorithm->address,
691 erase_check_algorithm->address + (sizeof(erase_check_code)-2),
692 10000, &mips32_info);
693 if (retval != ERROR_OK) {
694 destroy_reg_param(&reg_params[0]);
695 destroy_reg_param(&reg_params[1]);
696 destroy_reg_param(&reg_params[2]);
697 target_free_working_area(target, erase_check_algorithm);
698 return 0;
699 }
700
701 *blank = buf_get_u32(reg_params[2].value, 0, 32);
702
703 destroy_reg_param(&reg_params[0]);
704 destroy_reg_param(&reg_params[1]);
705 destroy_reg_param(&reg_params[2]);
706
707 target_free_working_area(target, erase_check_algorithm);
708
709 return ERROR_OK;
710 }
711
712 static int mips32_verify_pointer(struct command_context *cmd_ctx,
713 struct mips32_common *mips32)
714 {
715 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
716 command_print(cmd_ctx, "target is not an MIPS32");
717 return ERROR_TARGET_INVALID;
718 }
719 return ERROR_OK;
720 }
721
722 /**
723 * MIPS32 targets expose command interface
724 * to manipulate CP0 registers
725 */
726 COMMAND_HANDLER(mips32_handle_cp0_command)
727 {
728 int retval;
729 struct target *target = get_current_target(CMD_CTX);
730 struct mips32_common *mips32 = target_to_mips32(target);
731 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
732
733
734 retval = mips32_verify_pointer(CMD_CTX, mips32);
735 if (retval != ERROR_OK)
736 return retval;
737
738 if (target->state != TARGET_HALTED) {
739 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
740 return ERROR_OK;
741 }
742
743 /* two or more argument, access a single register/select (write if third argument is given) */
744 if (CMD_ARGC < 2)
745 return ERROR_COMMAND_SYNTAX_ERROR;
746 else {
747 uint32_t cp0_reg, cp0_sel;
748 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
749 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
750
751 if (CMD_ARGC == 2) {
752 uint32_t value;
753
754 retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
755 if (retval != ERROR_OK) {
756 command_print(CMD_CTX,
757 "couldn't access reg %" PRIi32,
758 cp0_reg);
759 return ERROR_OK;
760 }
761 retval = jtag_execute_queue();
762 if (retval != ERROR_OK)
763 return retval;
764
765 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
766 cp0_reg, cp0_sel, value);
767 } else if (CMD_ARGC == 3) {
768 uint32_t value;
769 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
770 retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
771 if (retval != ERROR_OK) {
772 command_print(CMD_CTX,
773 "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
774 cp0_reg, cp0_sel);
775 return ERROR_OK;
776 }
777 command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
778 cp0_reg, cp0_sel, value);
779 }
780 }
781
782 return ERROR_OK;
783 }
784
785 static const struct command_registration mips32_exec_command_handlers[] = {
786 {
787 .name = "cp0",
788 .handler = mips32_handle_cp0_command,
789 .mode = COMMAND_EXEC,
790 .usage = "regnum select [value]",
791 .help = "display/modify cp0 register",
792 },
793 COMMAND_REGISTRATION_DONE
794 };
795
796 const struct command_registration mips32_command_handlers[] = {
797 {
798 .name = "mips32",
799 .mode = COMMAND_ANY,
800 .help = "mips32 command group",
801 .usage = "",
802 .chain = mips32_exec_command_handlers,
803 },
804 COMMAND_REGISTRATION_DONE
805 };

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)