mips32_pracc.c 33.8 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
8
 *   Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com>          *
 *                                                                         *
ntfreak's avatar
ntfreak committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *   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.             *
 ***************************************************************************/
24
25
26
27
28
29
30

/*
This version has optimized assembly routines for 32 bit operations:
- read word
- write word
- write array of words

31
One thing to be aware of is that the MIPS32 cpu will execute the
32
33
34
35
36
37
38
39
instruction after a branch instruction (one delay slot).

For example:

    LW $2, ($5 +10)
    B foo
    LW $1, ($2 +100)

40
The LW $1, ($2 +100) instruction is also executed. If this is
41
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
not wanted a NOP can be inserted:

    LW $2, ($5 +10)
    B foo
    NOP
    LW $1, ($2 +100)

or the code can be changed to:

    B foo
    LW $2, ($5 +10)
    LW $1, ($2 +100)

The original code contained NOPs. I have removed these and moved
the branches.

I also moved the PRACC_STACK to 0xFF204000. This allows
the use of 16 bits offsets to get pointers to the input
and output area relative to the stack. Note that the stack
isn't really a stack (the stack pointer is not 'moving')
but a FIFO simulated in software.

These changes result in a 35% speed increase when programming an
external flash.

More improvement could be gained if the registers do no need
to be preserved but in that case the routines should be aware
OpenOCD is used as a flash programmer or as a debug tool.

Nico Coesel
*/

ntfreak's avatar
ntfreak committed
73
74
75
76
77
78
79
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "mips32.h"
#include "mips32_pracc.h"

Zachary T Welch's avatar
Zachary T Welch committed
80
81
struct mips32_pracc_context
{
82
	uint32_t *local_iparam;
ntfreak's avatar
ntfreak committed
83
	int num_iparam;
84
	uint32_t *local_oparam;
ntfreak's avatar
ntfreak committed
85
	int num_oparam;
86
	const uint32_t *code;
ntfreak's avatar
ntfreak committed
87
	int code_len;
88
	uint32_t stack[32];
ntfreak's avatar
ntfreak committed
89
	int stack_offset;
90
	struct mips_ejtag *ejtag_info;
Zachary T Welch's avatar
Zachary T Welch committed
91
};
ntfreak's avatar
ntfreak committed
92

