mips32_pracc.c 34.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint8_t *buf);
static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint16_t *buf);
static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint32_t *buf);
static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info,
		uint32_t addr, uint32_t *buf);

static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint8_t *buf);
static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint16_t *buf);
static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info,
		uint32_t addr, int count, uint32_t *buf);
static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info,
		uint32_t addr, uint32_t *buf);

111
static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
ntfreak's avatar
ntfreak committed
112
{
113
	uint32_t ejtag_ctrl;
114
115

	while (1)
ntfreak's avatar
ntfreak committed
116
	{
117
		mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
118
		ejtag_ctrl = ejtag_info->ejtag_ctrl;
ntfreak's avatar
ntfreak committed
119
120
121
		mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
		if (ejtag_ctrl & EJTAG_CTRL_PRACC)
			break;
Eric Wetzel's avatar
Eric Wetzel committed
122
		LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
ntfreak's avatar
ntfreak committed
123
124
		return ERROR_JTAG_DEVICE_ERROR;
	}
125

ntfreak's avatar
ntfreak committed
126
127
128
129
	*ctrl = ejtag_ctrl;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
130
static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
ntfreak's avatar
ntfreak committed
131
{
132
	struct mips_ejtag *ejtag_info = ctx->ejtag_info;
ntfreak's avatar
ntfreak committed
133
	int offset;
134
	uint32_t ejtag_ctrl, data;
ntfreak's avatar
ntfreak committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148

	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
149
		&& (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4))
ntfreak's avatar
ntfreak committed
150
151
152
153
154
155
156
157
158
159
160
161
162
	{
		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 */
163

ntfreak's avatar
ntfreak committed
164
		data = 0;
Spencer Oliver's avatar
Spencer Oliver committed
165
		LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
ntfreak's avatar
ntfreak committed
166
167
		return ERROR_JTAG_DEVICE_ERROR;
	}
168

ntfreak's avatar
ntfreak committed
169
	/* Send the data out */
170
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
ntfreak's avatar
ntfreak committed
171
172
173
	mips_ejtag_drscan_32(ctx->ejtag_info, &data);

	/* Clear the access pending bit (let the processor eat!) */
174
	ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
175
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
176
	mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
177
178
179

	jtag_add_clocks(5);
	jtag_execute_queue();
180

ntfreak's avatar
ntfreak committed
181
182
183
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
184
static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
ntfreak's avatar
ntfreak committed
185
{
186
	uint32_t ejtag_ctrl,data;
ntfreak's avatar
ntfreak committed
187
	int offset;
188
	struct mips_ejtag *ejtag_info = ctx->ejtag_info;
189

190
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
ntfreak's avatar
ntfreak committed
191
	mips_ejtag_drscan_32(ctx->ejtag_info, &data);
192

ntfreak's avatar
ntfreak committed
193
	/* Clear access pending bit */
194
	ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
195
	mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
196
	mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
197
198
199

	jtag_add_clocks(5);
	jtag_execute_queue();
200

ntfreak's avatar
ntfreak committed
201
202
203
204
205
206
	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;
	}
207
	else if ((address >= MIPS32_PRACC_PARAM_OUT)
ntfreak's avatar
ntfreak committed
208
209
210
211
212
213
214
215
216
217
218
219
		&& (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
220
		LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
ntfreak's avatar
ntfreak committed
221
222
		return ERROR_JTAG_DEVICE_ERROR;
	}
223

ntfreak's avatar
ntfreak committed
224
225
226
	return ERROR_OK;
}

227
228
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
229
{
230
231
	uint32_t ejtag_ctrl;
	uint32_t address, data;
Zachary T Welch's avatar
Zachary T Welch committed
232
	struct mips32_pracc_context ctx;
ntfreak's avatar
ntfreak committed
233
234
	int retval;
	int pass = 0;
235

ntfreak's avatar
ntfreak committed
236
237
238
239
240
241
242
243
	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;
244

ntfreak's avatar
ntfreak committed
245
246
	while (1)
	{
247
		if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
ntfreak's avatar
ntfreak committed
248
			return retval;
249

ntfreak's avatar
ntfreak committed
250
		address = data = 0;
251
		mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
ntfreak's avatar
ntfreak committed
252
		mips_ejtag_drscan_32(ejtag_info, &address);
253

ntfreak's avatar
ntfreak committed
254
		/* Check for read or write */
255
		if (ejtag_ctrl & EJTAG_CTRL_PRNW)
ntfreak's avatar
ntfreak committed
256
257
258
259
260
261
262
263
264
265
266
267
268
		{
			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;
			}
269

ntfreak's avatar
ntfreak committed
270
271
272
			if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
				return retval;
		}
273

ntfreak's avatar
ntfreak committed
274
275
276
		if (cycle == 0)
			break;
	}
277

ntfreak's avatar
ntfreak committed
278
279
280
281
282
	/* stack sanity check */
	if (ctx.stack_offset != 0)
	{
		LOG_DEBUG("Pracc Stack not zero");
	}
283

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

287
int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
ntfreak's avatar
ntfreak committed
288
289
290
291
{
	switch (size)
	{
		case 1:
292
			return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
ntfreak's avatar
ntfreak committed
293
		case 2:
zwelch's avatar
zwelch committed
294
			return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
ntfreak's avatar
ntfreak committed
295
		case 4:
zwelch's avatar
zwelch committed
296
			if (count == 1)
297
				return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf);
298
			else
299
				return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
ntfreak's avatar
ntfreak committed
300
	}
301

ntfreak's avatar
ntfreak committed
302
303
304
	return ERROR_OK;
}

