target/mips32: update coprocessor 0 command
[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
164 static int mips32_get_core_reg(struct reg *reg)
165 {
166 int retval;
167 struct mips32_core_reg *mips32_reg = reg->arch_info;
168 struct target *target = mips32_reg->target;
169 struct mips32_common *mips32_target = target_to_mips32(target);
170
171 if (target->state != TARGET_HALTED)
172 return ERROR_TARGET_NOT_HALTED;
173
174 retval = mips32_target->read_core_reg(target, mips32_reg->num);
175
176 return retval;
177 }
178
179 static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
180 {
181 struct mips32_core_reg *mips32_reg = reg->arch_info;
182 struct target *target = mips32_reg->target;
183 uint64_t value;
184
185 if (reg->size == 64)
186 value = buf_get_u64(buf, 0, 64);
187 else
188 value = buf_get_u32(buf, 0, 32);
189
190 if (target->state != TARGET_HALTED)
191 return ERROR_TARGET_NOT_HALTED;
192
193 if (reg->size == 64)
194 buf_set_u64(reg->value, 0, 64, value);
195 else
196 buf_set_u32(reg->value, 0, 32, value);
197
198 reg->dirty = true;
199 reg->valid = true;
200
201 return ERROR_OK;
202 }
203
204 static int mips32_read_core_reg(struct target *target, unsigned int num)
205 {
206 unsigned int cnum;
207 uint64_t reg_value = 0;
208
209 /* get pointers to arch-specific information */
210 struct mips32_common *mips32 = target_to_mips32(target);
211
212 if (num >= MIPS32_NUM_REGS)
213 return ERROR_COMMAND_SYNTAX_ERROR;
214
215 if (num >= MIPS32_REGLIST_C0_INDEX) {
216 /* CP0 */
217 cnum = num - MIPS32_REGLIST_C0_INDEX;
218 reg_value = mips32->core_regs.cp0[cnum];
219 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
220 } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
221 /* FPCR */
222 cnum = num - MIPS32_REGLIST_FPC_INDEX;
223 reg_value = mips32->core_regs.fpcr[cnum];
224 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
225 } else if (num >= MIPS32_REGLIST_FP_INDEX) {
226 /* FPR */
227 cnum = num - MIPS32_REGLIST_FP_INDEX;
228 reg_value = mips32->core_regs.fpr[cnum];
229 buf_set_u64(mips32->core_cache->reg_list[num].value, 0, 64, reg_value);
230 } else {
231 /* GPR */
232 cnum = num - MIPS32_REGLIST_GP_INDEX;
233 reg_value = mips32->core_regs.gpr[cnum];
234 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
235 }
236
237 mips32->core_cache->reg_list[num].valid = true;
238 mips32->core_cache->reg_list[num].dirty = false;
239
240 LOG_DEBUG("read core reg %i value 0x%" PRIx64 "", num, reg_value);
241
242 return ERROR_OK;
243 }
244
245 static int mips32_write_core_reg(struct target *target, unsigned int num)
246 {
247 unsigned int cnum;
248 uint64_t reg_value;
249
250 /* get pointers to arch-specific information */
251 struct mips32_common *mips32 = target_to_mips32(target);
252
253 if (num >= MIPS32_NUM_REGS)
254 return ERROR_COMMAND_SYNTAX_ERROR;
255
256 if (num >= MIPS32_REGLIST_C0_INDEX) {
257 /* CP0 */
258 cnum = num - MIPS32_REGLIST_C0_INDEX;
259 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
260 mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
261 } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
262 /* FPCR */
263 cnum = num - MIPS32_REGLIST_FPC_INDEX;
264 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
265 mips32->core_regs.fpcr[cnum] = (uint32_t)reg_value;
266 } else if (num >= MIPS32_REGLIST_FP_INDEX) {
267 /* FPR */
268 cnum = num - MIPS32_REGLIST_FP_INDEX;
269 reg_value = buf_get_u64(mips32->core_cache->reg_list[num].value, 0, 64);
270 mips32->core_regs.fpr[cnum] = reg_value;
271 } else {
272 /* GPR */
273 cnum = num - MIPS32_REGLIST_GP_INDEX;
274 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
275 mips32->core_regs.gpr[cnum] = (uint32_t)reg_value;
276 }
277
278 LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
279 mips32->core_cache->reg_list[num].valid = true;
280 mips32->core_cache->reg_list[num].dirty = false;
281
282 return ERROR_OK;
283 }
284
285 int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
286 int *reg_list_size, enum target_register_class reg_class)
287 {
288 /* get pointers to arch-specific information */
289 struct mips32_common *mips32 = target_to_mips32(target);
290 unsigned int i;
291
292 /* include floating point registers */
293 *reg_list_size = MIPS32_NUM_REGS;
294 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
295
296 for (i = 0; i < MIPS32_NUM_REGS; i++)
297 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
298
299 return ERROR_OK;
300 }
301
302 int mips32_save_context(struct target *target)
303 {
304 unsigned int i;
305
306 /* get pointers to arch-specific information */
307 struct mips32_common *mips32 = target_to_mips32(target);
308
309 /* read core registers */
310 int retval = mips32_pracc_read_regs(mips32);
311 if (retval != ERROR_OK) {
312 LOG_ERROR("Could not read core registers from target");
313 return retval;
314 }
315
316 for (i = 0; i < MIPS32_NUM_REGS; i++) {
317 if (!mips32->core_cache->reg_list[i].valid)
318 mips32->read_core_reg(target, i);
319 }
320
321 return ERROR_OK;
322 }
323
324 int mips32_restore_context(struct target *target)
325 {
326 unsigned int i;
327
328 /* get pointers to arch-specific information */
329 struct mips32_common *mips32 = target_to_mips32(target);
330
331 for (i = 0; i < MIPS32_NUM_REGS; i++) {
332 if (mips32->core_cache->reg_list[i].dirty)
333 mips32->write_core_reg(target, i);
334 }
335
336 /* write core regs */
337 return mips32_pracc_write_regs(mips32);
338 }
339
340 int mips32_arch_state(struct target *target)
341 {
342 struct mips32_common *mips32 = target_to_mips32(target);
343
344 LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
345 mips_isa_strings[mips32->isa_mode],
346 debug_reason_name(target),
347 buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
348
349 return ERROR_OK;
350 }
351
352 static const struct reg_arch_type mips32_reg_type = {
353 .get = mips32_get_core_reg,
354 .set = mips32_set_core_reg,
355 };
356
357 struct reg_cache *mips32_build_reg_cache(struct target *target)
358 {
359 /* get pointers to arch-specific information */
360 struct mips32_common *mips32 = target_to_mips32(target);
361
362 int num_regs = MIPS32_NUM_REGS;
363 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
364 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
365 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
366 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
367 struct reg_feature *feature;
368 int i;
369
370 /* Build the process context cache */
371 cache->name = "mips32 registers";
372 cache->next = NULL;
373 cache->reg_list = reg_list;
374 cache->num_regs = num_regs;
375 (*cache_p) = cache;
376 mips32->core_cache = cache;
377
378 for (i = 0; i < num_regs; i++) {
379 arch_info[i].num = mips32_regs[i].id;
380 arch_info[i].target = target;
381 arch_info[i].mips32_common = mips32;
382
383 reg_list[i].name = mips32_regs[i].name;
384 reg_list[i].size = mips32_regs[i].size ? 64 : 32;
385
386 reg_list[i].value = mips32_regs[i].size ? calloc(1, 8) : calloc(1, 4);
387 reg_list[i].valid = false;
388 reg_list[i].type = &mips32_reg_type;
389 reg_list[i].arch_info = &arch_info[i];
390
391 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
392 if (reg_list[i].reg_data_type)
393 reg_list[i].reg_data_type->type = mips32_regs[i].type;
394 else
395 LOG_ERROR("unable to allocate reg type list");
396
397
398 reg_list[i].dirty = false;
399
400 reg_list[i].group = mips32_regs[i].group;
401 reg_list[i].number = i;
402 reg_list[i].exist = true;
403 reg_list[i].caller_save = true; /* gdb defaults to true */
404
405 feature = calloc(1, sizeof(struct reg_feature));
406 if (feature) {
407 feature->name = mips32_regs[i].feature;
408 reg_list[i].feature = feature;
409 } else
410 LOG_ERROR("unable to allocate feature list");
411 }
412
413 return cache;
414 }
415
416 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
417 {
418 target->arch_info = mips32;
419 mips32->common_magic = MIPS32_COMMON_MAGIC;
420 mips32->fast_data_area = NULL;
421 mips32->isa_imp = MIPS32_ONLY; /* default */
422
423 /* has breakpoint/watchpoint unit been scanned */
424 mips32->bp_scanned = 0;
425 mips32->data_break_list = NULL;
426
427 mips32->ejtag_info.tap = tap;
428 mips32->read_core_reg = mips32_read_core_reg;
429 mips32->write_core_reg = mips32_write_core_reg;
430 /* if unknown endianness defaults to little endian, 1 */
431 mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1;
432 mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE;
433 mips32->ejtag_info.mode = 0; /* Initial default value */
434 mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */
435 mips32->ejtag_info.config_regs = 0; /* no config register read */
436 return ERROR_OK;
437 }
438
439 /* run to exit point. return error if exit point was not reached. */
440 static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
441 unsigned int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32)
442 {
443 uint32_t pc;
444 int retval;
445 /* This code relies on the target specific resume() and poll()->debug_entry()
446 * sequence to write register values to the processor and the read them back */
447 retval = target_resume(target, 0, entry_point, 0, 1);
448 if (retval != ERROR_OK)
449 return retval;
450
451 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
452 /* If the target fails to halt due to the breakpoint, force a halt */
453 if (retval != ERROR_OK || target->state != TARGET_HALTED) {
454 retval = target_halt(target);
455 if (retval != ERROR_OK)
456 return retval;
457 retval = target_wait_state(target, TARGET_HALTED, 500);
458 if (retval != ERROR_OK)
459 return retval;
460 return ERROR_TARGET_TIMEOUT;
461 }
462
463 pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
464 if (exit_point && (pc != exit_point)) {
465 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
466 return ERROR_TARGET_TIMEOUT;
467 }
468
469 return ERROR_OK;
470 }
471
472 int mips32_run_algorithm(struct target *target, int num_mem_params,
473 struct mem_param *mem_params, int num_reg_params,
474 struct reg_param *reg_params, target_addr_t entry_point,
475 target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
476 {
477 struct mips32_common *mips32 = target_to_mips32(target);
478 struct mips32_algorithm *mips32_algorithm_info = arch_info;
479 enum mips32_isa_mode isa_mode = mips32->isa_mode;
480
481 uint32_t context[MIPS32_NUM_REGS];
482 int retval = ERROR_OK;
483
484 LOG_DEBUG("Running algorithm");
485
486 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
487 * at the exit point */
488
489 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
490 LOG_ERROR("current target isn't a MIPS32 target");
491 return ERROR_TARGET_INVALID;
492 }
493
494 if (target->state != TARGET_HALTED) {
495 LOG_TARGET_ERROR(target, "not halted (run target algo)");
496 return ERROR_TARGET_NOT_HALTED;
497 }
498
499 /* refresh core register cache */
500 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
501 if (!mips32->core_cache->reg_list[i].valid)
502 mips32->read_core_reg(target, i);
503 context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
504 }
505
506 for (int i = 0; i < num_mem_params; i++) {
507 if (mem_params[i].direction == PARAM_IN)
508 continue;
509 retval = target_write_buffer(target, mem_params[i].address,
510 mem_params[i].size, mem_params[i].value);
511 if (retval != ERROR_OK)
512 return retval;
513 }
514
515 for (int i = 0; i < num_reg_params; i++) {
516 if (reg_params[i].direction == PARAM_IN)
517 continue;
518
519 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, false);
520
521 if (!reg) {
522 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
523 return ERROR_COMMAND_SYNTAX_ERROR;
524 }
525
526 if (reg->size != reg_params[i].size) {
527 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
528 reg_params[i].reg_name);
529 return ERROR_COMMAND_SYNTAX_ERROR;
530 }
531
532 mips32_set_core_reg(reg, reg_params[i].value);
533 }
534
535 mips32->isa_mode = mips32_algorithm_info->isa_mode;
536
537 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
538
539 if (retval != ERROR_OK)
540 return retval;
541
542 for (int i = 0; i < num_mem_params; i++) {
543 if (mem_params[i].direction != PARAM_OUT) {
544 retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
545 mem_params[i].value);
546 if (retval != ERROR_OK)
547 return retval;
548 }
549 }
550
551 for (int i = 0; i < num_reg_params; i++) {
552 if (reg_params[i].direction != PARAM_OUT) {
553 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, false);
554 if (!reg) {
555 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
556 return ERROR_COMMAND_SYNTAX_ERROR;
557 }
558
559 if (reg->size != reg_params[i].size) {
560 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
561 reg_params[i].reg_name);
562 return ERROR_COMMAND_SYNTAX_ERROR;
563 }
564
565 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
566 }
567 }
568
569 /* restore everything we saved before */
570 for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
571 uint32_t regvalue;
572 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
573 if (regvalue != context[i]) {
574 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
575 mips32->core_cache->reg_list[i].name, context[i]);
576 buf_set_u32(mips32->core_cache->reg_list[i].value,
577 0, 32, context[i]);
578 mips32->core_cache->reg_list[i].valid = true;
579 mips32->core_cache->reg_list[i].dirty = true;
580 }
581 }
582
583 mips32->isa_mode = isa_mode;
584
585 return ERROR_OK;
586 }
587
588 int mips32_examine(struct target *target)
589 {
590 struct mips32_common *mips32 = target_to_mips32(target);
591
592 if (!target_was_examined(target)) {
593 target_set_examined(target);
594
595 /* we will configure later */
596 mips32->bp_scanned = 0;
597 mips32->num_inst_bpoints = 0;
598 mips32->num_data_bpoints = 0;
599 mips32->num_inst_bpoints_avail = 0;
600 mips32->num_data_bpoints_avail = 0;
601 }
602
603 return ERROR_OK;
604 }
605
606 static int mips32_configure_ibs(struct target *target)
607 {
608 struct mips32_common *mips32 = target_to_mips32(target);
609 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
610 int retval, i;
611 uint32_t bpinfo;
612
613 /* get number of inst breakpoints */
614 retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
615 if (retval != ERROR_OK)
616 return retval;
617
618 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
619 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
620 mips32->inst_break_list = calloc(mips32->num_inst_bpoints,
621 sizeof(struct mips32_comparator));
622
623 for (i = 0; i < mips32->num_inst_bpoints; i++)
624 mips32->inst_break_list[i].reg_address =
625 ejtag_info->ejtag_iba0_addr +
626 (ejtag_info->ejtag_iba_step_size * i);
627
628 /* clear IBIS reg */
629 retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
630 return retval;
631 }
632
633 static int mips32_configure_dbs(struct target *target)
634 {
635 struct mips32_common *mips32 = target_to_mips32(target);
636 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
637 int retval, i;
638 uint32_t bpinfo;
639
640 /* get number of data breakpoints */
641 retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
642 if (retval != ERROR_OK)
643 return retval;
644
645 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
646 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
647 mips32->data_break_list = calloc(mips32->num_data_bpoints,
648 sizeof(struct mips32_comparator));
649
650 for (i = 0; i < mips32->num_data_bpoints; i++)
651 mips32->data_break_list[i].reg_address =
652 ejtag_info->ejtag_dba0_addr +
653 (ejtag_info->ejtag_dba_step_size * i);
654
655 /* clear DBIS reg */
656 retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
657 return retval;
658 }
659
660 int mips32_configure_break_unit(struct target *target)
661 {
662 /* get pointers to arch-specific information */
663 struct mips32_common *mips32 = target_to_mips32(target);
664 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
665 int retval;
666 uint32_t dcr;
667
668 if (mips32->bp_scanned)
669 return ERROR_OK;
670
671 /* get info about breakpoint support */
672 retval = target_read_u32(target, EJTAG_DCR, &dcr);
673 if (retval != ERROR_OK)
674 return retval;
675
676 /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */
677 if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
678 ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM;
679 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB))
680 ejtag_info->debug_caps |= EJTAG_DCR_IB;
681 if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB))
682 ejtag_info->debug_caps |= EJTAG_DCR_DB;
683 } else
684 /* keep debug caps for later use */
685 ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM
686 | EJTAG_DCR_IB | EJTAG_DCR_DB);
687
688
689 if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
690 retval = mips32_configure_ibs(target);
691 if (retval != ERROR_OK)
692 return retval;
693 }
694
695 if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
696 retval = mips32_configure_dbs(target);
697 if (retval != ERROR_OK)
698 return retval;
699 }
700
701 /* check if target endianness settings matches debug control register */
702 if (((ejtag_info->debug_caps & EJTAG_DCR_ENM)
703 && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
704 (!(ejtag_info->debug_caps & EJTAG_DCR_ENM)
705 && (target->endianness == TARGET_BIG_ENDIAN)))
706 LOG_WARNING("DCR endianness settings does not match target settings");
707
708 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
709 mips32->num_data_bpoints);
710
711 mips32->bp_scanned = 1;
712
713 return ERROR_OK;
714 }
715
716 int mips32_enable_interrupts(struct target *target, int enable)
717 {
718 int retval;
719 int update = 0;
720 uint32_t dcr;
721
722 /* read debug control register */
723 retval = target_read_u32(target, EJTAG_DCR, &dcr);
724 if (retval != ERROR_OK)
725 return retval;
726
727 if (enable) {
728 if (!(dcr & EJTAG_DCR_INTE)) {
729 /* enable interrupts */
730 dcr |= EJTAG_DCR_INTE;
731 update = 1;
732 }
733 } else {
734 if (dcr & EJTAG_DCR_INTE) {
735 /* disable interrupts */
736 dcr &= ~EJTAG_DCR_INTE;
737 update = 1;
738 }
739 }
740
741 if (update) {
742 retval = target_write_u32(target, EJTAG_DCR, dcr);
743 if (retval != ERROR_OK)
744 return retval;
745 }
746
747 return ERROR_OK;
748 }
749
750 /* read processor identification cp0 register */
751 static int mips32_read_c0_prid(struct target *target)
752 {
753 struct mips32_common *mips32 = target_to_mips32(target);
754 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
755 int retval;
756
757 retval = mips32_cp0_read(ejtag_info, &mips32->prid, 15, 0);
758 if (retval != ERROR_OK) {
759 LOG_ERROR("processor id not available, failed to read cp0 PRId register");
760 mips32->prid = 0;
761 }
762
763 return retval;
764 }
765
766 /**
767 * mips32_find_cpu_by_prid - Find CPU information by processor ID.
768 * @param[in] prid: Processor ID of the CPU.
769 *
770 * @brief This function looks up the CPU entry in the mips32_cpu_entry array based on the provided
771 * processor ID. It also handles special cases like AMD/Alchemy CPUs that use Company Options
772 * instead of Processor IDs.
773 *
774 * @return Pointer to the corresponding cpu_entry struct, or the 'unknown' entry if not found.
775 */
776 static const struct cpu_entry *mips32_find_cpu_by_prid(uint32_t prid)
777 {
778 /* AMD/Alchemy CPU uses Company Options instead of Processor ID.
779 * Therefore an extra transform step for prid to map it to an assigned ID,
780 */
781 if ((prid & PRID_COMP_MASK) == PRID_COMP_ALCHEMY) {
782 /* Clears Processor ID field, then put Company Option field to its place */
783 prid = (prid & 0xFFFF00FF) | ((prid & 0xFF000000) >> 16);
784 }
785
786 /* Mask out Company Option */
787 prid &= 0x00FFFFFF;
788
789 for (unsigned int i = 0; i < MIPS32_NUM_CPU_ENTRIES; i++) {
790 const struct cpu_entry *entry = &mips32_cpu_entry[i];
791 if ((entry->prid & MIPS32_CORE_MASK) <= prid && prid <= entry->prid)
792 return entry;
793 }
794
795 /* If nothing matched, then return unknown entry */
796 return &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1];
797 }
798
799 /**
800 * mips32_cpu_probe - Detects processor type and applies necessary quirks.
801 * @param[in] target: The target CPU to probe.
802 *
803 * @brief This function probes the CPU, reads its PRID (Processor ID), and determines the CPU type.
804 * It applies any quirks necessary for specific processor types.
805 *
806 * NOTE: The proper detection of certain CPUs can become quite complicated.
807 * Please consult the following Linux kernel code when adding new CPUs:
808 * arch/mips/include/asm/cpu.h
809 * arch/mips/kernel/cpu-probe.c
810 *
811 * @return ERROR_OK on success; error code on failure.
812 */
813 int mips32_cpu_probe(struct target *target)
814 {
815 struct mips32_common *mips32 = target_to_mips32(target);
816 int retval;
817
818 if (mips32->prid)
819 return ERROR_OK; /* Already probed once, return early. */
820
821 retval = mips32_read_c0_prid(target);
822 if (retval != ERROR_OK)
823 return retval;
824
825 const struct cpu_entry *entry = mips32_find_cpu_by_prid(mips32->prid);
826
827 switch (mips32->prid & PRID_COMP_MASK) {
828 case PRID_COMP_INGENIC_E1:
829 switch (mips32->prid & PRID_IMP_MASK) {
830 case PRID_IMP_XBURST_REV1:
831 mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET;
832 break;
833 default:
834 break;
835 }
836 break;
837
838 /* Determine which CP0 registers are available in the current processor core */
839 case PRID_COMP_MTI:
840 switch (entry->prid & PRID_IMP_MASK) {
841 case PRID_IMP_MAPTIV_UC:
842 mips32->cp0_mask = MIPS_CP0_MAPTIV_UC;
843 break;
844 case PRID_IMP_MAPTIV_UP:
845 case PRID_IMP_M5150:
846 mips32->cp0_mask = MIPS_CP0_MAPTIV_UP;
847 break;
848 case PRID_IMP_IAPTIV:
849 case PRID_IMP_IAPTIV_CM:
850 mips32->cp0_mask = MIPS_CP0_IAPTIV;
851 break;
852 default:
853 /* CP0 mask should be the same as MK4 by default */
854 mips32->cp0_mask = MIPS_CP0_MK4;
855 break;
856 }
857
858 default:
859 break;
860 }
861
862 mips32->cpu_info = entry;
863 LOG_DEBUG("CPU: %s (PRId %08x)", entry->cpu_name, mips32->prid);
864
865 return ERROR_OK;
866 }
867
868 /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/
869 static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
870 {
871 uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT);
872 if (dsp_present) {
873 mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1;
874 LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp);
875 } else {
876 LOG_USER("DSP implemented: %s", "no");
877 }
878 }
879
880 /* read fpu implementation info from CP0 Config1 register {CU1, FP}*/
881 static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
882 {
883 int retval;
884 uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT;
885 char buf[60] = {0};
886 if (!fp_imp) {
887 LOG_USER("FPU implemented: %s", "no");
888 mips32->fp_imp = MIPS32_FP_IMP_NONE;
889 return ERROR_OK;
890 }
891 uint32_t status_value;
892 bool status_fr, status_cu1;
893
894 retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
895 if (retval != ERROR_OK) {
896 LOG_ERROR("Failed to read cp0 status register");
897 return retval;
898 }
899
900 status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1;
901 status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1;
902 if (status_cu1) {
903 /* TODO: read fpu(cp1) config register for current operating mode.
904 * Now its set to 32 bits by default. */
905 snprintf(buf, sizeof(buf), "yes");
906 fp_imp = MIPS32_FP_IMP_32;
907 } else {
908 snprintf(buf, sizeof(buf), "yes, disabled");
909 fp_imp = MIPS32_FP_IMP_UNKNOWN;
910 }
911
912 mips32->fpu_in_64bit = status_fr;
913 mips32->fpu_enabled = status_cu1;
914
915 LOG_USER("FPU implemented: %s", buf);
916 mips32->fp_imp = fp_imp;
917
918 return ERROR_OK;
919 }
920
921 /**
922 * mips32_read_config_fdc - Read Fast Debug Channel configuration
923 * @param[in,out] mips32: MIPS32 common structure
924 * @param[in] ejtag_info: EJTAG information structure
925 * @param[in] dcr: Device Configuration Register value
926 *
927 * @brief Checks if the current target implements the Common Device Memory Map (CDMM) and Fast Debug Channel (FDC).
928 *
929 * This function examines the configuration registers and the Device Configuration Register (DCR) to determine
930 * if the current MIPS32 target supports the Common Device Memory Map (CDMM) and the Fast Debug Channel (FDC).
931 * If supported, it sets the corresponding flags in the MIPS32 common structure. \n
932 *
933 * NOTE:These are defined on MD00090, page 67 and MD00047F, page 82, respectively.
934 * MIPS Documents are pretty much all available online,
935 * it should pop up first when you search "MDxxxxx"
936 */
937 static void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr)
938 {
939 if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) {
940 mips32->fdc = 1;
941 mips32->semihosting = 1;
942 } else {
943 mips32->fdc = 0;
944 mips32->semihosting = 0;
945 }
946 }
947
948 /* read config to config3 cp0 registers and log isa implementation */
949 int mips32_read_config_regs(struct target *target)
950 {
951 struct mips32_common *mips32 = target_to_mips32(target);
952 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
953 char buf[60] = {0};
954 int retval;
955
956 if (ejtag_info->config_regs == 0)
957 for (int i = 0; i != 4; i++) {
958 retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
959 if (retval != ERROR_OK) {
960 LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
961 ejtag_info->config_regs = 0;
962 return retval;
963 }
964 ejtag_info->config_regs = i + 1;
965 if ((ejtag_info->config[i] & (1 << 31)) == 0)
966 break; /* no more config registers implemented */
967 }
968 else
969 return ERROR_OK; /* already successfully read */
970
971 LOG_DEBUG("read %"PRIu32" config registers", ejtag_info->config_regs);
972
973 mips32->isa_rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
974 snprintf(buf, sizeof(buf), ", release %s(AR=%d)",
975 mips32->isa_rel == MIPS32_RELEASE_1 ? "1"
976 : mips32->isa_rel == MIPS32_RELEASE_2 ? "2"
977 : mips32->isa_rel == MIPS32_RELEASE_6 ? "6"
978 : "unknown", mips32->isa_rel);
979
980 if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
981 mips32->isa_imp = MIPS32_MIPS16;
982 LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf);
983 } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
984 unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
985 if (isa_imp == 1) {
986 mips32->isa_imp = MMIPS32_ONLY;
987 LOG_USER("ISA implemented: %s%s", "microMIPS32", buf);
988
989 } else if (isa_imp != 0) {
990 mips32->isa_imp = MIPS32_MMIPS32;
991 LOG_USER("ISA implemented: %s%s", "MIPS32, microMIPS32", buf);
992 }
993 } else if (mips32->isa_imp == MIPS32_ONLY) {
994 /* initial default value */
995 LOG_USER("ISA implemented: %s%s", "MIPS32", buf);
996 }
997
998 /* Retrieve DSP info */
999 mips32_read_config_dsp(mips32, ejtag_info);
1000
1001 /* Retrieve if Float Point CoProcessor Implemented */
1002 retval = mips32_read_config_fpu(mips32, ejtag_info);
1003 if (retval != ERROR_OK) {
1004 LOG_ERROR("fpu info is not available, error while reading cp0 status");
1005 mips32->fp_imp = MIPS32_FP_IMP_NONE;
1006 return retval;
1007 }
1008
1009 uint32_t dcr;
1010
1011 retval = target_read_u32(target, EJTAG_DCR, &dcr);
1012 if (retval != ERROR_OK) {
1013 LOG_ERROR("failed to read EJTAG_DCR register");
1014 return retval;
1015 }
1016
1017 /* Determine if FDC and CDMM are implemented for this core */
1018 mips32_read_config_fdc(mips32, ejtag_info, dcr);
1019
1020 return ERROR_OK;
1021 }
1022
1023 int mips32_checksum_memory(struct target *target, target_addr_t address,
1024 uint32_t count, uint32_t *checksum)
1025 {
1026 struct working_area *crc_algorithm;
1027 struct reg_param reg_params[2];
1028 struct mips32_algorithm mips32_info;
1029
1030 struct mips32_common *mips32 = target_to_mips32(target);
1031 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1032
1033 /* see contrib/loaders/checksum/mips32.s for src */
1034 uint32_t isa = ejtag_info->isa ? 1 : 0;
1035
1036 uint32_t mips_crc_code[] = {
1037 MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */
1038 MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */
1039 MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */
1040 MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */
1041 MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */
1042 /* nbyte: */
1043 MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */
1044 MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */
1045 MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */
1046 MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */
1047 MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */
1048 MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */
1049 MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */
1050 /* loop */
1051 MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */
1052 MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */
1053 MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */
1054 MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */
1055 MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */
1056 MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */
1057 MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */
1058 MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */
1059 /* ncomp */
1060 MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */
1061 MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */
1062 MIPS32_SDBBP(isa),
1063 };
1064
1065 /* make sure we have a working area */
1066 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
1067 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1068
1069 pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code));
1070
1071 /* convert mips crc code into a buffer in target endianness */
1072 uint8_t mips_crc_code_8[sizeof(mips_crc_code)];
1073 target_buffer_set_u32_array(target, mips_crc_code_8,
1074 ARRAY_SIZE(mips_crc_code), mips_crc_code);
1075
1076 int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8);
1077 if (retval != ERROR_OK)
1078 return retval;
1079
1080 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
1081 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */
1082
1083 init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
1084 buf_set_u32(reg_params[0].value, 0, 32, address);
1085
1086 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
1087 buf_set_u32(reg_params[1].value, 0, 32, count);
1088
1089 unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
1090
1091 retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
1092 crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);
1093
1094 if (retval == ERROR_OK)
1095 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
1096
1097 destroy_reg_param(&reg_params[0]);
1098 destroy_reg_param(&reg_params[1]);
1099
1100 target_free_working_area(target, crc_algorithm);
1101
1102 return retval;
1103 }
1104
1105 /** Checks whether a memory region is erased. */
1106 int mips32_blank_check_memory(struct target *target,
1107 struct target_memory_check_block *blocks, int num_blocks,
1108 uint8_t erased_value)
1109 {
1110 struct working_area *erase_check_algorithm;
1111 struct reg_param reg_params[3];
1112 struct mips32_algorithm mips32_info;
1113
1114 struct mips32_common *mips32 = target_to_mips32(target);
1115 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1116
1117 if (erased_value != 0xff) {
1118 LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32",
1119 erased_value);
1120 return ERROR_FAIL;
1121 }
1122 uint32_t isa = ejtag_info->isa ? 1 : 0;
1123 uint32_t erase_check_code[] = {
1124 /* nbyte: */
1125 MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */
1126 MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */
1127 MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */
1128 MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */
1129 MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */
1130 MIPS32_SDBBP(isa) /* sdbbp */
1131 };
1132
1133 /* make sure we have a working area */
1134 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
1135 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1136
1137 pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code));
1138
1139 /* convert erase check code into a buffer in target endianness */
1140 uint8_t erase_check_code_8[sizeof(erase_check_code)];
1141 target_buffer_set_u32_array(target, erase_check_code_8,
1142 ARRAY_SIZE(erase_check_code), erase_check_code);
1143
1144 int retval = target_write_buffer(target, erase_check_algorithm->address,
1145 sizeof(erase_check_code), erase_check_code_8);
1146 if (retval != ERROR_OK)
1147 goto cleanup;
1148
1149 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
1150 mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
1151
1152 init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
1153 buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
1154
1155 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
1156 buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
1157
1158 init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
1159 buf_set_u32(reg_params[2].value, 0, 32, erased_value);
1160
1161 retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
1162 erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
1163
1164 if (retval == ERROR_OK)
1165 blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
1166
1167 destroy_reg_param(&reg_params[0]);
1168 destroy_reg_param(&reg_params[1]);
1169 destroy_reg_param(&reg_params[2]);
1170
1171 cleanup:
1172 target_free_working_area(target, erase_check_algorithm);
1173
1174 if (retval != ERROR_OK)
1175 return retval;
1176
1177 return 1; /* only one block has been checked */
1178 }
1179
1180 static int mips32_verify_pointer(struct command_invocation *cmd,
1181 struct mips32_common *mips32)
1182 {
1183 if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
1184 command_print(cmd, "target is not an MIPS32");
1185 return ERROR_TARGET_INVALID;
1186 }
1187 return ERROR_OK;
1188 }
1189
1190 /**
1191 * mips32_read_config_mmu - Reads MMU configuration and logs relevant information.
1192 * @param[in] ejtag_info: EJTAG interface information.
1193 *
1194 * @brief Reads the MMU configuration from the CP0 register and calculates the number of TLB entries,
1195 * ways, and sets. Handles different MMU types like VTLB only, root RPU/Fixed, and VTLB and FTLB.
1196 *
1197 * @return ERROR_OK on success; error code on failure.
1198 */
1199 static int mips32_read_config_mmu(struct mips_ejtag *ejtag_info)
1200 {
1201 uint32_t config4, tlb_entries = 0, ways = 0, sets = 0;
1202 uint32_t config0 = ejtag_info->config[0];
1203 uint32_t config1 = ejtag_info->config[1];
1204 uint32_t config3 = ejtag_info->config[3];
1205 uint32_t mmu_type = (config0 >> 7) & 7;
1206 uint32_t vz_present = (config3 & BIT(23));
1207
1208 int retval = mips32_cp0_read(ejtag_info, &config4, 16, 4);
1209 if (retval != ERROR_OK)
1210 return retval;
1211
1212 /* mmu type = 1: VTLB only (Note: Does not account for Config4.ExtVTLB)
1213 * mmu type = 3: root RPU/Fixed (Note: Only valid with VZ ASE)
1214 * mmu type = 4: VTLB and FTLB
1215 */
1216 if ((mmu_type == 1 || mmu_type == 4) || (mmu_type == 3 && vz_present)) {
1217 tlb_entries = (uint32_t)(((config1 >> 25) & 0x3f) + 1);
1218 if (mmu_type == 4) {
1219 /* Release 6 definition for Config4[0:15] (MD01251, page 243) */
1220 /* The FTLB ways field is defined as [2, 3, 4, 5, 6, 7, 8, ...0 (reserved)] */
1221 int index = ((config4 >> 4) & 0xf);
1222 ways = index > 6 ? 0 : index + 2;
1223
1224 /* The FTLB sets field is defined as [1, 2, 4, 8, ..., 16384, 32768] (powers of 2) */
1225 index = (config4 & 0xf);
1226 sets = 1 << index;
1227 tlb_entries = tlb_entries + (ways * sets);
1228 }
1229 }
1230 LOG_USER("TLB Entries: %d (%d ways, %d sets per way)", tlb_entries, ways, sets);
1231
1232 return ERROR_OK;
1233 }
1234
1235 /**
1236 * mips32_cp0_find_register_by_name - Find CP0 register by its name.
1237 * @param[in] cp0_mask: Mask to filter out irrelevant registers.
1238 * @param[in] reg_name: Name of the register to find.
1239 *
1240 * @brief This function iterates through mips32_cp0_regs to find a register
1241 * matching reg_name, considering cp0_mask to filter out registers
1242 * not relevant for the current core.
1243 *
1244 * @return Pointer to the found register, or NULL if not found.
1245 */
1246 static const struct mips32_cp0 *mips32_cp0_find_register_by_name(uint32_t cp0_mask, const char *reg_name)
1247 {
1248 if (reg_name)
1249 for (unsigned int i = 0; i < MIPS32NUMCP0REGS; i++) {
1250 if ((mips32_cp0_regs[i].core & cp0_mask) == 0)
1251 continue;
1252
1253 if (strcmp(mips32_cp0_regs[i].name, reg_name) == 0)
1254 return &mips32_cp0_regs[i];
1255 }
1256 return NULL;
1257 }
1258
1259 /**
1260 * mips32_cp0_get_all_regs - Print all CP0 registers and their values.
1261 * @param[in] cmd: Command invocation context.
1262 * @param[in] ejtag_info: EJTAG interface information.
1263 * @param[in] cp0_mask: Mask to identify relevant registers.
1264 *
1265 * @brief Iterates over all CP0 registers, reads their values, and prints them.
1266 * Only considers registers relevant to the current core, as defined by cp0_mask.
1267 *
1268 * @return ERROR_OK on success; error code on failure.
1269 */
1270 static int mips32_cp0_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info, uint32_t cp0_mask)
1271 {
1272 uint32_t value;
1273
1274 for (unsigned int i = 0; i < MIPS32NUMCP0REGS; i++) {
1275 /* Register name not valid for this core */
1276 if ((mips32_cp0_regs[i].core & cp0_mask) == 0)
1277 continue;
1278
1279 int retval = mips32_cp0_read(ejtag_info, &value, mips32_cp0_regs[i].reg, mips32_cp0_regs[i].sel);
1280 if (retval != ERROR_OK) {
1281 command_print(CMD, "Error: couldn't access reg %s", mips32_cp0_regs[i].name);
1282 return retval;
1283 }
1284
1285 command_print(CMD, "%*s: 0x%8.8" PRIx32, 14, mips32_cp0_regs[i].name, value);
1286 }
1287 return ERROR_OK;
1288 }
1289
1290 /**
1291 * mips32_cp0_get_reg_by_name - Read and print a CP0 register's value by name.
1292 * @param[in] cmd: Command invocation context.
1293 * @param[in] ejtag_info: EJTAG interface information.
1294 * @param[in] cp0_mask: Mask to identify relevant registers.
1295 *
1296 * @brief Finds a CP0 register by name, reads its value, and prints it.
1297 * Handles error scenarios like register not found or read failure.
1298 *
1299 * @return ERROR_OK on success; error code on failure.
1300 */
1301 static int mips32_cp0_get_reg_by_name(struct command_invocation *cmd, struct mips_ejtag *ejtag_info, uint32_t cp0_mask)
1302 {
1303 const struct mips32_cp0 *cp0_regs = mips32_cp0_find_register_by_name(cp0_mask, CMD_ARGV[0]);
1304 if (!cp0_regs) {
1305 command_print(CMD, "Error: Register '%s' not found", CMD_ARGV[0]);
1306 return ERROR_COMMAND_ARGUMENT_INVALID;
1307 }
1308
1309 uint32_t value;
1310 int retval = mips32_cp0_read(ejtag_info, &value, cp0_regs->reg, cp0_regs->sel);
1311 if (retval != ERROR_OK) {
1312 command_print(CMD, "Error: Encounter an Error while reading cp0 reg %d sel %d",
1313 cp0_regs->reg, cp0_regs->sel);
1314 return retval;
1315 }
1316
1317 command_print(CMD, "0x%8.8" PRIx32, value);
1318 return ERROR_OK;
1319 }
1320
1321 /**
1322 * mips32_cp0_get_reg_by_number - Read and print a CP0 register's value by number.
1323 * @param[in] cmd: Command invocation context.
1324 * @param[in] ejtag_info: EJTAG interface information.
1325 *
1326 * @brief Reads a specific CP0 register (identified by number and selection) and prints its value.
1327 * The register number and selection are parsed from the command arguments.
1328 *
1329 * @return ERROR_OK on success; error code on failure.
1330 */
1331 static int mips32_cp0_get_reg_by_number(struct command_invocation *cmd, struct mips_ejtag *ejtag_info)
1332 {
1333 uint32_t cp0_reg, cp0_sel, value;
1334 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
1335 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
1336
1337 int retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
1338 if (retval != ERROR_OK) {
1339 command_print(CMD,
1340 "Error: couldn't access reg %" PRIu32,
1341 cp0_reg);
1342 return retval;
1343 }
1344
1345 command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32,
1346 cp0_reg, cp0_sel, value);
1347 return ERROR_OK;
1348 }
1349
1350 /**
1351 * mips32_cp0_set_reg_by_name - Write to a CP0 register identified by name.
1352 * @param[in] cmd: Command invocation context.
1353 * @param[in] mips32: Common MIPS32 data structure.
1354 * @param[in] ejtag_info: EJTAG interface information.
1355 *
1356 * @brief Writes a value to a CP0 register specified by name. Updates internal
1357 * cache if specific registers (STATUS, CAUSE, DEPC, GUESTCTL1) are modified.
1358 *
1359 * @return ERROR_OK on success; error code on failure.
1360 */
1361 static int mips32_cp0_set_reg_by_name(struct command_invocation *cmd,
1362 struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
1363 {
1364 const struct mips32_cp0 *cp0_regs = mips32_cp0_find_register_by_name(mips32->cp0_mask, CMD_ARGV[0]);
1365 if (!cp0_regs) {
1366 command_print(CMD, "Error: Register '%s' not found", CMD_ARGV[0]);
1367 return ERROR_COMMAND_ARGUMENT_INVALID;
1368 }
1369
1370
1371 uint32_t value;
1372 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
1373
1374 if (cp0_regs->reg == MIPS32_C0_STATUS && cp0_regs->sel == 0) {
1375 /* Update cached Status register if user is writing to Status */
1376 mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] = value;
1377 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_STATUS_INDEX].dirty = 1;
1378 } else if (cp0_regs->reg == MIPS32_C0_CAUSE && cp0_regs->sel == 0) {
1379 /* Update register cache with new value if its Cause */
1380 mips32->core_regs.cp0[MIPS32_REG_C0_CAUSE_INDEX] = value;
1381 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_CAUSE_INDEX].dirty = 1;
1382 } else if (cp0_regs->reg == MIPS32_C0_DEPC && cp0_regs->sel == 0) {
1383 /* Update cached PC if its DEPC */
1384 mips32->core_regs.cp0[MIPS32_REG_C0_PC_INDEX] = value;
1385 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = 1;
1386 } else if (cp0_regs->reg == MIPS32_C0_GUESTCTL1 && cp0_regs->sel == 4) {
1387 /* Update cached guestCtl1 */
1388 mips32->core_regs.cp0[MIPS32_REG_C0_GUESTCTL1_INDEX] = value;
1389 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_GUESTCTL1_INDEX].dirty = 1;
1390 }
1391
1392 int retval = mips32_cp0_write(ejtag_info, value,
1393 cp0_regs->reg,
1394 cp0_regs->sel);
1395 if (retval != ERROR_OK) {
1396 command_print(CMD, "Error: Encounter an Error while writing to cp0 reg %d, sel %d",
1397 cp0_regs->reg, cp0_regs->sel);
1398 return retval;
1399 }
1400
1401 command_print(CMD, "cp0 reg %s (%u, select %u: %8.8" PRIx32 ")",
1402 CMD_ARGV[0], cp0_regs->reg, cp0_regs->sel, value);
1403 return ERROR_OK;
1404 }
1405
1406 /**
1407 * mips32_cp0_set_reg_by_number - Write to a CP0 register identified by number.
1408 * @param[in] cmd: Command invocation context.
1409 * @param[in] mips32: Common MIPS32 data structure.
1410 * @param[in] ejtag_info: EJTAG interface information.
1411 *
1412 * @brief Writes a value to a CP0 register specified by number and selection.
1413 * Handles special cases like updating the internal cache for certain registers.
1414 *
1415 * @return ERROR_OK on success; error code on failure.
1416 */
1417 static int mips32_cp0_set_reg_by_number(struct command_invocation *cmd,
1418 struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
1419 {
1420 uint32_t cp0_reg, cp0_sel, value;
1421 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
1422 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
1423 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
1424
1425 if (cp0_reg == MIPS32_C0_STATUS && cp0_sel == 0) {
1426 /* Update cached status register if user is writing to Status register */
1427 mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] = value;
1428 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_STATUS_INDEX].dirty = 1;
1429 } else if (cp0_reg == MIPS32_C0_CAUSE && cp0_sel == 0) {
1430 /* Update register cache with new value if its Cause register */
1431 mips32->core_regs.cp0[MIPS32_REG_C0_CAUSE_INDEX] = value;
1432 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_CAUSE_INDEX].dirty = 1;
1433 } else if (cp0_reg == MIPS32_C0_DEPC && cp0_sel == 0) {
1434 /* Update cached PC if its DEPC */
1435 mips32->core_regs.cp0[MIPS32_REG_C0_PC_INDEX] = value;
1436 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = 1;
1437 } else if (cp0_reg == MIPS32_C0_GUESTCTL1 && cp0_sel == 4) {
1438 /* Update cached guestCtl1, too */
1439 mips32->core_regs.cp0[MIPS32_REG_C0_GUESTCTL1_INDEX] = value;
1440 mips32->core_cache->reg_list[MIPS32_REGLIST_C0_GUESTCTL1_INDEX].dirty = 1;
1441 }
1442
1443 int retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
1444 if (retval != ERROR_OK) {
1445 command_print(CMD,
1446 "Error: couldn't access cp0 reg %" PRIu32 ", select %" PRIu32,
1447 cp0_reg, cp0_sel);
1448 return retval;
1449 }
1450
1451 command_print(CMD, "cp0 reg %" PRIu32 ", select %" PRIu32 ": %8.8" PRIx32,
1452 cp0_reg, cp0_sel, value);
1453 return ERROR_OK;
1454 }
1455
1456 /**
1457 * mips32_handle_cp0_command - Handle commands related to CP0 registers.
1458 * @cmd: Command invocation context.
1459 *
1460 * Orchestrates different operations on CP0 registers based on the command arguments.
1461 * Supports operations like reading all registers, reading/writing a specific register
1462 * by name or number.
1463 *
1464 * Return: ERROR_OK on success; error code on failure.
1465 */
1466 COMMAND_HANDLER(mips32_handle_cp0_command)
1467 {
1468 int retval, tmp;
1469 struct target *target = get_current_target(CMD_CTX);
1470 struct mips32_common *mips32 = target_to_mips32(target);
1471 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1472
1473
1474 retval = mips32_verify_pointer(CMD, mips32);
1475 if (retval != ERROR_OK)
1476 return retval;
1477
1478 if (target->state != TARGET_HALTED) {
1479 command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
1480 return ERROR_TARGET_NOT_HALTED;
1481 }
1482
1483 switch (CMD_ARGC) {
1484 case 0: /* No arg => print out all cp0 regs */
1485 retval = mips32_cp0_get_all_regs(CMD, ejtag_info, mips32->cp0_mask);
1486 break;
1487 case 1: /* 1 arg => get cp0 #reg/#sel value by name */
1488 retval = mips32_cp0_get_reg_by_name(CMD, ejtag_info, mips32->cp0_mask);
1489 break;
1490 case 2: /* 2 args => get cp0 reg/sel value or set value by name */
1491 tmp = *CMD_ARGV[0];
1492 if (isdigit(tmp)) /* starts from number then args are #reg and #sel */
1493 retval = mips32_cp0_get_reg_by_number(CMD, ejtag_info);
1494 else /* or set value by register name */
1495 retval = mips32_cp0_set_reg_by_name(CMD, mips32, ejtag_info);
1496
1497 break;
1498 case 3: /* 3 args => set cp0 reg/sel value*/
1499 retval = mips32_cp0_set_reg_by_number(CMD, mips32, ejtag_info);
1500 break;
1501 default: /* Other argc => err */
1502 retval = ERROR_COMMAND_SYNTAX_ERROR;
1503 break;
1504 }
1505
1506 return retval;
1507 }
1508
1509 /**
1510 * mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command.
1511 * @param[in] cmd: Command invocation context.
1512 *
1513 * @brief Executes the 'cpuinfo' command which displays detailed information about the current CPU core.
1514 * This includes core type, vendor, instruction set, cache size, and other relevant details.
1515 *
1516 * @return ERROR_OK on success; error code on failure.
1517 */
1518 COMMAND_HANDLER(mips32_handle_cpuinfo_command)
1519 {
1520 int retval;
1521 struct target *target = get_current_target(CMD_CTX);
1522 struct mips32_common *mips32 = target_to_mips32(target);
1523 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1524
1525 uint32_t prid = mips32->prid; /* cp0 PRID - 15, 0 */
1526 uint32_t config0 = ejtag_info->config[0]; /* cp0 config - 16, 0 */
1527 uint32_t config1 = ejtag_info->config[1]; /* cp0 config - 16, 1 */
1528 uint32_t config3 = ejtag_info->config[3]; /* cp0 config - 16, 3 */
1529
1530 /* Following configs are not read during probe */
1531 uint32_t config5; /* cp0 config - 16, 5 */
1532
1533 /* No args for now */
1534 if (CMD_ARGC != 0)
1535 return ERROR_COMMAND_SYNTAX_ERROR;
1536
1537 if (target->state != TARGET_HALTED) {
1538 command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
1539 return ERROR_TARGET_NOT_HALTED;
1540 }
1541
1542 retval = mips32_cp0_read(ejtag_info, &config5, 16, 5);
1543 if (retval != ERROR_OK)
1544 return retval;
1545
1546 /* Determine Core info */
1547 const struct cpu_entry *entry = mips32->cpu_info;
1548 /* Display Core Type info */
1549 command_print(CMD, "CPU Core: %s", entry->cpu_name);
1550
1551 /* Display Core Vendor ID if it's unknown */
1552 if (entry == &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1])
1553 command_print(CMD, "Vendor: Unknown CPU vendor code %x.", ((prid & 0x00ffff00) >> 16));
1554 else
1555 command_print(CMD, "Vendor: %s", entry->vendor);
1556
1557 /* If MIPS release 2 or above, then get exception base info */
1558 enum mips32_isa_rel ar = mips32->isa_rel;
1559 if (ar > MIPS32_RELEASE_1) { /* release 2 and above */
1560 uint32_t ebase;
1561 retval = mips32_cp0_read(ejtag_info, &ebase, 15, 1);
1562 if (retval != ERROR_OK)
1563 return retval;
1564
1565 command_print(CMD, "Current CPU ID: %d", (ebase & 0x1ff));
1566 } else {
1567 command_print(CMD, "Current CPU ID: 0");
1568 }
1569
1570 char *instr;
1571 switch ((config3 & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT) {
1572 case 0:
1573 instr = "MIPS32";
1574 break;
1575 case 1:
1576 instr = "microMIPS";
1577 break;
1578 case 2:
1579 instr = "MIPS32 (at reset) and microMIPS";
1580 break;
1581 case 3:
1582 instr = "microMIPS (at reset) and MIPS32";
1583 break;
1584 }
1585
1586 /* Display Instruction Set Info */
1587 command_print(CMD, "Instr set: %s", instr);
1588 command_print(CMD, "Instr rel: %s",
1589 ar == MIPS32_RELEASE_1 ? "1"
1590 : ar == MIPS32_RELEASE_2 ? "2"
1591 : ar == MIPS32_RELEASE_6 ? "6"
1592 : "unknown");
1593 command_print(CMD, "PRId: %x", prid);
1594 /* Some of MIPS CPU Revisions(for M74K) can be seen on MD00541, page 26 */
1595 uint32_t rev = prid & 0x000000ff;
1596 command_print(CMD, "RTL Rev: %d.%d.%d", (rev & 0xE0), (rev & 0x1C), (rev & 0x3));
1597
1598 command_print(CMD, "Max Number of Instr Breakpoints: %d", mips32->num_inst_bpoints);
1599 command_print(CMD, "Max Number of Data Breakpoints: %d", mips32->num_data_bpoints);
1600
1601 /* MMU Support */
1602 uint32_t mmu_type = (config0 >> 7) & 7; /* MMU Type Info */
1603 char *mmu;
1604 switch (mmu_type) {
1605 case MIPS32_MMU_TLB:
1606 mmu = "TLB";
1607 break;
1608 case MIPS32_MMU_BAT:
1609 mmu = "BAT";
1610 break;
1611 case MIPS32_MMU_FIXED:
1612 mmu = "FIXED";
1613 break;
1614 case MIPS32_MMU_DUAL_VTLB_FTLB:
1615 mmu = "DUAL VAR/FIXED";
1616 break;
1617 default:
1618 mmu = "Unknown";
1619 }
1620 command_print(CMD, "MMU Type: %s", mmu);
1621
1622 retval = mips32_read_config_mmu(ejtag_info);
1623 if (retval != ERROR_OK)
1624 return retval;
1625
1626 /* Definitions of I/D Cache Sizes are available on MD01251, page 224~226 */
1627 int index;
1628 uint32_t ways, sets, bpl;
1629
1630 /* Determine Instr Cache Size */
1631 /* Ways mapping = [1, 2, 3, 4, 5, 6, 7, 8] */
1632 ways = ((config1 >> MIPS32_CFG1_IASHIFT) & 7);
1633
1634 /* Sets per way = [64, 128, 256, 512, 1024, 2048, 4096, 32] */
1635 index = ((config1 >> MIPS32_CFG1_ISSHIFT) & 7);
1636 sets = index == 7 ? 32 : 32 << (index + 1);
1637
1638 /* Bytes per line = [0, 4, 8, 16, 32, 64, 128, Reserved] */
1639 index = ((config1 >> MIPS32_CFG1_ILSHIFT) & 7);
1640 bpl = index == 0 ? 0 : 4 << (index - 1);
1641 command_print(CMD, "Instr Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl);
1642
1643 /* Determine data cache size, same as above */
1644 ways = ((config1 >> MIPS32_CFG1_DASHIFT) & 7);
1645
1646 index = ((config1 >> MIPS32_CFG1_DSSHIFT) & 7);
1647 sets = index == 7 ? 32 : 32 << (index + 1);
1648
1649 index = ((config1 >> MIPS32_CFG1_DLSHIFT) & 7);
1650 bpl = index == 0 ? 0 : 4 << (index - 1);
1651 command_print(CMD, " Data Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl);
1652
1653 /* does the core hava FPU*/
1654 mips32_read_config_fpu(mips32, ejtag_info);
1655
1656 /* does the core support a DSP */
1657 mips32_read_config_dsp(mips32, ejtag_info);
1658
1659 /* VZ module */
1660 uint32_t vzase = (config3 & BIT(23));
1661 if (vzase)
1662 command_print(CMD, "VZ implemented: yes");
1663 else
1664 command_print(CMD, "VZ implemented: no");
1665
1666 /* multithreading */
1667 uint32_t mtase = (config3 & BIT(2));
1668 if (mtase) {
1669 command_print(CMD, "MT implemented: yes");
1670
1671 /* Get VPE and Thread info */
1672 uint32_t tcbind;
1673 uint32_t mvpconf0;
1674
1675 /* Read tcbind register */
1676 retval = mips32_cp0_read(ejtag_info, &tcbind, 2, 2);
1677 if (retval != ERROR_OK)
1678 return retval;
1679
1680 command_print(CMD, " | Current VPE: %d", (tcbind & 0xf));
1681 command_print(CMD, " | Current TC: %d", ((tcbind >> 21) & 0xff));
1682
1683 /* Read mvpconf0 register */
1684 retval = mips32_cp0_read(ejtag_info, &mvpconf0, 0, 2);
1685 if (retval != ERROR_OK)
1686 return retval;
1687
1688 command_print(CMD, " | Total TC: %d", (mvpconf0 & 0xf) + 1);
1689 command_print(CMD, " | Total VPE: %d", ((mvpconf0 >> 10) & 0xf) + 1);
1690 } else {
1691 command_print(CMD, "MT implemented: no");
1692 }
1693
1694 /* MIPS SIMD Architecture (MSA) */
1695 uint32_t msa = (config3 & BIT(28));
1696 command_print(CMD, "MSA implemented: %s", msa ? "yes" : "no");
1697
1698 /* Move To/From High COP0 (MTHC0/MFHC0) instructions are implemented.
1699 * Implicates current ISA release >= 5.*/
1700 uint32_t mvh = (config5 & BIT(5));
1701 command_print(CMD, "MVH implemented: %s", mvh ? "yes" : "no");
1702
1703 /* Common Device Memory Map implemented? */
1704 uint32_t cdmm = (config3 & BIT(3));
1705 command_print(CMD, "CDMM implemented: %s", cdmm ? "yes" : "no");
1706
1707 return ERROR_OK;
1708 }
1709
1710 COMMAND_HANDLER(mips32_handle_scan_delay_command)
1711 {
1712 struct target *target = get_current_target(CMD_CTX);
1713 struct mips32_common *mips32 = target_to_mips32(target);
1714 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
1715
1716 if (CMD_ARGC == 1)
1717 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
1718 else if (CMD_ARGC > 1)
1719 return ERROR_COMMAND_SYNTAX_ERROR;
1720
1721 command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay);
1722 if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {
1723 ejtag_info->mode = 0;
1724 command_print(CMD, "running in legacy mode");
1725 } else {
1726 ejtag_info->mode = 1;
1727 command_print(CMD, "running in fast queued mode");
1728 }
1729
1730 return ERROR_OK;
1731 }
1732
1733 static const struct command_registration mips32_exec_command_handlers[] = {
1734 {
1735 .name = "cp0",
1736 .handler = mips32_handle_cp0_command,
1737 .mode = COMMAND_EXEC,
1738 .usage = "[[reg_name|regnum select] [value]]",
1739 .help = "display/modify cp0 register",
1740 },
1741 {
1742 .name = "cpuinfo",
1743 .handler = mips32_handle_cpuinfo_command,
1744 .mode = COMMAND_EXEC,
1745 .help = "display CPU information",
1746 .usage = "",
1747 },
1748 {
1749 .name = "scan_delay",
1750 .handler = mips32_handle_scan_delay_command,
1751 .mode = COMMAND_ANY,
1752 .help = "display/set scan delay in nano seconds",
1753 .usage = "[value]",
1754 },
1755 COMMAND_REGISTRATION_DONE
1756 };
1757
1758 const struct command_registration mips32_command_handlers[] = {
1759 {
1760 .name = "mips32",
1761 .mode = COMMAND_ANY,
1762 .help = "mips32 command group",
1763 .usage = "",
1764 .chain = mips32_exec_command_handlers,
1765 },
1766 COMMAND_REGISTRATION_DONE
1767 };

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)