93
static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
ntfreak's avatar
ntfreak committed
94
{
95
	uint32_t ejtag_ctrl;
96
97

	while (1)
ntfreak's avatar
ntfreak committed
98
99
	{
		mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
100
		ejtag_ctrl = ejtag_info->ejtag_ctrl;
ntfreak's avatar
ntfreak committed
101
102
103
104
105
106
		mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
		if (ejtag_ctrl & EJTAG_CTRL_PRACC)
			break;
		LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
		return ERROR_JTAG_DEVICE_ERROR;
	}
107

ntfreak's avatar
ntfreak committed
108
109
110
111
	*ctrl = ejtag_ctrl;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
112
static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
ntfreak's avatar
ntfreak committed
113
{
114
	struct mips_ejtag *ejtag_info = ctx->ejtag_info;
ntfreak's avatar
ntfreak committed
115
	int offset;
116
	uint32_t ejtag_ctrl, data;
ntfreak's avatar
ntfreak committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130

	if ((address >= MIPS32_PRACC_PARAM_IN)
		&& (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
	{
		offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
		data = ctx->local_iparam[offset];
	}
	else if ((address >= MIPS32_PRACC_PARAM_OUT)
		&& (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
	{
		offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
		data = ctx->local_oparam[offset];
	}
	else if ((address >= MIPS32_PRACC_TEXT)
Spencer Oliver's avatar
Spencer Oliver committed
131
		&& (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4))
ntfreak's avatar
ntfreak committed
132
133
134
135
136
137
138
139
140
141
142
143
144
	{
		offset = (address - MIPS32_PRACC_TEXT) / 4;
		data = ctx->code[offset];
	}
	else if (address == MIPS32_PRACC_STACK)
	{
		/* save to our debug stack */
		data = ctx->stack[--ctx->stack_offset];
	}
	else
	{
		/* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
		 * to start of debug vector */
145

ntfreak's avatar
ntfreak committed
146
		data = 0;
Spencer Oliver's avatar
Spencer Oliver committed
147
		LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
ntfreak's avatar
ntfreak committed
148
149
		return ERROR_JTAG_DEVICE_ERROR;
	}
150

ntfreak's avatar
ntfreak committed
151
152
153
154
155
	/* Send the data out */
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
	mips_ejtag_drscan_32(ctx->ejtag_info, &data);

	/* Clear the access pending bit (let the processor eat!) */
156
	ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
ntfreak's avatar
ntfreak committed
157
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
158
	mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
159
160
161

	jtag_add_clocks(5);
	jtag_execute_queue();
162

ntfreak's avatar
ntfreak committed
163
164
165
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
166
static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
ntfreak's avatar
ntfreak committed
167
{
168
	uint32_t ejtag_ctrl,data;
ntfreak's avatar
ntfreak committed
169
	int offset;
170
	struct mips_ejtag *ejtag_info = ctx->ejtag_info;
171

ntfreak's avatar
ntfreak committed
172
173
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
	mips_ejtag_drscan_32(ctx->ejtag_info, &data);
174

ntfreak's avatar
ntfreak committed
175
	/* Clear access pending bit */
176
	ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
ntfreak's avatar
ntfreak committed
177
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
178
	mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
179
180
181

	jtag_add_clocks(5);
	jtag_execute_queue();
182

ntfreak's avatar
ntfreak committed
183
184
185
186
187
188
	if ((address >= MIPS32_PRACC_PARAM_IN)
		&& (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
	{
		offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
		ctx->local_iparam[offset] = data;
	}
189
	else if ((address >= MIPS32_PRACC_PARAM_OUT)
ntfreak's avatar
ntfreak committed
190
191
192
193
194
195
196
197
198
199
200
201
		&& (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
	{
		offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
		ctx->local_oparam[offset] = data;
	}
	else if (address == MIPS32_PRACC_STACK)
	{
		/* save data onto our stack */
		ctx->stack[ctx->stack_offset++] = data;
	}
	else
	{
Spencer Oliver's avatar
Spencer Oliver committed
202
		LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
ntfreak's avatar
ntfreak committed
203
204
		return ERROR_JTAG_DEVICE_ERROR;
	}
205

ntfreak's avatar
ntfreak committed
206
207
208
	return ERROR_OK;
}

209
210
int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code,
		int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
ntfreak's avatar
ntfreak committed
211
{
212
213
	uint32_t ejtag_ctrl;
	uint32_t address, data;
Zachary T Welch's avatar
Zachary T Welch committed
214
	struct mips32_pracc_context ctx;
ntfreak's avatar
ntfreak committed
215
216
	int retval;
	int pass = 0;
217

ntfreak's avatar
ntfreak committed
218
219
220
221
222
223
224
225
	ctx.local_iparam = param_in;
	ctx.local_oparam = param_out;
	ctx.num_iparam = num_param_in;
	ctx.num_oparam = num_param_out;
	ctx.code = code;
	ctx.code_len = code_len;
	ctx.ejtag_info = ejtag_info;
	ctx.stack_offset = 0;
226

ntfreak's avatar
ntfreak committed
227
228
	while (1)
	{
229
		if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
ntfreak's avatar
ntfreak committed
230
			return retval;
231

ntfreak's avatar
ntfreak committed
232
233
234
		address = data = 0;
		mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
		mips_ejtag_drscan_32(ejtag_info, &address);
235

ntfreak's avatar
ntfreak committed
236
		/* Check for read or write */
237
		if (ejtag_ctrl & EJTAG_CTRL_PRNW)
ntfreak's avatar
ntfreak committed
238
239
240
241
242
243
244
245
246
247
248
249
250
		{
			if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
				return retval;
		}
		else
		{
			/* Check to see if its reading at the debug vector. The first pass through
			 * the module is always read at the vector, so the first one we allow.  When
			 * the second read from the vector occurs we are done and just exit. */
			if ((address == MIPS32_PRACC_TEXT) && (pass++))
			{
				break;
			}
251

ntfreak's avatar
ntfreak committed
252
253
254
			if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
				return retval;
		}
255

ntfreak's avatar
ntfreak committed
256
257
258
		if (cycle == 0)
			break;
	}
259

ntfreak's avatar
ntfreak committed
260
261
262
263
264
	/* stack sanity check */
	if (ctx.stack_offset != 0)
	{
		LOG_DEBUG("Pracc Stack not zero");
	}
265

ntfreak's avatar
ntfreak committed
266
267
268
	return ERROR_OK;
}

269
int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
ntfreak's avatar
ntfreak committed
270
271
272
273
{
	switch (size)
	{
		case 1:
274
			return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
ntfreak's avatar
ntfreak committed
275
		case 2:
zwelch's avatar
zwelch committed
276
			return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
ntfreak's avatar
ntfreak committed
277
		case 4:
zwelch's avatar
zwelch committed
278
			if (count == 1)
279
				return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf);
280
			else
281
				return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
ntfreak's avatar
ntfreak committed
282
	}
283

ntfreak's avatar
ntfreak committed
284
285
286
	return ERROR_OK;
}

287
int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
288
{
289
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
290
291
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
292
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
293
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
294
295
296
297
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
298

ntfreak's avatar
ntfreak committed
299
300
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
zwelch's avatar
zwelch committed
301
		MIPS32_LW(9,0,8),									/* $9 = mem[$8]; read addr */
zwelch's avatar
zwelch committed
302
		MIPS32_LW(10,4,8),									/* $10 = mem[$8 + 4]; read count */
Spencer Oliver's avatar
Spencer Oliver committed
303
		MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),		/* $11 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
304
305
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
306
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
307
		MIPS32_NOP,
308

Spencer Oliver's avatar
Spencer Oliver committed
309
310
		MIPS32_LW(8,0,9),									/* lw $8,0($9), Load $8 with the word @mem[$9] */
		MIPS32_SW(8,0,11),									/* sw $8,0($11) */
311

Spencer Oliver's avatar
Spencer Oliver committed
312
313
314
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,4),									/* $1 += 4 */
		MIPS32_ADDI(11,11,4),								/* $11 += 4 */
315

Spencer Oliver's avatar
Spencer Oliver committed
316
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
317
318
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
319
320
321
322
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
323
		MIPS32_B(NEG16(27)),								/* b start */
ntfreak's avatar
ntfreak committed
324
325
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
326

327
	int retval = ERROR_OK;
ntfreak's avatar
ntfreak committed
328
329
	int blocksize;
	int bytesread;
330
	uint32_t param_in[2];
331

ntfreak's avatar
ntfreak committed
332
	bytesread = 0;
333

ntfreak's avatar
ntfreak committed
334
	while (count > 0)
335
	{
ntfreak's avatar
ntfreak committed
336
337
338
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
339

ntfreak's avatar
ntfreak committed
340
341
		param_in[0] = addr;
		param_in[1] = blocksize;
342

Zachary T Welch's avatar
Zachary T Welch committed
343
344
		if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
			ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
oharboe's avatar
oharboe committed
345
		{
ntfreak's avatar
ntfreak committed
346
			return retval;
oharboe's avatar
oharboe committed
347
		}
348

ntfreak's avatar
ntfreak committed
349
350
351
352
353
354
355
356
		count -= blocksize;
		addr += blocksize;
		bytesread += blocksize;
	}

	return retval;
}

357
int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
358
{
359
	static const uint32_t code[] = {
360
361
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
362
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
363
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
364
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
365

Spencer Oliver's avatar
Spencer Oliver committed
366
		MIPS32_LW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN),15), /* load R8 @ param_in[0] = address */
367

Spencer Oliver's avatar
Spencer Oliver committed
368
		MIPS32_LW(8,0,8),									/* lw $8,0($8), Load $8 with the word @mem[$8] */
Spencer Oliver's avatar
Spencer Oliver committed
369
		MIPS32_SW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_OUT),15), /* store R8 @ param_out[0] */
370

Spencer Oliver's avatar
Spencer Oliver committed
371
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
372
373
		MIPS32_B(NEG16(9)),									/* b start */
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
374
375
376
	};

	int retval = ERROR_OK;
377
	uint32_t param_in[1];
378
379
380

	param_in[0] = addr;

Zachary T Welch's avatar
Zachary T Welch committed
381
	if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
Spencer Oliver's avatar
Spencer Oliver committed
382
		ARRAY_SIZE(param_in), param_in, 1, buf, 1)) != ERROR_OK)
383
384
385
386
387
388
389
	{
		return retval;
	}

	return retval;
}

