mips: Add MIPS64 support
[openocd.git] / src / target / mips64.c
1 /*
2 * Support for processors implementing MIPS64 instruction set
3 *
4 * Copyright (C) 2014 by Andrey Sidorov <anysidorov@gmail.com>
5 * Copyright (C) 2014 by Aleksey Kuleshov <rndfax@yandex.ru>
6 * Copyright (C) 2014 by Antony Pavlov <antonynpavlov@gmail.com>
7 * Copyright (C) 2014 by Peter Mamonov <pmamonov@gmail.com>
8 *
9 * Based on the work of:
10 * Copyright (C) 2008 by Spencer Oliver
11 * Copyright (C) 2008 by David T.L. Wong
12 * Copyright (C) 2010 by Konstantin Kostyukhin, Nikolay Shmyrev
13 *
14 * SPDX-License-Identifier: GPL-2.0-or-later
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #if BUILD_TARGET64 == 1
22
23 #include "mips64.h"
24
25 static const struct {
26 unsigned id;
27 const char *name;
28 enum reg_type type;
29 const char *group;
30 const char *feature;
31 int flag;
32 } mips64_regs[] = {
33 { 0, "r0", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
34 { 1, "r1", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
35 { 2, "r2", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
36 { 3, "r3", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
37 { 4, "r4", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
38 { 5, "r5", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
39 { 6, "r6", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
40 { 7, "r7", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
41 { 8, "r8", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
42 { 9, "r9", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
43 { 10, "r10", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
44 { 11, "r11", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
45 { 12, "r12", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
46 { 13, "r13", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
47 { 14, "r14", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
48 { 15, "r15", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
49 { 16, "r16", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
50 { 17, "r17", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
51 { 18, "r18", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
52 { 19, "r19", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
53 { 20, "r20", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
54 { 21, "r21", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
55 { 22, "r22", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
56 { 23, "r23", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
57 { 24, "r24", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
58 { 25, "r25", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
59 { 26, "r26", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
60 { 27, "r27", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
61 { 28, "r28", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
62 { 29, "r29", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
63 { 30, "r30", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
64 { 31, "r31", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
65 { 32, "lo", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
66 { 33, "hi", REG_TYPE_UINT64, NULL, "org.gnu.gdb.mips.cpu", 0 },
67 { MIPS64_NUM_CORE_REGS + 0, "pc", REG_TYPE_UINT64, NULL,
68 "org.gnu.gdb.mips.cpu", 0 },
69 { MIPS64_NUM_CORE_REGS + 1, "Random", REG_TYPE_UINT32, NULL,
70 "org.gnu.gdb.mips.cp0", 0 },
71 { MIPS64_NUM_CORE_REGS + 2, "Entrylo_0", REG_TYPE_UINT64, NULL,
72 "org.gnu.gdb.mips.cp0", 0 },
73 { MIPS64_NUM_CORE_REGS + 3, "Entrylo_1", REG_TYPE_UINT64, NULL,
74 "org.gnu.gdb.mips.cp0", 0 },
75 { MIPS64_NUM_CORE_REGS + 4, "Context", REG_TYPE_UINT64, NULL,
76 "org.gnu.gdb.mips.cp0", 0 },
77 { MIPS64_NUM_CORE_REGS + 5, "Pagemask", REG_TYPE_UINT32, NULL,
78 "org.gnu.gdb.mips.cp0", 0 },
79 { MIPS64_NUM_CORE_REGS + 6, "Wired", REG_TYPE_UINT32, NULL,
80 "org.gnu.gdb.mips.cp0", 0 },
81 { MIPS64_NUM_CORE_REGS + 7, "badvaddr", REG_TYPE_UINT64, NULL,
82 "org.gnu.gdb.mips.cp0", 0 },
83 { MIPS64_NUM_CORE_REGS + 8, "Count", REG_TYPE_UINT32, NULL,
84 "org.gnu.gdb.mips.cp0", 0 },
85 { MIPS64_NUM_CORE_REGS + 9, "EntryHi", REG_TYPE_UINT64, NULL,
86 "org.gnu.gdb.mips.cp0", 0 },
87 { MIPS64_NUM_CORE_REGS + 10, "Compare", REG_TYPE_UINT32, NULL,
88 "org.gnu.gdb.mips.cp0", 0 },
89 { MIPS64_NUM_CORE_REGS + 11, "status", REG_TYPE_UINT32, NULL,
90 "org.gnu.gdb.mips.cp0", 0 },
91 { MIPS64_NUM_CORE_REGS + 12, "cause", REG_TYPE_UINT32, NULL,
92 "org.gnu.gdb.mips.cp0", 0 },
93 { MIPS64_NUM_CORE_REGS + 13, "EPC", REG_TYPE_UINT64, NULL,
94 "org.gnu.gdb.mips.cp0", 0 },
95 { MIPS64_NUM_CORE_REGS + 14, "PrID", REG_TYPE_UINT32, NULL,
96 "org.gnu.gdb.mips.cp0", 0 },
97 { MIPS64_NUM_CORE_REGS + 15, "Config", REG_TYPE_UINT32, NULL,
98 "org.gnu.gdb.mips.cp0", 0 },
99 { MIPS64_NUM_CORE_REGS + 16, "LLA", REG_TYPE_UINT32, NULL,
100 "org.gnu.gdb.mips.cp0", 0 },
101 { MIPS64_NUM_CORE_REGS + 17, "WatchLo0", REG_TYPE_UINT64, NULL,
102 "org.gnu.gdb.mips.cp0", 0 },
103 { MIPS64_NUM_CORE_REGS + 18, "WatchLo1", REG_TYPE_UINT64, NULL,
104 "org.gnu.gdb.mips.cp0", 0 },
105 { MIPS64_NUM_CORE_REGS + 19, "WatchHi0", REG_TYPE_UINT32, NULL,
106 "org.gnu.gdb.mips.cp0", 0 },
107 { MIPS64_NUM_CORE_REGS + 20, "WatchHi1", REG_TYPE_UINT32, NULL,
108 "org.gnu.gdb.mips.cp0", 0 },
109 { MIPS64_NUM_CORE_REGS + 21, "Xcontext", REG_TYPE_UINT64, NULL,
110 "org.gnu.gdb.mips.cp0", 0 },
111 { MIPS64_NUM_CORE_REGS + 22, "ChipMemCtrl", REG_TYPE_UINT32, NULL,
112 "org.gnu.gdb.mips.cp0", 0 },
113 { MIPS64_NUM_CORE_REGS + 23, "Debug", REG_TYPE_UINT32, NULL,
114 "org.gnu.gdb.mips.cp0", 0 },
115 { MIPS64_NUM_CORE_REGS + 24, "Perfcount, sel=0", REG_TYPE_UINT32, NULL,
116 "org.gnu.gdb.mips.cp0", 0 },
117 { MIPS64_NUM_CORE_REGS + 25, "Perfcount, sel=1", REG_TYPE_UINT64, NULL,
118 "org.gnu.gdb.mips.cp0", 0 },
119 { MIPS64_NUM_CORE_REGS + 26, "Perfcount, sel=2", REG_TYPE_UINT32, NULL,
120 "org.gnu.gdb.mips.cp0", 0 },
121 { MIPS64_NUM_CORE_REGS + 27, "Perfcount, sel=3", REG_TYPE_UINT64, NULL,
122 "org.gnu.gdb.mips.cp0", 0 },
123 { MIPS64_NUM_CORE_REGS + 28, "ECC", REG_TYPE_UINT32, NULL,
124 "org.gnu.gdb.mips.cp0", 0 },
125 { MIPS64_NUM_CORE_REGS + 29, "CacheErr", REG_TYPE_UINT32, NULL,
126 "org.gnu.gdb.mips.cp0", 0 },
127 { MIPS64_NUM_CORE_REGS + 30, "TagLo", REG_TYPE_UINT32, NULL,
128 "org.gnu.gdb.mips.cp0", 0 },
129 { MIPS64_NUM_CORE_REGS + 31, "TagHi", REG_TYPE_UINT32, NULL,
130 "org.gnu.gdb.mips.cp0", 0 },
131 { MIPS64_NUM_CORE_REGS + 32, "DataHi", REG_TYPE_UINT64, NULL,
132 "org.gnu.gdb.mips.cp0", 0 },
133 { MIPS64_NUM_CORE_REGS + 33, "EEPC", REG_TYPE_UINT64, NULL,
134 "org.gnu.gdb.mips.cp0", 0 },
135 { MIPS64_NUM_CORE_C0_REGS + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
136 "org.gnu.gdb.mips.fpu", 0 },
137 { MIPS64_NUM_CORE_C0_REGS + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
138 "org.gnu.gdb.mips.fpu", 0 },
139 { MIPS64_NUM_CORE_C0_REGS + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
140 "org.gnu.gdb.mips.fpu", 0 },
141 { MIPS64_NUM_CORE_C0_REGS + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
142 "org.gnu.gdb.mips.fpu", 0 },
143 { MIPS64_NUM_CORE_C0_REGS + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
144 "org.gnu.gdb.mips.fpu", 0 },
145 { MIPS64_NUM_CORE_C0_REGS + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
146 "org.gnu.gdb.mips.fpu", 0 },
147 { MIPS64_NUM_CORE_C0_REGS + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
148 "org.gnu.gdb.mips.fpu", 0 },
149 { MIPS64_NUM_CORE_C0_REGS + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
150 "org.gnu.gdb.mips.fpu", 0 },
151 { MIPS64_NUM_CORE_C0_REGS + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
152 "org.gnu.gdb.mips.fpu", 0 },
153 { MIPS64_NUM_CORE_C0_REGS + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
154 "org.gnu.gdb.mips.fpu", 0 },
155 { MIPS64_NUM_CORE_C0_REGS + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
156 "org.gnu.gdb.mips.fpu", 0 },
157 { MIPS64_NUM_CORE_C0_REGS + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
158 "org.gnu.gdb.mips.fpu", 0 },
159 { MIPS64_NUM_CORE_C0_REGS + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
160 "org.gnu.gdb.mips.fpu", 0 },
161 { MIPS64_NUM_CORE_C0_REGS + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
162 "org.gnu.gdb.mips.fpu", 0 },
163 { MIPS64_NUM_CORE_C0_REGS + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
164 "org.gnu.gdb.mips.fpu", 0 },
165 { MIPS64_NUM_CORE_C0_REGS + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
166 "org.gnu.gdb.mips.fpu", 0 },
167 { MIPS64_NUM_CORE_C0_REGS + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
168 "org.gnu.gdb.mips.fpu", 0 },
169 { MIPS64_NUM_CORE_C0_REGS + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
170 "org.gnu.gdb.mips.fpu", 0 },
171 { MIPS64_NUM_CORE_C0_REGS + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
172 "org.gnu.gdb.mips.fpu", 0 },
173 { MIPS64_NUM_CORE_C0_REGS + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
174 "org.gnu.gdb.mips.fpu", 0 },
175 { MIPS64_NUM_CORE_C0_REGS + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
176 "org.gnu.gdb.mips.fpu", 0 },
177 { MIPS64_NUM_CORE_C0_REGS + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
178 "org.gnu.gdb.mips.fpu", 0 },
179 { MIPS64_NUM_CORE_C0_REGS + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
180 "org.gnu.gdb.mips.fpu", 0 },
181 { MIPS64_NUM_CORE_C0_REGS + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
182 "org.gnu.gdb.mips.fpu", 0 },
183 { MIPS64_NUM_CORE_C0_REGS + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
184 "org.gnu.gdb.mips.fpu", 0 },
185 { MIPS64_NUM_CORE_C0_REGS + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
186 "org.gnu.gdb.mips.fpu", 0 },
187 { MIPS64_NUM_CORE_C0_REGS + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
188 "org.gnu.gdb.mips.fpu", 0 },
189 { MIPS64_NUM_CORE_C0_REGS + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
190 "org.gnu.gdb.mips.fpu", 0 },
191 { MIPS64_NUM_CORE_C0_REGS + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
192 "org.gnu.gdb.mips.fpu", 0 },
193 { MIPS64_NUM_CORE_C0_REGS + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
194 "org.gnu.gdb.mips.fpu", 0 },
195 { MIPS64_NUM_CORE_C0_REGS + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
196 "org.gnu.gdb.mips.fpu", 0 },
197 { MIPS64_NUM_CORE_C0_REGS + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
198 "org.gnu.gdb.mips.fpu", 0 },
199 { MIPS64_NUM_CORE_C0_REGS + 32, "fcsr", REG_TYPE_INT, "float",
200 "org.gnu.gdb.mips.fpu", 0 },
201 { MIPS64_NUM_CORE_C0_REGS + 33, "fir", REG_TYPE_INT, "float",
202 "org.gnu.gdb.mips.fpu", 0 },
203 { MIPS64_NUM_CORE_C0_REGS + 34, "fconfig", REG_TYPE_INT, "float",
204 "org.gnu.gdb.mips.fpu", 0 },
205 { MIPS64_NUM_CORE_C0_REGS + 35, "fccr", REG_TYPE_INT, "float",
206 "org.gnu.gdb.mips.fpu", 0 },
207 { MIPS64_NUM_CORE_C0_REGS + 36, "fexr", REG_TYPE_INT, "float",
208 "org.gnu.gdb.mips.fpu", 0 },
209 { MIPS64_NUM_CORE_C0_REGS + 37, "fenr", REG_TYPE_INT, "float",
210 "org.gnu.gdb.mips.fpu", 0 },
211 };
212
213 static int reg_type2size(enum reg_type type)
214 {
215 switch (type) {
216 case REG_TYPE_UINT32:
217 case REG_TYPE_INT:
218 return 32;
219 case REG_TYPE_UINT64:
220 case REG_TYPE_IEEE_DOUBLE:
221 return 64;
222 default:
223 return 64;
224 }
225 }
226
227 static int mips64_get_core_reg(struct reg *reg)
228 {
229 int retval;
230 struct mips64_core_reg *mips64_reg = reg->arch_info;
231 struct target *target = mips64_reg->target;
232 struct mips64_common *mips64_target = target->arch_info;
233
234 if (target->state != TARGET_HALTED)
235 return ERROR_TARGET_NOT_HALTED;
236
237 retval = mips64_target->read_core_reg(target, mips64_reg->num);
238
239 return retval;
240 }
241
242 static int mips64_set_core_reg(struct reg *reg, uint8_t *buf)
243 {
244 struct mips64_core_reg *mips64_reg = reg->arch_info;
245 struct target *target = mips64_reg->target;
246 uint64_t value = buf_get_u64(buf, 0, 64);
247
248 if (target->state != TARGET_HALTED)
249 return ERROR_TARGET_NOT_HALTED;
250
251 buf_set_u64(reg->value, 0, 64, value);
252 reg->dirty = 1;
253 reg->valid = 1;
254
255 return ERROR_OK;
256 }
257
258 static int mips64_read_core_reg(struct target *target, int num)
259 {
260 uint64_t reg_value;
261
262 /* get pointers to arch-specific information */
263 struct mips64_common *mips64 = target->arch_info;
264
265 if ((num < 0) || (num >= MIPS64_NUM_REGS))
266 return ERROR_COMMAND_ARGUMENT_INVALID;
267
268 reg_value = mips64->core_regs[num];
269 buf_set_u64(mips64->core_cache->reg_list[num].value, 0, 64, reg_value);
270 mips64->core_cache->reg_list[num].valid = 1;
271 mips64->core_cache->reg_list[num].dirty = 0;
272
273 return ERROR_OK;
274 }
275
276 static int mips64_write_core_reg(struct target *target, int num)
277 {
278 uint64_t reg_value;
279
280 /* get pointers to arch-specific information */
281 struct mips64_common *mips64 = target->arch_info;
282
283 if ((num < 0) || (num >= MIPS64_NUM_REGS))
284 return ERROR_COMMAND_ARGUMENT_INVALID;
285
286 reg_value = buf_get_u64(mips64->core_cache->reg_list[num].value, 0, 64);
287 mips64->core_regs[num] = reg_value;
288 LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num , reg_value);
289 mips64->core_cache->reg_list[num].valid = 1;
290 mips64->core_cache->reg_list[num].dirty = 0;
291
292 return ERROR_OK;
293 }
294
295 int mips64_invalidate_core_regs(struct target *target)
296 {
297 /* get pointers to arch-specific information */
298 struct mips64_common *mips64 = target->arch_info;
299 unsigned int i;
300
301 for (i = 0; i < mips64->core_cache->num_regs; i++) {
302 mips64->core_cache->reg_list[i].valid = 0;
303 mips64->core_cache->reg_list[i].dirty = 0;
304 }
305
306 return ERROR_OK;
307 }
308
309
310 int mips64_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
311 int *reg_list_size, enum target_register_class reg_class)
312 {
313 /* get pointers to arch-specific information */
314 struct mips64_common *mips64 = target->arch_info;
315 register int i;
316
317 /* include floating point registers */
318 *reg_list_size = MIPS64_NUM_REGS;
319 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
320
321 for (i = 0; i < MIPS64_NUM_REGS; i++)
322 (*reg_list)[i] = &mips64->core_cache->reg_list[i];
323
324 return ERROR_OK;
325 }
326
327 int mips64_save_context(struct target *target)
328 {
329 int retval;
330 struct mips64_common *mips64 = target->arch_info;
331 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
332
333 retval = mips64_pracc_read_regs(ejtag_info, mips64->core_regs);
334 if (retval != ERROR_OK)
335 return retval;
336
337 for (unsigned i = 0; i < MIPS64_NUM_REGS; i++)
338 retval = mips64->read_core_reg(target, i);
339
340 return retval;
341 }
342
343 int mips64_restore_context(struct target *target)
344 {
345 struct mips64_common *mips64 = target->arch_info;
346 struct mips_ejtag *ejtag_info = &mips64->ejtag_info;
347
348 for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) {
349 if (mips64->core_cache->reg_list[i].dirty)
350 mips64->write_core_reg(target, i);
351 }
352
353 return mips64_pracc_write_regs(ejtag_info, mips64->core_regs);
354 }
355
356 int mips64_arch_state(struct target *target)
357 {
358 struct mips64_common *mips64 = target->arch_info;
359 struct reg *pc = &mips64->core_cache->reg_list[MIPS64_PC];
360
361 if (mips64->common_magic != MIPS64_COMMON_MAGIC) {
362 LOG_ERROR("BUG: called for a non-MIPS64 target");
363 exit(-1);
364 }
365
366 LOG_USER("target halted due to %s, pc: 0x%" PRIx64 "",
367 debug_reason_name(target), buf_get_u64(pc->value, 0, 64));
368
369 return ERROR_OK;
370 }
371
372 static const struct reg_arch_type mips64_reg_type = {
373 .get = mips64_get_core_reg,
374 .set = mips64_set_core_reg,
375 };
376
377 int mips64_build_reg_cache(struct target *target)
378 {
379 /* get pointers to arch-specific information */
380 struct mips64_common *mips64 = target->arch_info;
381 struct reg_cache **cache_p, *cache;
382 struct mips64_core_reg *arch_info = NULL;
383 struct reg *reg_list = NULL;
384 unsigned i;
385
386 cache = calloc(1, sizeof(*cache));
387 if (!cache) {
388 LOG_ERROR("unable to allocate cache");
389 return ERROR_FAIL;
390 }
391
392 reg_list = calloc(MIPS64_NUM_REGS, sizeof(*reg_list));
393 if (!reg_list) {
394 LOG_ERROR("unable to allocate reg_list");
395 goto alloc_fail;
396 }
397
398 arch_info = calloc(MIPS64_NUM_REGS, sizeof(*arch_info));
399 if (!arch_info) {
400 LOG_ERROR("unable to allocate arch_info");
401 goto alloc_fail;
402 }
403
404 for (i = 0; i < MIPS64_NUM_REGS; i++) {
405 struct mips64_core_reg *a = &arch_info[i];
406 struct reg *r = &reg_list[i];
407
408 r->arch_info = &arch_info[i];
409 r->caller_save = true; /* gdb defaults to true */
410 r->exist = true;
411 r->feature = &a->feature;
412 r->feature->name = mips64_regs[i].feature;
413 r->group = mips64_regs[i].group;
414 r->name = mips64_regs[i].name;
415 r->number = i;
416 r->reg_data_type = &a->reg_data_type;
417 r->reg_data_type->type = mips64_regs[i].type;
418 r->size = reg_type2size(mips64_regs[i].type);
419 r->type = &mips64_reg_type;
420 r->value = &a->value[0];
421
422 a->mips64_common = mips64;
423 a->num = mips64_regs[i].id;
424 a->target = target;
425 }
426
427 cache->name = "mips64 registers";
428 cache->reg_list = reg_list;
429 cache->num_regs = MIPS64_NUM_REGS;
430
431 cache_p = register_get_last_cache_p(&target->reg_cache);
432 (*cache_p) = cache;
433
434 mips64->core_cache = cache;
435
436 return ERROR_OK;
437
438 alloc_fail:
439 free(cache);
440 free(reg_list);
441 free(arch_info);
442
443 return ERROR_FAIL;
444 }
445
446 int mips64_init_arch_info(struct target *target, struct mips64_common *mips64,
447 struct jtag_tap *tap)
448 {
449 mips64->bp_scanned = false;
450 mips64->common_magic = MIPS64_COMMON_MAGIC;
451 mips64->data_break_list = NULL;
452 mips64->ejtag_info.tap = tap;
453 mips64->fast_data_area = NULL;
454 mips64->mips64mode32 = false;
455 mips64->read_core_reg = mips64_read_core_reg;
456 mips64->write_core_reg = mips64_write_core_reg;
457
458 return ERROR_OK;
459 }
460
461 int mips64_run_algorithm(struct target *target, int num_mem_params,
462 struct mem_param *mem_params, int num_reg_params,
463 struct reg_param *reg_params, target_addr_t entry_point,
464 target_addr_t exit_point, int timeout_ms, void *arch_info)
465 {
466 /* TODO */
467 return ERROR_OK;
468 }
469
470 int mips64_examine(struct target *target)
471 {
472 struct mips64_common *mips64 = target->arch_info;
473
474 if (target_was_examined(target))
475 return ERROR_OK;
476
477 /* TODO: why we do not do mips64_configure_break_unit() here? */
478 mips64->bp_scanned = false;
479 mips64->num_data_bpoints = 0;
480 mips64->num_data_bpoints_avail = 0;
481 mips64->num_inst_bpoints = 0;
482 mips64->num_inst_bpoints_avail = 0;
483
484 target_set_examined(target);
485
486 return ERROR_OK;
487 }
488
489 static int mips64_configure_i_break_unit(struct target *target)
490 {
491 /* get pointers to arch-specific information */
492 struct mips64_common *mips64 = target->arch_info;
493 struct mips64_comparator *ibl;
494 uint64_t bpinfo;
495 int retval;
496 int i;
497
498 /* get number of inst breakpoints */
499 retval = target_read_u64(target, EJTAG64_V25_IBS, &bpinfo);
500 if (retval != ERROR_OK)
501 return retval;
502
503 mips64->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
504 mips64->num_inst_bpoints_avail = mips64->num_inst_bpoints;
505 ibl = calloc(mips64->num_inst_bpoints, sizeof(*ibl));
506 if (!ibl) {
507 LOG_ERROR("unable to allocate inst_break_list");
508 return ERROR_FAIL;
509 }
510
511 for (i = 0; i < mips64->num_inst_bpoints; i++)
512 ibl[i].reg_address = EJTAG64_V25_IBA0 + (0x100 * i);
513
514 mips64->inst_break_list = ibl;
515 /* clear IBIS reg */
516 retval = target_write_u64(target, EJTAG64_V25_IBS, 0);
517 if (retval != ERROR_OK)
518 return retval;
519
520 return ERROR_OK;
521 }
522
523 static int mips64_configure_d_break_unit(struct target *target)
524 {
525 struct mips64_common *mips64 = target->arch_info;
526 struct mips64_comparator *dbl;
527 uint64_t bpinfo;
528 int retval;
529 int i;
530
531 /* get number of data breakpoints */
532 retval = target_read_u64(target, EJTAG64_V25_DBS, &bpinfo);
533 if (retval != ERROR_OK)
534 return retval;
535
536 mips64->num_data_bpoints = (bpinfo >> 24) & 0x0F;
537 mips64->num_data_bpoints_avail = mips64->num_data_bpoints;
538
539 dbl = calloc(mips64->num_data_bpoints, sizeof(*dbl));
540
541 if (!dbl) {
542 LOG_ERROR("unable to allocate data_break_list");
543 return ERROR_FAIL;
544 }
545
546 for (i = 0; i < mips64->num_data_bpoints; i++)
547 dbl[i].reg_address = EJTAG64_V25_DBA0 + (0x100 * i);
548
549 mips64->data_break_list = dbl;
550
551 /* clear DBIS reg */
552 retval = target_write_u64(target, EJTAG64_V25_DBS, 0);
553 if (retval != ERROR_OK)
554 return retval;
555
556 return ERROR_OK;
557 }
558
559 int mips64_configure_break_unit(struct target *target)
560 {
561 struct mips64_common *mips64 = target->arch_info;
562 uint64_t dcr;
563 int retval;
564
565 if (mips64->bp_scanned)
566 return ERROR_OK;
567
568 /* get info about breakpoint support */
569 retval = target_read_u64(target, EJTAG64_DCR, &dcr);
570 if (retval != ERROR_OK)
571 return retval;
572
573 if (dcr & EJTAG64_DCR_IB) {
574 retval = mips64_configure_i_break_unit(target);
575 if (retval != ERROR_OK)
576 return retval;
577 }
578
579 if (dcr & EJTAG64_DCR_DB) {
580 retval = mips64_configure_d_break_unit(target);
581 if (retval != ERROR_OK)
582 return retval;
583 }
584
585 LOG_DEBUG("DCR 0x%" PRIx64 " numinst %i numdata %i", dcr,
586 mips64->num_inst_bpoints, mips64->num_data_bpoints);
587
588 mips64->bp_scanned = true;
589
590 return ERROR_OK;
591 }
592
593 int mips64_enable_interrupts(struct target *target, bool enable)
594 {
595 int retval;
596 bool update = false;
597 uint64_t dcr;
598
599 /* read debug control register */
600 retval = target_read_u64(target, EJTAG64_DCR, &dcr);
601 if (retval != ERROR_OK)
602 return retval;
603
604 if (enable) {
605 if (!(dcr & EJTAG64_DCR_INTE)) {
606 /* enable interrupts */
607 dcr |= EJTAG64_DCR_INTE;
608 update = true;
609 }
610 } else {
611 if (dcr & EJTAG64_DCR_INTE) {
612 /* disable interrupts */
613 dcr &= ~(uint64_t)EJTAG64_DCR_INTE;
614 update = true;
615 }
616 }
617
618 if (update) {
619 retval = target_write_u64(target, EJTAG64_DCR, dcr);
620 if (retval != ERROR_OK)
621 return retval;
622 }
623
624 return ERROR_OK;
625 }
626
627 #endif /* BUILD_TARGET64 */

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)