305
static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
306
{
307
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
308
309
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
310
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
311
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
312
313
314
315
		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) */
316

ntfreak's avatar
ntfreak committed
317
318
		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
319
		MIPS32_LW(9,0,8),									/* $9 = mem[$8]; read addr */
zwelch's avatar
zwelch committed
320
		MIPS32_LW(10,4,8),									/* $10 = mem[$8 + 4]; read count */
Spencer Oliver's avatar
Spencer Oliver committed
321
		MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),		/* $11 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
322
323
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
324
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
325
		MIPS32_NOP,
326

Spencer Oliver's avatar
Spencer Oliver committed
327
328
		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) */
329

Spencer Oliver's avatar
Spencer Oliver committed
330
331
332
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,4),									/* $1 += 4 */
		MIPS32_ADDI(11,11,4),								/* $11 += 4 */
333

Spencer Oliver's avatar
Spencer Oliver committed
334
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
335
336
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
337
338
339
340
		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
341
		MIPS32_B(NEG16(27)),								/* b start */
ntfreak's avatar
ntfreak committed
342
343
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
344

345
	int retval = ERROR_OK;
ntfreak's avatar
ntfreak committed
346
347
	int blocksize;
	int bytesread;
348
	uint32_t param_in[2];
349

ntfreak's avatar
ntfreak committed
350
	bytesread = 0;
351

ntfreak's avatar
ntfreak committed
352
	while (count > 0)
353
	{
ntfreak's avatar
ntfreak committed
354
355
356
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
357

ntfreak's avatar
ntfreak committed
358
359
		param_in[0] = addr;
		param_in[1] = blocksize;
360

Zachary T Welch's avatar
Zachary T Welch committed
361
362
		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
363
		{
ntfreak's avatar
ntfreak committed
364
			return retval;
oharboe's avatar
oharboe committed
365
		}
366

ntfreak's avatar
ntfreak committed
367
368
369
370
371
372
373
374
		count -= blocksize;
		addr += blocksize;
		bytesread += blocksize;
	}

	return retval;
}