390
int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
ntfreak's avatar
ntfreak committed
391
{
392
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
393
394
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
395
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
396
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
397
398
399
400
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
401

ntfreak's avatar
ntfreak committed
402
403
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
zwelch's avatar
zwelch committed
404
		MIPS32_LW(9,0,8),									/* $9 = mem[$8]; read addr */
zwelch's avatar
zwelch committed
405
		MIPS32_LW(10,4,8),									/* $10 = mem[$8 + 4]; read count */
zwelch's avatar
zwelch committed
406
		MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),		/* $11 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
407
408
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
409
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
410
		MIPS32_NOP,
411

Spencer Oliver's avatar
Spencer Oliver committed
412
413
		MIPS32_LHU(8,0,9),									/* lw $8,0($9), Load $8 with the halfword @mem[$9] */
		MIPS32_SW(8,0,11),									/* sw $8,0($11) */
414

Spencer Oliver's avatar
Spencer Oliver committed
415
416
417
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,2),									/* $9 += 2 */
		MIPS32_ADDI(11,11,4),								/* $11 += 4 */
Spencer Oliver's avatar
Spencer Oliver committed
418
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
419
		MIPS32_NOP,
Spencer Oliver's avatar
Spencer Oliver committed
420
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
421
422
423
424
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
425
426
		MIPS32_B(NEG16(27)),								/* b start */
		MIPS32_MFC0(15,30,0),								/* move COP0 DeSave to $15 */
