mips32.c 12.1 KB
Newer Older
ntfreak's avatar
ntfreak committed
1
2
3
4
5
6
/***************************************************************************
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
 *   Copyright (C) 2008 by David T.L. Wong                                 *
 *                                                                         *
7
 *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
8
9
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
ntfreak's avatar
ntfreak committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "mips32.h"


char* mips32_core_reg_list[] =
{
ntfreak's avatar
ntfreak committed
34
35
36
37
	"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
	"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
	"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
ntfreak's avatar
ntfreak committed
38
39
40
	"status", "lo", "hi", "badvaddr", "cause", "pc"
};

41
mips32_core_reg_t mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] =
ntfreak's avatar
ntfreak committed
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
{
	{0, NULL, NULL},
	{1, NULL, NULL},
	{2, NULL, NULL},
	{3, NULL, NULL},
	{4, NULL, NULL},
	{5, NULL, NULL},
	{6, NULL, NULL},
	{7, NULL, NULL},
	{8, NULL, NULL},
	{9, NULL, NULL},
	{10, NULL, NULL},
	{11, NULL, NULL},
	{12, NULL, NULL},
	{13, NULL, NULL},
	{14, NULL, NULL},
	{15, NULL, NULL},
	{16, NULL, NULL},
	{17, NULL, NULL},
	{18, NULL, NULL},
	{19, NULL, NULL},
	{20, NULL, NULL},
	{21, NULL, NULL},
	{22, NULL, NULL},
	{23, NULL, NULL},
	{24, NULL, NULL},
	{25, NULL, NULL},
	{26, NULL, NULL},
	{27, NULL, NULL},
	{28, NULL, NULL},
	{29, NULL, NULL},
	{30, NULL, NULL},
	{31, NULL, NULL},
75

ntfreak's avatar
ntfreak committed
76
77
78
79
80
81
82
83
	{32, NULL, NULL},
	{33, NULL, NULL},
	{34, NULL, NULL},
	{35, NULL, NULL},
	{36, NULL, NULL},
	{37, NULL, NULL},
};

84
85
/* number of mips dummy fp regs fp0 - fp31 + fsr and fir
 * we also add 18 unknown registers to handle gdb requests */
ntfreak's avatar
ntfreak committed
86

87
#define MIPS32NUMFPREGS 34 + 18
ntfreak's avatar
ntfreak committed
88

89
uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
ntfreak's avatar
ntfreak committed
90

91
reg_t mips32_gdb_dummy_fp_reg =
ntfreak's avatar
ntfreak committed
92
{
93
	"GDB dummy floating-point register", mips32_gdb_dummy_fp_value, 0, 1, 32, NULL, 0, NULL, 0
ntfreak's avatar
ntfreak committed
94
95
96
97
98
99
100
101
102
103
};

int mips32_core_reg_arch_type = -1;

int mips32_get_core_reg(reg_t *reg)
{
	int retval;
	mips32_core_reg_t *mips32_reg = reg->arch_info;
	target_t *target = mips32_reg->target;
	mips32_common_t *mips32_target = target->arch_info;
104

ntfreak's avatar
ntfreak committed
105
106
107
108
109
110
	if (target->state != TARGET_HALTED)
	{
		return ERROR_TARGET_NOT_HALTED;
	}

	retval = mips32_target->read_core_reg(target, mips32_reg->num);
111

ntfreak's avatar
ntfreak committed
112
113
114
	return retval;
}

115
int mips32_set_core_reg(reg_t *reg, uint8_t *buf)
ntfreak's avatar
ntfreak committed
116
117
118
{
	mips32_core_reg_t *mips32_reg = reg->arch_info;
	target_t *target = mips32_reg->target;
119
	uint32_t value = buf_get_u32(buf, 0, 32);
120

ntfreak's avatar
ntfreak committed
121
122
123
124
	if (target->state != TARGET_HALTED)
	{
		return ERROR_TARGET_NOT_HALTED;
	}
125

ntfreak's avatar
ntfreak committed
126
127
128
129
130
131
132
133
134
	buf_set_u32(reg->value, 0, 32, value);
	reg->dirty = 1;
	reg->valid = 1;

	return ERROR_OK;
}

int mips32_read_core_reg(struct target_s *target, int num)
{
135
	uint32_t reg_value;
ntfreak's avatar
ntfreak committed
136
	mips32_core_reg_t *mips_core_reg;
137

ntfreak's avatar
ntfreak committed
138
139
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
140

ntfreak's avatar
ntfreak committed
141
142
143
144
145
146
147
148
	if ((num < 0) || (num >= MIPS32NUMCOREREGS))
		return ERROR_INVALID_ARGUMENTS;

	mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
	reg_value = mips32->core_regs[num];
	buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
	mips32->core_cache->reg_list[num].valid = 1;
	mips32->core_cache->reg_list[num].dirty = 0;
149
150

	return ERROR_OK;
ntfreak's avatar
ntfreak committed
151
152
153
154
}