375
static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
376
{
377
	static const uint32_t code[] = {
378
379
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
380
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
381
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
382
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
383

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

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

Spencer Oliver's avatar
Spencer Oliver committed
389
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
Spencer Oliver's avatar
Spencer Oliver committed
390
391
		MIPS32_B(NEG16(9)),									/* b start */
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
392
393
394
	};

	int retval = ERROR_OK;
395
	uint32_t param_in[1];
396
397
398

	param_in[0] = addr;

Zachary T Welch's avatar
Zachary T Welch committed
399
	if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
Spencer Oliver's avatar
Spencer Oliver committed
400
		ARRAY_SIZE(param_in), param_in, 1, buf, 1)) != ERROR_OK)
401
402
403
404
405
406
407
	{
		return retval;
	}

	return retval;
}

408
static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
ntfreak's avatar
ntfreak committed
409
{
410
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
411
412
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
413
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
414
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
415
416
417
418
		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) */
419

ntfreak's avatar
ntfreak committed
420
421
		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
422
		MIPS32_LW(9,0,8),									/* $9 = mem[$8]; read addr */
zwelch's avatar
zwelch committed
423
		MIPS32_LW(10,4,8),									/* $10 = mem[$8 + 4]; read count */
zwelch's avatar
zwelch committed
424
		MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),		/* $11 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
425
426
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
427
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
428
		MIPS32_NOP,
429

Spencer Oliver's avatar
Spencer Oliver committed
430
431
		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) */
432

Spencer Oliver's avatar
Spencer Oliver committed
433
434
435
		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
436
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
437
		MIPS32_NOP,
Spencer Oliver's avatar
Spencer Oliver committed
438
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
439
440
441
442
		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
443
444
		MIPS32_B(NEG16(27)),								/* b start */
		MIPS32_MFC0(15,30,0),								/* move COP0 DeSave to $15 */
ntfreak's avatar
ntfreak committed
445
446
	};

Spencer Oliver's avatar
Spencer Oliver committed
447
	/* TODO remove array */
448
	uint32_t *param_out = malloc(count * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
449
	int i;
450

ntfreak's avatar
ntfreak committed
451
452
453
//	int retval;
	int blocksize;
	int bytesread;
454
	uint32_t param_in[2];
455

ntfreak's avatar
ntfreak committed
456
	bytesread = 0;
457

ntfreak's avatar
ntfreak committed
458
	//while (count > 0)
459
	{
ntfreak's avatar
ntfreak committed
460
461
462
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
463

ntfreak's avatar
ntfreak committed
464
465
		param_in[0] = addr;
		param_in[1] = blocksize;
466

Zachary T Welch's avatar
Zachary T Welch committed
467
468
		mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
			ARRAY_SIZE(param_in), param_in, count, param_out, 1);
469

ntfreak's avatar
ntfreak committed
470
471
472
473
//		count -= blocksize;
//		addr += blocksize;
//		bytesread += blocksize;
	}
474

ntfreak's avatar
ntfreak committed
475
476
477
478
	for (i = 0; i < count; i++)
	{
		buf[i] = param_out[i];
	}
479

480
481
	free(param_out);

ntfreak's avatar
ntfreak committed
482
483
484
	return ERROR_OK;
}

485
static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
ntfreak's avatar
ntfreak committed
486
{
487
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
488
489
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
490
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
491
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
492
493
494
495
		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) */
496

Spencer Oliver's avatar
Spencer Oliver committed
497
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
498
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
499
500
501
		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
502
503
		MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
504
		MIPS32_BEQ(0,10,8),									/* beq 0, $10, end */
ntfreak's avatar
ntfreak committed
505
		MIPS32_NOP,
506

Spencer Oliver's avatar
Spencer Oliver committed
507
508
		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) */
509

Spencer Oliver's avatar
Spencer Oliver committed
510
511
512
		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
513
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
514
515
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
516
517
518
519
		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
520
		MIPS32_B(NEG16(27)),								/* b start */
ntfreak's avatar
ntfreak committed
521
522
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
523

Spencer Oliver's avatar
Spencer Oliver committed
524
	/* TODO remove array */