ntfreak's avatar
ntfreak committed
427
428
	};

Spencer Oliver's avatar
Spencer Oliver committed
429
	/* TODO remove array */
430
	uint32_t *param_out = malloc(count * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
431
	int i;
432

ntfreak's avatar
ntfreak committed
433
434
435
//	int retval;
	int blocksize;
	int bytesread;
436
	uint32_t param_in[2];
437

ntfreak's avatar
ntfreak committed
438
	bytesread = 0;
439

ntfreak's avatar
ntfreak committed
440
	//while (count > 0)
441
	{
ntfreak's avatar
ntfreak committed
442
443
444
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
445

ntfreak's avatar
ntfreak committed
446
447
		param_in[0] = addr;
		param_in[1] = blocksize;
448

Zachary T Welch's avatar
Zachary T Welch committed
449
450
		mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
			ARRAY_SIZE(param_in), param_in, count, param_out, 1);
451

ntfreak's avatar
ntfreak committed
452
453
454
455
//		count -= blocksize;
//		addr += blocksize;
//		bytesread += blocksize;
	}
456

ntfreak's avatar
ntfreak committed
457
458
459
460
	for (i = 0; i < count; i++)
	{
		buf[i] = param_out[i];
	}
461

462
463
	free(param_out);

ntfreak's avatar
ntfreak committed
464
465
466
	return ERROR_OK;
}

467
int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
ntfreak's avatar
ntfreak committed
468
{
469
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
470
471
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
472
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
473
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
474
475
476
477
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
478

Spencer Oliver's avatar
Spencer Oliver committed
479
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
480
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
481
482
483
		MIPS32_LW(9,0,8),									/* $9 = mem[$8]; read addr */
		MIPS32_LW(10,4,8),									/* $10 = mem[$8 + 4]; read count */
		MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),		/* $11 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
484
485
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
486
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
487
		MIPS32_NOP,
488

Spencer Oliver's avatar
Spencer Oliver committed
489
490
		MIPS32_LBU(8,0,9),									/* lw $8,0($9), Load t4 with the byte @mem[t1] */
		MIPS32_SW(8,0,11),									/* sw $8,0($11) */
491

Spencer Oliver's avatar
Spencer Oliver committed
492
493
494
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,1),									/* $9 += 1 */
		MIPS32_ADDI(11,11,4),								/* $11 += 4 */
Spencer Oliver's avatar
Spencer Oliver committed
495
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
496
497
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
498
499
500
501
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
502
		MIPS32_B(NEG16(27)),								/* b start */
ntfreak's avatar
ntfreak committed
503
504
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
505

Spencer Oliver's avatar
Spencer Oliver committed
506
	/* TODO remove array */
507
	uint32_t *param_out = malloc(count * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
508
	int i;
509

ntfreak's avatar
ntfreak committed
510
511
512
//	int retval;
	int blocksize;
	int bytesread;
513
	uint32_t param_in[2];
514

ntfreak's avatar
ntfreak committed
515
	bytesread = 0;
516

ntfreak's avatar
ntfreak committed
517
//	while (count > 0)
518
	{
ntfreak's avatar
ntfreak committed
519
520
521
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
522

ntfreak's avatar
ntfreak committed
523
524
		param_in[0] = addr;
		param_in[1] = blocksize;
525

Zachary T Welch's avatar
Zachary T Welch committed
526
527
		mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
			ARRAY_SIZE(param_in), param_in, count, param_out, 1);
528

ntfreak's avatar
ntfreak committed
529
530
531
532
//		count -= blocksize;
//		addr += blocksize;
//		bytesread += blocksize;
	}
