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 = &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 
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