525
	uint32_t *param_out = malloc(count * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
526
	int i;
527

ntfreak's avatar
ntfreak committed
528
529
530
//	int retval;
	int blocksize;
	int bytesread;
531
	uint32_t param_in[2];
532

ntfreak's avatar
ntfreak committed
533
	bytesread = 0;
534

ntfreak's avatar
ntfreak committed
535
//	while (count > 0)
536
	{
ntfreak's avatar
ntfreak committed
537
538
539
		blocksize = count;
		if (count > 0x400)
			blocksize = 0x400;
540

ntfreak's avatar
ntfreak committed
541
542
		param_in[0] = addr;
		param_in[1] = blocksize;
543

Zachary T Welch's avatar
Zachary T Welch committed
544
545
		mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
			ARRAY_SIZE(param_in), param_in, count, param_out, 1);
546

ntfreak's avatar
ntfreak committed
547
548
549
550
//		count -= blocksize;
//		addr += blocksize;
//		bytesread += blocksize;
	}
551

ntfreak's avatar
ntfreak committed
552
553
554
555
556
	for (i = 0; i < count; i++)
	{
		buf[i] = param_out[i];
	}

557
558
	free(param_out);

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

562
int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
ntfreak's avatar
ntfreak committed
563
564
565
566
{
	switch (size)
	{
		case 1:
567
			return mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
ntfreak's avatar
ntfreak committed
568
		case 2:
zwelch's avatar
zwelch committed
569
			return mips32_pracc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
ntfreak's avatar
ntfreak committed
570
		case 4:
zwelch's avatar
zwelch committed
571
			if (count == 1)
572
				return mips32_pracc_write_u32(ejtag_info, addr, (uint32_t*)buf);
573
			else
574
				return mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
ntfreak's avatar
ntfreak committed
575
	}
576

ntfreak's avatar
ntfreak committed
577
578
579
	return ERROR_OK;
}

580
static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
ntfreak's avatar
ntfreak committed
581
{
582
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
583
584
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
585
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
586
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
587
588
589
590
		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) */
591

Spencer Oliver's avatar
Spencer Oliver committed
592
		MIPS32_ADDI(8,15,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)),  /* $8= MIPS32_PRACC_PARAM_IN */
Spencer Oliver's avatar
Spencer Oliver committed
593
		MIPS32_LW(9,0,8),									/* Load write addr to $9 */
Spencer Oliver's avatar
Spencer Oliver committed
594
595
		MIPS32_LW(10,4,8),									/* Load write count to $10 */
		MIPS32_ADDI(8,8,8),									/* $8 += 8 beginning of data */
596

Spencer Oliver's avatar
Spencer Oliver committed
597
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
598
599
		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) */
600

Spencer Oliver's avatar
Spencer Oliver committed
601
		MIPS32_ADDI(9,9,4),									/* $9 += 4 */
Spencer Oliver's avatar
Spencer Oliver committed
602
603
604
		MIPS32_BNE(10,9,NEG16(4)),							/* bne $10, $9, loop */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */

ntfreak's avatar
ntfreak committed
605
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
606
607
608
609
		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
610
		MIPS32_B(NEG16(21)),								/* b start */
ntfreak's avatar
ntfreak committed
611
612
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
613

ntfreak's avatar
ntfreak committed
614
	/* TODO remove array */
615
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
616
	param_in[0] = addr;
Spencer Oliver's avatar
Spencer Oliver committed
617
	param_in[1] = addr + (count * sizeof(uint32_t));	/* last address */
618

619
	memcpy(&param_in[2], buf, count * sizeof(uint32_t));
620

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

624
625
	free(param_in);

ntfreak's avatar
ntfreak committed
626
627
628
	return ERROR_OK;
}