533

ntfreak's avatar
ntfreak committed
534
535
536
537
538
	for (i = 0; i < count; i++)
	{
		buf[i] = param_out[i];
	}

539
540
	free(param_out);

ntfreak's avatar
ntfreak committed
541
542
543
	return ERROR_OK;
}

544
int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
ntfreak's avatar
ntfreak committed
545
546
547
548
{
	switch (size)
	{
		case 1:
549
			return mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
ntfreak's avatar
ntfreak committed
550
		case 2:
zwelch's avatar
zwelch committed
551
			return mips32_pracc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
ntfreak's avatar
ntfreak committed
552
		case 4:
zwelch's avatar
zwelch committed
553
			if (count == 1)
554
				return mips32_pracc_write_u32(ejtag_info, addr, (uint32_t*)buf);
555
			else
556
				return mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
ntfreak's avatar
ntfreak committed
557
	}
558

ntfreak's avatar
ntfreak committed
559
560
561
	return ERROR_OK;
}

562
int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
ntfreak's avatar
ntfreak committed
563
{
564
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
565
566
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
567
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
568
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
569
570
571
572
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
573

Spencer Oliver's avatar
Spencer Oliver committed
574
		MIPS32_ADDI(8,15,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)),  /* $8= MIPS32_PRACC_PARAM_IN */
Spencer Oliver's avatar
Spencer Oliver committed
575
		MIPS32_LW(9,0,8),									/* Load write addr to $9 */
Spencer Oliver's avatar
Spencer Oliver committed
576
577
		MIPS32_LW(10,4,8),									/* Load write count to $10 */
		MIPS32_ADDI(8,8,8),									/* $8 += 8 beginning of data */
578

Spencer Oliver's avatar
Spencer Oliver committed
579
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
580
581
		MIPS32_LW(11,0,8),									/* lw $11,0($8), Load $11 with the word @mem[$8] */
		MIPS32_SW(11,0,9),									/* sw $11,0($9) */
582

Spencer Oliver's avatar
Spencer Oliver committed
583
		MIPS32_ADDI(9,9,4),									/* $9 += 4 */
Spencer Oliver's avatar
Spencer Oliver committed
584
585
586
		MIPS32_BNE(10,9,NEG16(4)),							/* bne $10, $9, loop */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */

ntfreak's avatar
ntfreak committed
587
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
588
589
590
591
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
592
		MIPS32_B(NEG16(21)),								/* b start */
ntfreak's avatar
ntfreak committed
593
594
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
595

ntfreak's avatar
ntfreak committed
596
	/* TODO remove array */
597
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
598
	param_in[0] = addr;
Spencer Oliver's avatar
Spencer Oliver committed
599
	param_in[1] = addr + (count * sizeof(uint32_t));	/* last address */
600

601
	memcpy(&param_in[2], buf, count * sizeof(uint32_t));
602

Zachary T Welch's avatar
Zachary T Welch committed
603
	mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
604
		count + 2, param_in, 0, NULL, 1);
ntfreak's avatar
ntfreak committed
605

606
607
	free(param_in);

ntfreak's avatar
ntfreak committed
608
609
610
	return ERROR_OK;
}

611
int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
612
{
613
	static const uint32_t code[] = {
614
615
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
616
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
617
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
618
619
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
620

Spencer Oliver's avatar
Spencer Oliver committed
621
622
		MIPS32_LW(8,NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15),	/* load R8 @ param_in[1] = data */
		MIPS32_LW(9,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15),		/* load R9 @ param_in[0] = address */
623

Spencer Oliver's avatar
Spencer Oliver committed
624
		MIPS32_SW(8,0,9),									/* sw $8,0($9) */
625

Spencer Oliver's avatar
Spencer Oliver committed
626
627
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
628
		MIPS32_B(NEG16(11)),								/* b start */
Spencer Oliver's avatar
Spencer Oliver committed
629
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
630
631
632
	};

	/* TODO remove array */
zwelch's avatar
zwelch committed
633
	uint32_t param_in[1 + 1];
634
635
636
	param_in[0] = addr;
	param_in[1] = *buf;

Zachary T Welch's avatar
Zachary T Welch committed
637
	mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
Spencer Oliver's avatar
Spencer Oliver committed
638
		ARRAY_SIZE(param_in), param_in, 0, NULL, 1);
639
640
641
642

	return ERROR_OK;
}