int mips32_write_core_reg(struct target_s *target, int num)
{
155
	uint32_t reg_value;
ntfreak's avatar
ntfreak committed
156
	mips32_core_reg_t *mips_core_reg;
157

ntfreak's avatar
ntfreak committed
158
159
160
161
162
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;

	if ((num < 0) || (num >= MIPS32NUMCOREREGS))
		return ERROR_INVALID_ARGUMENTS;
163

ntfreak's avatar
ntfreak committed
164
165
166
	reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
	mips_core_reg = mips32->core_cache->reg_list[num].arch_info;
	mips32->core_regs[num] = reg_value;
duane's avatar
duane committed
167
	LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
ntfreak's avatar
ntfreak committed
168
169
	mips32->core_cache->reg_list[num].valid = 1;
	mips32->core_cache->reg_list[num].dirty = 0;
170

ntfreak's avatar
ntfreak committed
171
172
173
174
175
176
177
178
	return ERROR_OK;
}

int mips32_invalidate_core_regs(target_t *target)
{
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
	int i;
179

ntfreak's avatar
ntfreak committed
180
181
182
183
184
	for (i = 0; i < mips32->core_cache->num_regs; i++)
	{
		mips32->core_cache->reg_list[i].valid = 0;
		mips32->core_cache->reg_list[i].dirty = 0;
	}
185

ntfreak's avatar
ntfreak committed
186
187
188
189
190
191
192
193
	return ERROR_OK;
}

