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

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)