643
int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
ntfreak's avatar
ntfreak committed
644
{
645
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
646
647
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
648
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
649
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
650
651
652
653
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
654

Spencer Oliver's avatar
Spencer Oliver committed
655
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
656
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
657
658
659
		MIPS32_LW(9,0,8),									/* Load write addr to $9 */
		MIPS32_LW(10,4,8),									/* Load write count to $10 */
		MIPS32_ADDI(8,8,8),									/* $8 += 8 */
ntfreak's avatar
ntfreak committed
660
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
661
		MIPS32_BEQ(0,10,8),									/* beq $0, $10, end */
ntfreak's avatar
ntfreak committed
662
		MIPS32_NOP,
663

Spencer Oliver's avatar
Spencer Oliver committed
664
665
		MIPS32_LW(11,0,8),									/* lw $11,0($8), Load $11 with the word @mem[$8] */
		MIPS32_SH(11,0,9),									/* sh $11,0($9) */
666

Spencer Oliver's avatar
Spencer Oliver committed
667
668
669
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,2),									/* $9 += 2 */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */
670

Spencer Oliver's avatar
Spencer Oliver committed
671
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
672
673
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
674
675
676
677
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
678
		MIPS32_B(NEG16(26)),								/* b start */
ntfreak's avatar
ntfreak committed
679
680
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
681

ntfreak's avatar
ntfreak committed
682
	/* TODO remove array */
683
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
684
685
686
	int i;
	param_in[0] = addr;
	param_in[1] = count;
687

ntfreak's avatar
ntfreak committed
688
689
	for (i = 0; i < count; i++)
	{
zwelch's avatar
zwelch committed
690
		param_in[i + 2] = buf[i];
ntfreak's avatar
ntfreak committed
691
	}
692

Zachary T Welch's avatar
Zachary T Welch committed
693
	mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
694
		count + 2, param_in, 0, NULL, 1);
ntfreak's avatar
ntfreak committed
695

696
697
	free(param_in);

ntfreak's avatar
ntfreak committed
698
699
700
	return ERROR_OK;
}

701
int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
ntfreak's avatar
ntfreak committed
702
{
703
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
704
705
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
706
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
707
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
708
709
710
711
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
		MIPS32_SW(10,0,15),									/* sw $10,($15) */
		MIPS32_SW(11,0,15),									/* sw $11,($15) */
712

Spencer Oliver's avatar
Spencer Oliver committed
713
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
714
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
715
716
717
		MIPS32_LW(9,0,8),									/* Load write addr to $9 */
		MIPS32_LW(10,4,8),									/* Load write count to $10 */
		MIPS32_ADDI(8,8,8),									/* $8 += 8 */
ntfreak's avatar
ntfreak committed
718
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
719
		MIPS32_BEQ(0,10,8),									/* beq $0, $10, end */
ntfreak's avatar
ntfreak committed
720
		MIPS32_NOP,
721

Spencer Oliver's avatar
Spencer Oliver committed
722
723
		MIPS32_LW(11,0,8),									/* lw $11,0($8), Load $11 with the word @mem[$8] */
		MIPS32_SB(11,0,9),									/* sb $11,0($9) */
724

Spencer Oliver's avatar
Spencer Oliver committed
725
726
727
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,1),									/* $9 += 1 */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */
728

Spencer Oliver's avatar
Spencer Oliver committed
729
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
730
731
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
732
733
734
735
		MIPS32_LW(11,0,15),									/* lw $11,($15) */
		MIPS32_LW(10,0,15),									/* lw $10,($15) */
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
736
		MIPS32_B(NEG16(26)),								/* b start */
ntfreak's avatar
ntfreak committed
737
738
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
739

ntfreak's avatar
ntfreak committed
740
	/* TODO remove array */
741
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
742
743
744
745
	int retval;
	int i;
	param_in[0] = addr;
	param_in[1] = count;
746

ntfreak's avatar
ntfreak committed
747
748
	for (i = 0; i < count; i++)
	{
zwelch's avatar
zwelch committed
749
		param_in[i + 2] = buf[i];
ntfreak's avatar
ntfreak committed
750
	}
751

Zachary T Welch's avatar
Zachary T Welch committed
752
	retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
Spencer Oliver's avatar
Spencer Oliver committed
753
		count + 2, param_in, 0, NULL, 1);
ntfreak's avatar
ntfreak committed
754

755
756
	free(param_in);

