target/mips32: rework mips core register related functions
[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 mips32_pracc_read_regs(mips32);
310
311 for (i = 0; i < MIPS32_NUM_REGS; i++) {
312 if (!mips32->core_cache->reg_list[i].valid)
313 mips32->read_core_reg(target, i);
314 }
315
316 return ERROR_OK;
317 }
318
319 int mips32_restore_context(struct target *target)
320 {
321 unsigned int i;
322
323 /* get pointers to arch-specific information */
324 struct mips32_common *mips32 = target_to_mips32(target);
325
326 for (i = 0; i < MIPS32_NUM_REGS; i++) {
327 if (mips32->core_cache->reg_list[i].dirty)
328 mips32->write_core_reg(target, i);
329 }
330
331 /* write core regs */
332 mips32_pracc_write_regs(mips32);
333
334 return ERROR_OK;
335 }
336
337 int mips32_arch_state(struct target *target)
338 {
339 struct mips32_common *mips32 = target_to_mips32(target);
340
341 LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
342 mips_isa_strings[mips32->isa_mode],
343 debug_reason_name(target),
344 buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
345
346 return ERROR_OK;
347 }
348
349 static const struct reg_arch_type mips32_reg_type = {
350 .get = mips32_get_core_reg,
351 .set = mips32_set_core_reg,
352 };
353
354 struct reg_cache *mips32_build_reg_cache(struct target *target)
355 {
356 /* get pointers to arch-specific information */
357 struct mips32_common *mips32 = target_to_mips32(target);
358
359 int num_regs = MIPS32_NUM_REGS;
360 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
361 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
362 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
363 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
364 struct reg_feature *feature;
365 int i;
366
367 /* Build the process context cache */
368 cache->name = "mips32 registers";
369 cache->next = NULL;
370 cache->reg_list = reg_list;
371 cache->num_regs = num_regs;
372 (*cache_p) = cache;
373 mips32->core_cache = cache;
374
375 for (i = 0; i < num_regs; i++) {
376 arch_info[i].num = mips32_regs[i].id;
377 arch_info[i].target = target;
378 arch_info[i].mips32_common = mips32;
379
380 reg_list[i].name = mips32_regs[i].name;
381 reg_list[i].size = mips32_regs[i].size ? 64 : 32;
382
383 reg_list[i].value = mips32_regs[i].size ? calloc(1, 8) : calloc(1, 4);
384 reg_list[i].valid = false;
385 reg_list[i].type = &mips32_reg_type;
386 reg_list[i].arch_info = &arch_info[i];
387
388 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
389 if (reg_list[i].reg_data_type)
390 reg_list[i].reg_data_type->type = mips32_regs[i].type;
391 else
392 LOG_ERROR("unable to allocate reg type list");
393
394
395 reg_list[i].dirty = false;
396
397 reg_list[i].group = mips32_regs[i].group;
398 reg_list[i].number = i;
399 reg_list[i].exist = true;
400 reg_list[i].caller_save = true; /* gdb defaults to true */
401
402 feature = calloc(1, sizeof(struct reg_feature));
403 if (feature) {
404 feature->name = mips32_regs[i].feature;
405 reg_list[i].feature = feature;
406 } else
407 LOG_ERROR("unable to allocate feature list");
408 }
409
410 return cache;
411 }
412
413 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
414 {
415 target->arch_info = mips32;
416 mips32->common_magic = MIPS32_COMMON_MAGIC;
417 mips32->fast_data_area = NULL;
418 mips32->isa_imp = MIPS32_ONLY; /* default */
419
420 /* has breakpoint/watchpoint unit been scanned */
421 mips32->bp_scanned = 0;
422 mips32->data_break_list = NULL;
423
424 mips32->ejtag_info.tap = tap;
425 mips32->read_core_reg = mips32_read_core_reg;
426 mips32->write_core_reg = mips32_write_core_reg;
427 /* if unknown endianness defaults to little endian, 1 */
428 mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1;
429 mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE;
430 mips32->ejtag_info.mode = 0; /* Initial default value */
431 mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */
432 mips32->ejtag_info.config_regs = 0; /* no config register read */
433 return ERROR_OK;
434 }
435
436 /* run to exit point. return error if exit point was not reached. */
437 static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
438 unsigned int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32)
439 {
440 uint32_t pc;
441 int retval;
442 /* This code relies on the target specific resume() and poll()->debug_entry()
443 * sequence to write register values to the processor and the read them back */
444 retval = target_resume(target, 0, entry_point, 0, 1);
445 if (retval != ERROR_OK)
446 return retval;
447
448 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
449 /* If the target fails to halt due to the breakpoint, force a halt */
450 if (retval != ERROR_OK || target->state != TARGET_HALTED) {
451 retval = target_halt(target);
452 if (retval != ERROR_OK)
453 return retval;
454 retval = target_wait_state(target, TARGET_HALTED, 500);
455 if (retval != ERROR_OK)
456 return retval;
457 return ERROR_TARGET_TIMEOUT;
458 }
459
460 pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
461 if (exit_point && (pc != exit_point)) {
462 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
463 return ERROR_TARGET_TIMEOUT;
464 }
465
466 return ERROR_OK;
467 }
468
469 int mips32_run_algorithm(struct target *target, int num_mem_params,
470 struct mem_param *mem_params, int num_reg_params,
471 struct reg_param *reg_params, target_addr_t entry_point,
472 target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
473 {
474 struct mips32_common *mips32 = target_to_mips32(target);
475 struct mips32_algorithm *mips32_algorithm_info = arch_info;
476 enum mips32_isa_mode isa_mode = mips32->isa_mode;
477
478 uint32_t context[MIPS32_NUM_REGS];
479 int retval = ERROR_OK;
480
481 LOG_DEBUG("Running algorithm");
482
483 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
484 * at the exit point */
485
486 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
487 LOG_ERROR("current target isn't a MIPS32 target");
488 return ERROR_TARGET_INVALID;
489 }
490
491 if (target->state != TARGET_HALTED) {
492 LOG_TARGET_ERROR(target, "not halted (run target algo)");
493 return ERROR_TARGET_NOT_HALTED;
494 }
495
496 /* refresh core register cache */
497 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
498 if (!mips32->core_cache->reg_list[i].valid)
499 mips32->read_core_reg(target, i);
500 context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
501 }
502
503 for (int i = 0; i < num_mem_params; i++) {
504 if (mem_params[i].direction == PARAM_IN)
505 continue;
506 retval = target_write_buffer(target, mem_params[i].address,
507 mem_params[i].size, mem_params[i].value);
508 if (retval != ERROR_OK)
509 return retval;
510 }
511
512 for (int i = 0; i < num_reg_params; i++) {
513 if (reg_params[i].direction == PARAM_IN)
514 continue;
515
516 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, false);
517
518 if (!reg) {
519 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
520 return ERROR_COMMAND_SYNTAX_ERROR;
521 }
522
523 if (reg->size != reg_params[i].size) {
524 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
525 reg_params[i].reg_name);
526 return ERROR_COMMAND_SYNTAX_ERROR;
527 }
528
529 mips32_set_core_reg(reg, reg_params[i].value);
530 }
531
532 mips32->isa_mode = mips32_algorithm_info->isa_mode;
533
534 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
535
536 if (retval != ERROR_OK)
537 return retval;
538
539 for (int i = 0; i < num_mem_params; i++) {
540 if (mem_params[i].direction != PARAM_OUT) {
541 retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
542 mem_params[i].value);
543 if (retval != ERROR_OK)
544 return retval;
545 }
546 }
547
548 for (int i = 0; i < num_reg_params; i++) {
549 if (reg_params[i].direction != PARAM_OUT) {
550 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, false);
551 if (!reg) {
552 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
553 return ERROR_COMMAND_SYNTAX_ERROR;
554 }
555
556 if (reg->size != reg_params[i].size) {
557 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
558 reg_params[i].reg_name);
559 return ERROR_COMMAND_SYNTAX_ERROR;
560 }
561
562 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
563 }
564 }
565
566 /* restore everything we saved before */
567 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
568 uint32_t regvalue;
569 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
570 if (regvalue != context[i]) {
571 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
572 mips32->core_cache->reg_list[i].name, context[i]);
573 buf_set_u32(mips32->core_cache->reg_list[i].value,
574 0, 32, context[i]);
575 mips32->core_cache->reg_list[i].valid = true;
576 mips32->core_cache->reg_list[i].dirty = true;
577 }
578 }
579
580 mips32->isa_mode = isa_mode;
581
582 return ERROR_OK;
583 }
584
585 int mips32_examine(struct target *target)
586 {
587 struct mips32_common *mips32 = target_to_mips32(target);
588
589 if (!target_was_examined(target)) {
590 target_set_examined(target);
591
592 /* we will configure later */
593 mips32->bp_scanned = 0;
594 mips32->num_inst_bpoints = 0;
595 mips32->num_data_bpoints = 0;
596 mips32->num_inst_bpoints_avail = 0;
597 mips32->num_data_bpoints_avail = 0;
598 }
599
600 return ERROR_OK;
601 }
602
603 static int mips32_configure_ibs(struct target *target)
604 {
605 struct mips32_common *mips32 = target_to_mips32(target);
606 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
607 int retval, i;
608 uint32_t bpinfo;
609
610 /* get number of inst breakpoints */
611 retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
612 if (retval != ERROR_OK)
613 return retval;
614
615 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
616 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
617 mips32->inst_break_list = calloc(mips32->num_inst_bpoints,
618 sizeof(struct mips32_comparator));
619
620 for (i = 0; i < mips32->num_inst_bpoints; i++)
621 mips32->inst_break_list[i].reg_address =
622 ejtag_info->ejtag_iba0_addr +
623 (ejtag_info->ejtag_iba_step_size * i);
624
625 /* clear IBIS reg */
626 retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
627 return retval;
628 }
629
630 static int mips32_configure_dbs(struct target *target)
631 {
632 struct mips32_common *mips32 = target_to_mips32(target);
633 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
634 int retval, i;
635 uint32_t bpinfo;
636
637 /* get number of data breakpoints */
638 retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
639 if (retval != ERROR_OK)
640 return retval;
641
642 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
643 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
644 mips32->data_break_list = calloc(mips32->num_data_bpoints,
645 sizeof(struct mips32_comparator));
646
647 for (i = 0; i < mips32->num_data_bpoints; i++)
648 mips32->data_break_list[i].reg_address =
649 ejtag_info->ejtag_dba0_addr +
650 (ejtag_info->ejtag_dba_step_size * i);
651
652 /* clear DBIS reg */
653 retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
654 return retval;
655 }
656
657 int mips32_configure_break_unit(struct target *target)
658 {
659 /* get pointers to arch-specific information */
660 struct mips32_common *mips32 = target_to_mips32(target);
661 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
662 int retval;
663 uint32_t dcr;
664
665 if (mips32->bp_scanned)
666 return ERROR_OK;
667
668 /* get info about breakpoint support */
669 retval = target_read_u32(target, EJTAG_DCR, &dcr);
670 if (retval != ERROR_OK)
671 return retval;
672
673 /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */
674 if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
675 ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM;
676 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB))
677 ejtag_info->debug_caps |= EJTAG_DCR_IB;
678 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB))
679 ejtag_info->debug_caps |= EJTAG_DCR_DB;
680 } else
681 /* keep debug caps for later use */
682 ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM
683 | EJTAG_DCR_IB | EJTAG_DCR_DB);
684
685
686 if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
687 retval = mips32_configure_ibs(target);
688 if (retval != ERROR_OK)
689 return retval;
690 }
691
692 if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
693 retval = mips32_configure_dbs(target);
694 if (retval != ERROR_OK)
695 return retval;
696 }
697
698 /* check if target endianness settings matches debug control register */
699 if (((ejtag_info->debug_caps & EJTAG_DCR_ENM)
700 && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
701 (!(ejtag_info->debug_caps & EJTAG_DCR_ENM)
702 && (target->endianness == TARGET_BIG_ENDIAN)))
703 LOG_WARNING("DCR endianness settings does not match target settings");
704
705 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
706 mips32->num_data_bpoints);
707
708 mips32->bp_scanned = 1;
709
710 return ERROR_OK;
711 }
712
713 int mips32_enable_interrupts(struct target *target, int enable)
714 {
715 int retval;
716 int update = 0;
717 uint32_t dcr;
718
719 /* read debug control register */
720 retval = target_read_u32(target, EJTAG_DCR, &dcr);
721 if (retval != ERROR_OK)
722 return retval;
723
724 if (enable) {
725 if (!(dcr & EJTAG_DCR_INTE)) {
726 /* enable interrupts */
727 dcr |= EJTAG_DCR_INTE;
728 update = 1;
729 }
730 } else {
731 if (dcr & EJTAG_DCR_INTE) {
732 /* disable interrupts */
733 dcr &= ~EJTAG_DCR_INTE;
734 update = 1;
735 }
736 }
737
738 if (update) {
739 retval = target_write_u32(target, EJTAG_DCR, dcr);
740 if (retval != ERROR_OK)
741 return retval;
742 }
743
744 return ERROR_OK;
745 }
746
747 /* read processor identification cp0 register */
748 static int mips32_read_c0_prid(struct target *target)
749 {
750 struct mips32_common *mips32 = target_to_mips32(target);
751 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
752 int retval;
753
754 retval = mips32_cp0_read(ejtag_info, &mips32->prid, 15, 0);
755 if (retval != ERROR_OK) {
756 LOG_ERROR("processor id not available, failed to read cp0 PRId register");
757 mips32->prid = 0;
758 }
759
760 return retval;
761 }
762
763 /*
764 * Detect processor type and apply required quirks.
765 *
766 * NOTE: The proper detection of certain CPUs can become quite complicated.
767 * Please consult the following Linux kernel code when adding new CPUs:
768 * arch/mips/include/asm/cpu.h
769 * arch/mips/kernel/cpu-probe.c
770 */
771 int mips32_cpu_probe(struct target *target)
772 {
773 struct mips32_common *mips32 = target_to_mips32(target);
774 const char *cpu_name = "unknown";
775 int retval;
776
777 if (mips32->prid)
778 return ERROR_OK; /* Already probed once, return early. */
779
780 retval = mips32_read_c0_prid(target);
781 if (retval != ERROR_OK)
782 return retval;
783
784 switch (mips32->prid & PRID_COMP_MASK) {
785 case PRID_COMP_INGENIC_E1:
786 switch (mips32->prid & PRID_IMP_MASK) {
787 case PRID_IMP_XBURST_REV1:
788 cpu_name = "Ingenic XBurst rev1";
789 mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET;
790 break;
791 default:
792 break;
793 }
794 break;
795 default:
796 break;
797 }
798
799 LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid);
800
801 return ERROR_OK;
802 }
803
804 /* read config to config3 cp0 registers and log isa implementation */
805 int mips32_read_config_regs(struct target *target)
806 {
807 struct mips32_common *mips32 = target_to_mips32(target);
808 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
809
810 if (ejtag_info->config_regs == 0)
811 for (int i = 0; i != 4; i++) {
812 int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
813 if (retval != ERROR_OK) {
814 LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
815 ejtag_info->config_regs = 0;
816 return retval;
817 }
818 ejtag_info->config_regs = i + 1;
819 if ((ejtag_info->config[i] & (1 << 31)) == 0)
820 break; /* no more config registers implemented */
821 }
822 else
823 return ERROR_OK; /* already successfully read */
824
825 LOG_DEBUG("read %"PRIu32" config registers", ejtag_info->config_regs);
826
827 if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
828 mips32->isa_imp = MIPS32_MIPS16;
829 LOG_USER("MIPS32 with MIPS16 support implemented");
830
831 } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
832 unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
833 if (isa_imp == 1) {
834 mips32->isa_imp = MMIPS32_ONLY;
835 LOG_USER("MICRO MIPS32 only implemented");
836
837 } else if (isa_imp != 0) {
838 mips32->isa_imp = MIPS32_MMIPS32;
839 LOG_USER("MIPS32 and MICRO MIPS32 implemented");
840 }
841 }
842
843 if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
844 LOG_USER("MIPS32 only implemented");
845
846 return ERROR_OK;
847 }
848 int mips32_checksum_memory(struct target *target, target_addr_t address,
849 uint32_t count, uint32_t *checksum)
850 {
851 struct working_area *crc_algorithm;
852 struct reg_param reg_params[2];
853 struct mips32_algorithm mips32_info;
854
855 struct mips32_common *mips32 = target_to_mips32(target);
856 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
857
858 /* see contrib/loaders/checksum/mips32.s for src */
859 uint32_t isa = ejtag_info->isa ? 1 : 0;
860
861 uint32_t mips_crc_code[] = {
862 MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */
863 MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */
864 MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */
865 MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */
866 MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */
867 /* nbyte: */
868 MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */
869 MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */
870 MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */
871 MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */
872 MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */
873 MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */
874 MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */
875 /* loop */
876 MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */
877 MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */
878 MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */
879 MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */
880 MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */
881 MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */
882 MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */
883 MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */
884 /* ncomp */
885 MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */
886 MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */
887 MIPS32_SDBBP(isa),
888 };
889
890 /* make sure we have a working area */
891 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
892 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
893
894 pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code));
895
896 /* convert mips crc code into a buffer in target endianness */
897 uint8_t mips_crc_code_8[sizeof(mips_crc_code)];
898 target_buffer_set_u32_array(target, mips_crc_code_8,
899 ARRAY_SIZE(mips_crc_code), mips_crc_code);
900
901 int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8);
902 if (retval != ERROR_OK)
903 return retval;
904
905 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
906 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */
907
908 init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
909 buf_set_u32(reg_params[0].value, 0, 32, address);
910
911 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
912 buf_set_u32(reg_params[1].value, 0, 32, count);
913
914 unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
915
916 retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
917 crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);
918
919 if (retval == ERROR_OK)
920 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
921
922 destroy_reg_param(&reg_params[0]);
923 destroy_reg_param(&reg_params[1]);
924
925 target_free_working_area(target, crc_algorithm);
926
927 return retval;
928 }
929
930 /** Checks whether a memory region is erased. */
931 int mips32_blank_check_memory(struct target *target,
932 struct target_memory_check_block *blocks, int num_blocks,
933 uint8_t erased_value)
934 {
935 struct working_area *erase_check_algorithm;
936 struct reg_param reg_params[3];
937 struct mips32_algorithm mips32_info;
938
939 struct mips32_common *mips32 = target_to_mips32(target);
940 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
941
942 if (erased_value != 0xff) {
943 LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32",
944 erased_value);
945 return ERROR_FAIL;
946 }
947 uint32_t isa = ejtag_info->isa ? 1 : 0;
948 uint32_t erase_check_code[] = {
949 /* nbyte: */
950 MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */
951 MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */
952 MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */
953 MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */
954 MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */
955 MIPS32_SDBBP(isa) /* sdbbp */
956 };
957
958 /* make sure we have a working area */
959 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
960 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
961
962 pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code));
963
964 /* convert erase check code into a buffer in target endianness */
965 uint8_t erase_check_code_8[sizeof(erase_check_code)];
966 target_buffer_set_u32_array(target, erase_check_code_8,
967 ARRAY_SIZE(erase_check_code), erase_check_code);
968
969 int retval = target_write_buffer(target, erase_check_algorithm->address,
970 sizeof(erase_check_code), erase_check_code_8);
971 if (retval != ERROR_OK)
972 goto cleanup;
973
974 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
975 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
976
977 init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
978 buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
979
980 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
981 buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
982
983 init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
984 buf_set_u32(reg_params[2].value, 0, 32, erased_value);
985
986 retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
987 erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
988
989 if (retval == ERROR_OK)
990 blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
991
992 destroy_reg_param(&reg_params[0]);
993 destroy_reg_param(&reg_params[1]);
994 destroy_reg_param(&reg_params[2]);
995
996 cleanup:
997 target_free_working_area(target, erase_check_algorithm);
998
999 if (retval != ERROR_OK)
1000 return retval;
1001
1002 return 1; /* only one block has been checked */
1003 }
1004
1005 static int mips32_verify_pointer(struct command_invocation *cmd,
1006 struct mips32_common *mips32)
1007 {
1008 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
1009 command_print(cmd, "target is not an MIPS32");
1010 return ERROR_TARGET_INVALID;
1011 }
1012 return ERROR_OK;
1013 }
1014
1015 /**
1016 * MIPS32 targets expose command interface
1017 * to manipulate CP0 registers
1018 */
1019 COMMAND_HANDLER(mips32_handle_cp0_command)
1020 {
1021 int retval;
1022 struct target *target = get_current_target(CMD_CTX);
1023 struct mips32_common *mips32 = target_to_mips32(target);
1024 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1025
1026
1027 retval = mips32_verify_pointer(CMD, mips32);
1028 if (retval != ERROR_OK)
1029 return retval;
1030
1031 if (target->state != TARGET_HALTED) {
1032 command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
1033 return ERROR_TARGET_NOT_HALTED;
1034 }
1035
1036 /* two or more argument, access a single register/select (write if third argument is given) */
1037 if (CMD_ARGC < 2)
1038 return ERROR_COMMAND_SYNTAX_ERROR;
1039 else {
1040 uint32_t cp0_reg, cp0_sel;
1041 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
1042 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
1043
1044 if (CMD_ARGC == 2) {
1045 uint32_t value;
1046
1047 retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
1048 if (retval != ERROR_OK) {
1049 command_print(CMD,
1050 "couldn't access reg %" PRIu32,
1051 cp0_reg);
1052 return ERROR_OK;
1053 }
1054 command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32,
1055 cp0_reg, cp0_sel, value);
1056
1057 } else if (CMD_ARGC == 3) {
1058 uint32_t value;
1059 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
1060 retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
1061 if (retval != ERROR_OK) {
1062 command_print(CMD,
1063 "couldn't access cp0 reg %" PRIu32 ", select %" PRIu32,
1064 cp0_reg, cp0_sel);
1065 return ERROR_OK;
1066 }
1067 command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32,
1068 cp0_reg, cp0_sel, value);
1069 }
1070 }
1071
1072 return ERROR_OK;
1073 }
1074
1075 COMMAND_HANDLER(mips32_handle_scan_delay_command)
1076 {
1077 struct target *target = get_current_target(CMD_CTX);
1078 struct mips32_common *mips32 = target_to_mips32(target);
1079 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1080
1081 if (CMD_ARGC == 1)
1082 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
1083 else if (CMD_ARGC > 1)
1084 return ERROR_COMMAND_SYNTAX_ERROR;
1085
1086 command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay);
1087 if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {
1088 ejtag_info->mode = 0;
1089 command_print(CMD, "running in legacy mode");
1090 } else {
1091 ejtag_info->mode = 1;
1092 command_print(CMD, "running in fast queued mode");
1093 }
1094
1095 return ERROR_OK;
1096 }
1097
1098 static const struct command_registration mips32_exec_command_handlers[] = {
1099 {
1100 .name = "cp0",
1101 .handler = mips32_handle_cp0_command,
1102 .mode = COMMAND_EXEC,
1103 .usage = "regnum select [value]",
1104 .help = "display/modify cp0 register",
1105 },
1106 {
1107 .name = "scan_delay",
1108 .handler = mips32_handle_scan_delay_command,
1109 .mode = COMMAND_ANY,
1110 .help = "display/set scan delay in nano seconds",
1111 .usage = "[value]",
1112 },
1113 COMMAND_REGISTRATION_DONE
1114 };
1115
1116 const struct command_registration mips32_command_handlers[] = {
1117 {
1118 .name = "mips32",
1119 .mode = COMMAND_ANY,
1120 .help = "mips32 command group",
1121 .usage = "",
1122 .chain = mips32_exec_command_handlers,
1123 },
1124 COMMAND_REGISTRATION_DONE
1125 };

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)