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 #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
reg_type2size(enum reg_type type)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
mips64_get_core_reg(struct reg * reg)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
mips64_set_core_reg(struct reg * reg,uint8_t * buf)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
mips64_read_core_reg(struct target * target,int num)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
mips64_write_core_reg(struct target * target,int num)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
mips64_invalidate_core_regs(struct target * target)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
mips64_get_gdb_reg_list(struct target * target,struct reg ** reg_list[],int * reg_list_size,enum target_register_class reg_class)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
mips64_save_context(struct target * target)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
mips64_restore_context(struct target * target)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
mips64_arch_state(struct target * target)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
mips64_build_reg_cache(struct target * target)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 = ®_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
mips64_init_arch_info(struct target * target,struct mips64_common * mips64,struct jtag_tap * tap)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
mips64_run_algorithm(struct target * target,int num_mem_params,struct mem_param * mem_params,int num_reg_params,struct reg_param * reg_params,target_addr_t entry_point,target_addr_t exit_point,int timeout_ms,void * arch_info)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
mips64_examine(struct target * target)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
mips64_configure_i_break_unit(struct target * target)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
mips64_configure_d_break_unit(struct target * target)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
mips64_configure_break_unit(struct target * target)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
mips64_enable_interrupts(struct target * target,bool enable)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 }
624