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

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)