ntfreak's avatar
ntfreak committed
757
758
759
	return retval;
}

760
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
ntfreak's avatar
ntfreak committed
761
{
762
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
763
														/* start: */
Spencer Oliver's avatar
Spencer Oliver committed
764
		MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),	/* $2 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
765
		MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
766
767
		MIPS32_LW(1,1*4,2),								/* lw $1,1*4($2) */
		MIPS32_LW(15,15*4,2),							/* lw $15,15*4($2) */
768
		MIPS32_MTC0(15,31,0),							/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
769
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),		/* $15 = MIPS32_PRACC_STACK */
770
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
771
772
		MIPS32_SW(1,0,15),								/* sw $1,($15) */
		MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)),	/* $1 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
773
		MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
		MIPS32_LW(3,3*4,1),								/* lw $3,3*4($1) */
		MIPS32_LW(4,4*4,1),								/* lw $4,4*4($1) */
		MIPS32_LW(5,5*4,1),								/* lw $5,5*4($1) */
		MIPS32_LW(6,6*4,1),								/* lw $6,6*4($1) */
		MIPS32_LW(7,7*4,1),								/* lw $7,7*4($1) */
		MIPS32_LW(8,8*4,1),								/* lw $8,8*4($1) */
		MIPS32_LW(9,9*4,1),								/* lw $9,9*4($1) */
		MIPS32_LW(10,10*4,1),							/* lw $10,10*4($1) */
		MIPS32_LW(11,11*4,1),							/* lw $11,11*4($1) */
		MIPS32_LW(12,12*4,1),							/* lw $12,12*4($1) */
		MIPS32_LW(13,13*4,1),							/* lw $13,13*4($1) */
		MIPS32_LW(14,14*4,1),							/* lw $14,14*4($1) */
		MIPS32_LW(16,16*4,1),							/* lw $16,16*4($1) */
		MIPS32_LW(17,17*4,1),							/* lw $17,17*4($1) */
		MIPS32_LW(18,18*4,1),							/* lw $18,18*4($1) */
		MIPS32_LW(19,19*4,1),							/* lw $19,19*4($1) */
		MIPS32_LW(20,20*4,1),							/* lw $20,20*4($1) */
		MIPS32_LW(21,21*4,1),							/* lw $21,21*4($1) */
		MIPS32_LW(22,22*4,1),							/* lw $22,22*4($1) */
		MIPS32_LW(23,23*4,1),							/* lw $23,23*4($1) */
		MIPS32_LW(24,24*4,1),							/* lw $24,24*4($1) */
		MIPS32_LW(25,25*4,1),							/* lw $25,25*4($1) */
		MIPS32_LW(26,26*4,1),							/* lw $26,26*4($1) */
		MIPS32_LW(27,27*4,1),							/* lw $27,27*4($1) */
		MIPS32_LW(28,28*4,1),							/* lw $28,28*4($1) */
		MIPS32_LW(29,29*4,1),							/* lw $29,29*4($1) */
		MIPS32_LW(30,30*4,1),							/* lw $30,30*4($1) */
		MIPS32_LW(31,31*4,1),							/* lw $31,31*4($1) */

		MIPS32_LW(2,32*4,1),							/* lw $2,32*4($1) */
804
		MIPS32_MTC0(2,12,0),							/* move $2 to status */
Spencer Oliver's avatar
Spencer Oliver committed
805
		MIPS32_LW(2,33*4,1),							/* lw $2,33*4($1) */
806
		MIPS32_MTLO(2),									/* move $2 to lo */
Spencer Oliver's avatar
Spencer Oliver committed
807
		MIPS32_LW(2,34*4,1),							/* lw $2,34*4($1) */
808
		MIPS32_MTHI(2),									/* move $2 to hi */
Spencer Oliver's avatar
Spencer Oliver committed
809
		MIPS32_LW(2,35*4,1),							/* lw $2,35*4($1) */
810
		MIPS32_MTC0(2,8,0),								/* move $2 to badvaddr */
Spencer Oliver's avatar
Spencer Oliver committed
811
		MIPS32_LW(2,36*4,1),							/* lw $2,36*4($1) */
812
		MIPS32_MTC0(2,13,0),							/* move $2 to cause*/
Spencer Oliver's avatar
Spencer Oliver committed
813
		MIPS32_LW(2,37*4,1),							/* lw $2,37*4($1) */
814
		MIPS32_MTC0(2,24,0),							/* move $2 to depc (pc) */
815