629
static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
630
{
631
	static const uint32_t code[] = {
632
633
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
634
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
635
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
636
637
		MIPS32_SW(8,0,15),									/* sw $8,($15) */
		MIPS32_SW(9,0,15),									/* sw $9,($15) */
638

Spencer Oliver's avatar
Spencer Oliver committed
639
640
		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 */
641

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

Spencer Oliver's avatar
Spencer Oliver committed
644
645
		MIPS32_LW(9,0,15),									/* lw $9,($15) */
		MIPS32_LW(8,0,15),									/* lw $8,($15) */
646
		MIPS32_B(NEG16(11)),								/* b start */
Spencer Oliver's avatar
Spencer Oliver committed
647
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
648
649
650
	};

	/* TODO remove array */
zwelch's avatar
zwelch committed
651
	uint32_t param_in[1 + 1];
652
653
654
	param_in[0] = addr;
	param_in[1] = *buf;

Zachary T Welch's avatar
Zachary T Welch committed
655
	mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
Spencer Oliver's avatar
Spencer Oliver committed
656
		ARRAY_SIZE(param_in), param_in, 0, NULL, 1);
657
658
659
660

	return ERROR_OK;
}

661
static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
ntfreak's avatar
ntfreak committed
662
{
663
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
664
665
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
666
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
667
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
668
669
670
671
		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) */
672

Spencer Oliver's avatar
Spencer Oliver committed
673
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
674
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
675
676
677
		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
678
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
679
		MIPS32_BEQ(0,10,8),									/* beq $0, $10, end */
ntfreak's avatar
ntfreak committed
680
		MIPS32_NOP,
681

Spencer Oliver's avatar
Spencer Oliver committed
682
683
		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) */
684

Spencer Oliver's avatar
Spencer Oliver committed
685
686
687
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,2),									/* $9 += 2 */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */
688

Spencer Oliver's avatar
Spencer Oliver committed
689
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
690
691
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
692
693
694
695
		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
696
		MIPS32_B(NEG16(26)),								/* b start */
ntfreak's avatar
ntfreak committed
697
698
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
699

ntfreak's avatar
ntfreak committed
700
	/* TODO remove array */
701
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
702
703
704
	int i;
	param_in[0] = addr;
	param_in[1] = count;
705

ntfreak's avatar
ntfreak committed
706
707
	for (i = 0; i < count; i++)
	{
zwelch's avatar
zwelch committed
708
		param_in[i + 2] = buf[i];
ntfreak's avatar
ntfreak committed
709
	}
710

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

714
715
	free(param_in);

ntfreak's avatar
ntfreak committed
716
717
718
	return ERROR_OK;
}

719
static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
ntfreak's avatar
ntfreak committed
720
{
721
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
722
723
															/* start: */
		MIPS32_MTC0(15,31,0),								/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
724
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),			/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
725
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
726
727
728
729
		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) */
730

Spencer Oliver's avatar
Spencer Oliver committed
731
		MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),		/* $8 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
732
		MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
733
734
735
		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
736
															/* loop: */
Spencer Oliver's avatar
Spencer Oliver committed
737
		MIPS32_BEQ(0,10,8),									/* beq $0, $10, end */
ntfreak's avatar
ntfreak committed
738
		MIPS32_NOP,
739

Spencer Oliver's avatar
Spencer Oliver committed
740
741
		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) */
742

Spencer Oliver's avatar
Spencer Oliver committed
743
744
745
		MIPS32_ADDI(10,10,NEG16(1)),						/* $10-- */
		MIPS32_ADDI(9,9,1),									/* $9 += 1 */
		MIPS32_ADDI(8,8,4),									/* $8 += 4 */
746

Spencer Oliver's avatar
Spencer Oliver committed
747
		MIPS32_B(NEG16(8)),									/* b loop */
ntfreak's avatar
ntfreak committed
748
749
		MIPS32_NOP,
															/* end: */
Spencer Oliver's avatar
Spencer Oliver committed
750
751
752
753
		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
754
		MIPS32_B(NEG16(26)),								/* b start */