int mips32_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
{
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
	int i;
194

195
196
	/* include floating point registers */
	*reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
ntfreak's avatar
ntfreak committed
197
	*reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
198

ntfreak's avatar
ntfreak committed
199
200
201
202
	for (i = 0; i < MIPS32NUMCOREREGS; i++)
	{
		(*reg_list)[i] = &mips32->core_cache->reg_list[i];
	}
203

ntfreak's avatar
ntfreak committed
204
	/* add dummy floating points regs */
205
206
207
208
209
	for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
	{
		(*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
	}

ntfreak's avatar
ntfreak committed
210
211
212
213
214
215
	return ERROR_OK;
}

int mips32_save_context(target_t *target)
{
	int i;
216

ntfreak's avatar
ntfreak committed
217
218
219
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
	mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
220

ntfreak's avatar
ntfreak committed
221
222
	/* read core registers */
	mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
223

ntfreak's avatar
ntfreak committed
224
225
226
227
228
229
230
	for (i = 0; i < MIPS32NUMCOREREGS; i++)
	{
		if (!mips32->core_cache->reg_list[i].valid)
		{
			mips32->read_core_reg(target, i);
		}
	}
231
232

	return ERROR_OK;
ntfreak's avatar
ntfreak committed
233
234
235
236
237
}

int mips32_restore_context(target_t *target)
{
	int i;
238

ntfreak's avatar
ntfreak committed
239
240
241
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
	mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
242

ntfreak's avatar
ntfreak committed
243
244
245
246
247
248
249
	for (i = 0; i < MIPS32NUMCOREREGS; i++)
	{
		if (mips32->core_cache->reg_list[i].dirty)
		{
			mips32->write_core_reg(target, i);
		}
	}
250

ntfreak's avatar
ntfreak committed
251
252
	/* write core regs */
	mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
253
254

	return ERROR_OK;
ntfreak's avatar
ntfreak committed
255
256
257
258
259
}

int mips32_arch_state(struct target_s *target)
{
	mips32_common_t *mips32 = target->arch_info;
260

ntfreak's avatar
ntfreak committed
261
262
263
264
265
	if (mips32->common_magic != MIPS32_COMMON_MAGIC)
	{
		LOG_ERROR("BUG: called for a non-MIPS32 target");
		exit(-1);
	}
266

duane's avatar
duane committed
267
	LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
268
		Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
ntfreak's avatar
ntfreak committed
269
		buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
270

ntfreak's avatar
ntfreak committed
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	return ERROR_OK;
}

reg_cache_t *mips32_build_reg_cache(target_t *target)
{
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;

	int num_regs = MIPS32NUMCOREREGS;
	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
	reg_cache_t *cache = malloc(sizeof(reg_cache_t));
	reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
	mips32_core_reg_t *arch_info = malloc(sizeof(mips32_core_reg_t) * num_regs);
	int i;
285

ntfreak's avatar
ntfreak committed
286
287
	if (mips32_core_reg_arch_type == -1)
		mips32_core_reg_arch_type = register_reg_arch_type(mips32_get_core_reg, mips32_set_core_reg);
288

289
	register_init_dummy(&mips32_gdb_dummy_fp_reg);
290

291
	/* Build the process context cache */
ntfreak's avatar
ntfreak committed
292
293
294
295
296
297
	cache->name = "mips32 registers";
	cache->next = NULL;
	cache->reg_list = reg_list;
	cache->num_regs = num_regs;
	(*cache_p) = cache;
	mips32->core_cache = cache;
298

ntfreak's avatar
ntfreak committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
	for (i = 0; i < num_regs; i++)
	{
		arch_info[i] = mips32_core_reg_list_arch_info[i];
		arch_info[i].target = target;
		arch_info[i].mips32_common = mips32;
		reg_list[i].name = mips32_core_reg_list[i];
		reg_list[i].size = 32;
		reg_list[i].value = calloc(1, 4);
		reg_list[i].dirty = 0;
		reg_list[i].valid = 0;
		reg_list[i].bitfield_desc = NULL;
		reg_list[i].num_bitfields = 0;
		reg_list[i].arch_type = mips32_core_reg_arch_type;
		reg_list[i].arch_info = &arch_info[i];
	}
314

ntfreak's avatar
ntfreak committed
315
316
317
	return cache;
}

318
int mips32_init_arch_info(target_t *target, mips32_common_t *mips32, struct jtag_tap *tap)
ntfreak's avatar
ntfreak committed
319
320
321
{
	target->arch_info = mips32;
	mips32->common_magic = MIPS32_COMMON_MAGIC;
322

323
324
325
	/* has breakpoint/watchpint unit been scanned */
	mips32->bp_scanned = 0;
	mips32->data_break_list = NULL;
326

327
	mips32->ejtag_info.tap = tap;
ntfreak's avatar
ntfreak committed
328
329
	mips32->read_core_reg = mips32_read_core_reg;
	mips32->write_core_reg = mips32_write_core_reg;
330

ntfreak's avatar
ntfreak committed
331
332
333
334
335
336
337
338
	return ERROR_OK;
}

int mips32_register_commands(struct command_context_s *cmd_ctx)
{
	return ERROR_OK;
}

339
int mips32_run_algorithm(struct target_s *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
ntfreak's avatar
ntfreak committed
340
341
342
343
{
	/*TODO*/
	return ERROR_OK;
}
344
345
346
347

int mips32_examine(struct target_s *target)
{
	mips32_common_t *mips32 = target->arch_info;
348

ntfreak's avatar
ntfreak committed
349
	if (!target_was_examined(target))
350
	{
351
		target_set_examined(target);
352

353
354
355
356
357
358
359
		/* we will configure later */
		mips32->bp_scanned = 0;
		mips32->num_inst_bpoints = 0;
		mips32->num_data_bpoints = 0;
		mips32->num_inst_bpoints_avail = 0;
		mips32->num_data_bpoints_avail = 0;
	}
360

361
362
363
364
365
366
367
368
	return ERROR_OK;
}

int mips32_configure_break_unit(struct target_s *target)
{
	/* get pointers to arch-specific information */
	mips32_common_t *mips32 = target->arch_info;
	int retval;
369
	uint32_t dcr, bpinfo;
370
	int i;
371

372
373
	if (mips32->bp_scanned)
		return ERROR_OK;
374

375
376
377
	/* get info about breakpoint support */
	if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
		return retval;
378

379
380
381
382
383
	if (dcr & (1 << 16))
	{
		/* get number of inst breakpoints */
		if ((retval = target_read_u32(target, EJTAG_IBS, &bpinfo)) != ERROR_OK)
			return retval;
384

385
386
387
388
389
390
391
		mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
		mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
		mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(mips32_comparator_t));
		for (i = 0; i < mips32->num_inst_bpoints; i++)
		{
			mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
		}
392

393
394
395
396
		/* clear IBIS reg */
		if ((retval = target_write_u32(target, EJTAG_IBS, 0)) != ERROR_OK)
			return retval;
	}
397

398
399
400
401
402
	if (dcr & (1 << 17))
	{
		/* get number of data breakpoints */
		if ((retval = target_read_u32(target, EJTAG_DBS, &bpinfo)) != ERROR_OK)
			return retval;
403

404
405
406
407
408
409
410
		mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
		mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
		mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(mips32_comparator_t));
		for (i = 0; i < mips32->num_data_bpoints; i++)
		{
			mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
		}
411

412
413
414
415
		/* clear DBIS reg */
		if ((retval = target_write_u32(target, EJTAG_DBS, 0)) != ERROR_OK)
			return retval;
	}
416

duane's avatar
duane committed
417
	LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints, mips32->num_data_bpoints);
418

419
	mips32->bp_scanned = 1;
420

421
422
	return ERROR_OK;
}
423
424
425
426
427

int mips32_enable_interrupts(struct target_s *target, int enable)
{
	int retval;
	int update = 0;
428
	uint32_t dcr;
429

430
431
432
	/* read debug control register */
	if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
		return retval;
433

434
435
	if (enable)
	{
zwelch's avatar
zwelch committed
436
		if (!(dcr & (1 << 4)))
437
438
		{
			/* enable interrupts */
zwelch's avatar
zwelch committed
439
			dcr |= (1 << 4);
440
441
442
443
444
			update = 1;
		}
	}
	else
	{
zwelch's avatar
zwelch committed
445
		if (dcr & (1 << 4))
446
447
		{
			/* disable interrupts */
zwelch's avatar
zwelch committed
448
			dcr &= ~(1 << 4);
449
450
451
			update = 1;
		}
	}
452

453
454
455
456
457
	if (update)
	{
		if ((retval = target_write_u32(target, EJTAG_DCR, dcr)) != ERROR_OK)
			return retval;
	}
458

459
460
	return ERROR_OK;
}