Spencer Oliver's avatar
Spencer Oliver committed
816
817
		MIPS32_LW(2,2*4,1),								/* lw $2,2*4($1) */
		MIPS32_LW(1,0,15),								/* lw $1,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
818
		MIPS32_B(NEG16(53)),							/* b start */
819
		MIPS32_MFC0(15,31,0),							/* move COP0 DeSave to $15 */
ntfreak's avatar
ntfreak committed
820
	};
821

ntfreak's avatar
ntfreak committed
822
	int retval;
823

Zachary T Welch's avatar
Zachary T Welch committed
824
	retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
Spencer Oliver's avatar
Spencer Oliver committed
825
			MIPS32NUMCOREREGS, regs, 0, NULL, 1);
826

ntfreak's avatar
ntfreak committed
827
828
829
	return retval;
}

830
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
ntfreak's avatar
ntfreak committed
831
{
832
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
833
834
														/* start: */
		MIPS32_MTC0(2,31,0),							/* move $2 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
835
		MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),	/* $2 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
836
837
		MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
		MIPS32_SW(0,0*4,2),								/* sw $0,0*4($2) */
Spencer Oliver's avatar
Spencer Oliver committed
838
839
		MIPS32_SW(1,1*4,2),								/* sw $1,1*4($2) */
		MIPS32_SW(15,15*4,2),							/* sw $15,15*4($2) */
ntfreak's avatar
ntfreak committed
840
841
		MIPS32_MFC0(2,31,0),							/* move COP0 DeSave to $2 */
		MIPS32_MTC0(15,31,0),							/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
842
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),		/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
843
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
844
845
846
		MIPS32_SW(1,0,15),								/* sw $1,($15) */
		MIPS32_SW(2,0,15),								/* sw $2,($15) */
		MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),	/* $1 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
847
		MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
Spencer Oliver's avatar
Spencer Oliver committed
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
		MIPS32_SW(2,2*4,1),								/* sw $2,2*4($1) */
		MIPS32_SW(3,3*4,1),								/* sw $3,3*4($1) */
		MIPS32_SW(4,4*4,1),								/* sw $4,4*4($1) */
		MIPS32_SW(5,5*4,1),								/* sw $5,5*4($1) */
		MIPS32_SW(6,6*4,1),								/* sw $6,6*4($1) */
		MIPS32_SW(7,7*4,1),								/* sw $7,7*4($1) */
		MIPS32_SW(8,8*4,1),								/* sw $8,8*4($1) */
		MIPS32_SW(9,9*4,1),								/* sw $9,9*4($1) */
		MIPS32_SW(10,10*4,1),							/* sw $10,10*4($1) */
		MIPS32_SW(11,11*4,1),							/* sw $11,11*4($1) */
		MIPS32_SW(12,12*4,1),							/* sw $12,12*4($1) */
		MIPS32_SW(13,13*4,1),							/* sw $13,13*4($1) */
		MIPS32_SW(14,14*4,1),							/* sw $14,14*4($1) */
		MIPS32_SW(16,16*4,1),							/* sw $16,16*4($1) */
		MIPS32_SW(17,17*4,1),							/* sw $17,17*4($1) */
		MIPS32_SW(18,18*4,1),							/* sw $18,18*4($1) */
		MIPS32_SW(19,19*4,1),							/* sw $19,19*4($1) */
		MIPS32_SW(20,20*4,1),							/* sw $20,20*4($1) */
		MIPS32_SW(21,21*4,1),							/* sw $21,21*4($1) */
		MIPS32_SW(22,22*4,1),							/* sw $22,22*4($1) */
		MIPS32_SW(23,23*4,1),							/* sw $23,23*4($1) */
		MIPS32_SW(24,24*4,1),							/* sw $24,24*4($1) */
		MIPS32_SW(25,25*4,1),							/* sw $25,25*4($1) */
		MIPS32_SW(26,26*4,1),							/* sw $26,26*4($1) */
		MIPS32_SW(27,27*4,1),							/* sw $27,27*4($1) */
		MIPS32_SW(28,28*4,1),							/* sw $28,28*4($1) */
		MIPS32_SW(29,29*4,1),							/* sw $29,29*4($1) */
		MIPS32_SW(30,30*4,1),							/* sw $30,30*4($1) */
		MIPS32_SW(31,31*4,1),							/* sw $31,31*4($1) */
877

ntfreak's avatar
ntfreak committed
878
		MIPS32_MFC0(2,12,0),							/* move status to $2 */