ntfreak's avatar
ntfreak committed
755
756
		MIPS32_MFC0(15,31,0),								/* move COP0 DeSave to $15 */
	};
757

ntfreak's avatar
ntfreak committed
758
	/* TODO remove array */
759
	uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
ntfreak's avatar
ntfreak committed
760
761
762
763
	int retval;
	int i;
	param_in[0] = addr;
	param_in[1] = count;
764

ntfreak's avatar
ntfreak committed
765
766
	for (i = 0; i < count; i++)
	{
zwelch's avatar
zwelch committed
767
		param_in[i + 2] = buf[i];
ntfreak's avatar
ntfreak committed
768
	}
769

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

773
774
	free(param_in);

ntfreak's avatar
ntfreak committed
775
776
777
	return retval;
}

778
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
ntfreak's avatar
ntfreak committed
779
{
780
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
781
														/* start: */
Spencer Oliver's avatar
Spencer Oliver committed
782
		MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),	/* $2 = MIPS32_PRACC_PARAM_IN */
ntfreak's avatar
ntfreak committed
783
		MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
784
785
		MIPS32_LW(1,1*4,2),								/* lw $1,1*4($2) */
		MIPS32_LW(15,15*4,2),							/* lw $15,15*4($2) */
786
		MIPS32_MTC0(15,31,0),							/* move $15 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
787
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),		/* $15 = MIPS32_PRACC_STACK */
788
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
789
790
		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
791
		MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
Spencer Oliver's avatar
Spencer Oliver committed
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
		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) */
822
		MIPS32_MTC0(2,12,0),							/* move $2 to status */
Spencer Oliver's avatar
Spencer Oliver committed
823
		MIPS32_LW(2,33*4,1),							/* lw $2,33*4($1) */
824
		MIPS32_MTLO(2),									/* move $2 to lo */
Spencer Oliver's avatar
Spencer Oliver committed
825
		MIPS32_LW(2,34*4,1),							/* lw $2,34*4($1) */
826
		MIPS32_MTHI(2),									/* move $2 to hi */
Spencer Oliver's avatar
Spencer Oliver committed
827
		MIPS32_LW(2,35*4,1),							/* lw $2,35*4($1) */
828
		MIPS32_MTC0(2,8,0),								/* move $2 to badvaddr */
Spencer Oliver's avatar
Spencer Oliver committed
829
		MIPS32_LW(2,36*4,1),							/* lw $2,36*4($1) */
830
		MIPS32_MTC0(2,13,0),							/* move $2 to cause*/
Spencer Oliver's avatar
Spencer Oliver committed
831
		MIPS32_LW(2,37*4,1),							/* lw $2,37*4($1) */
832
		MIPS32_MTC0(2,24,0),							/* move $2 to depc (pc) */
833

Spencer Oliver's avatar
Spencer Oliver committed
834
835
		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
836
		MIPS32_B(NEG16(53)),							/* b start */
837
		MIPS32_MFC0(15,31,0),							/* move COP0 DeSave to $15 */
ntfreak's avatar
ntfreak committed
838
	};
839

ntfreak's avatar
ntfreak committed
840
	int retval;
841

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

ntfreak's avatar
ntfreak committed
845
846
847
	return retval;
}

848
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
ntfreak's avatar
ntfreak committed
849
{
850
	static const uint32_t code[] = {
ntfreak's avatar
ntfreak committed
851
852
														/* start: */
		MIPS32_MTC0(2,31,0),							/* move $2 to COP0 DeSave */
Spencer Oliver's avatar
Spencer Oliver committed
853
		MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),	/* $2 = MIPS32_PRACC_PARAM_OUT */
ntfreak's avatar
ntfreak committed
854
855
		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
856
857
		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
858
859
		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
860
		MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),		/* $15 = MIPS32_PRACC_STACK */
ntfreak's avatar
ntfreak committed
861
		MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
Spencer Oliver's avatar
Spencer Oliver committed
862
863
864
		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
865