target: further shrink Jim-awareness
[openocd.git] / src / target / mips32_pracc.c
blob604d34edbf2524d9183b69740fa6d85f00f1438e
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
24 This version has optimized assembly routines for 32 bit operations:
25 - read word
26 - write word
27 - write array of words
29 One thing to be aware of is that the MIPS32 cpu will execute the
30 instruction after a branch instruction (one delay slot).
32 For example:
35 LW $2, ($5 +10)
36 B foo
37 LW $1, ($2 +100)
39 The LW $1, ($2 +100) instruction is also executed. If this is
40 not wanted a NOP can be inserted:
42 LW $2, ($5 +10)
43 B foo
44 NOP
45 LW $1, ($2 +100)
47 or the code can be changed to:
49 B foo
50 LW $2, ($5 +10)
51 LW $1, ($2 +100)
53 The original code contained NOPs. I have removed these and moved
54 the branches.
56 I also moved the PRACC_STACK to 0xFF204000. This allows
57 the use of 16 bits offsets to get pointers to the input
58 and output area relative to the stack. Note that the stack
59 isn't really a stack (the stack pointer is not 'moving')
60 but a FIFO simulated in software.
62 These changes result in a 35% speed increase when programming an
63 external flash.
65 More improvement could be gained if the registers do no need
66 to be preserved but in that case the routines should be aware
67 OpenOCD is used as a flash programmer or as a debug tool.
69 Nico Coesel
73 #ifdef HAVE_CONFIG_H
74 #include "config.h"
75 #endif
77 #include "mips32.h"
78 #include "mips32_pracc.h"
80 struct mips32_pracc_context
82 uint32_t *local_iparam;
83 int num_iparam;
84 uint32_t *local_oparam;
85 int num_oparam;
86 const uint32_t *code;
87 int code_len;
88 uint32_t stack[32];
89 int stack_offset;
90 struct mips_ejtag *ejtag_info;
93 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
95 uint32_t ejtag_ctrl;
97 while (1)
99 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
100 ejtag_ctrl = ejtag_info->ejtag_ctrl;
101 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
102 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
103 break;
104 LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
105 return ERROR_JTAG_DEVICE_ERROR;
108 *ctrl = ejtag_ctrl;
109 return ERROR_OK;
112 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
114 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
115 int offset;
116 uint32_t ejtag_ctrl, data;
118 if ((address >= MIPS32_PRACC_PARAM_IN)
119 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
121 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
122 data = ctx->local_iparam[offset];
124 else if ((address >= MIPS32_PRACC_PARAM_OUT)
125 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
127 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
128 data = ctx->local_oparam[offset];
130 else if ((address >= MIPS32_PRACC_TEXT)
131 && (address <= MIPS32_PRACC_TEXT + ctx->code_len*4))
133 offset = (address - MIPS32_PRACC_TEXT) / 4;
134 data = ctx->code[offset];
136 else if (address == MIPS32_PRACC_STACK)
138 /* save to our debug stack */
139 data = ctx->stack[--ctx->stack_offset];
141 else
143 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
144 * to start of debug vector */
146 data = 0;
147 LOG_ERROR("Error reading unexpected address %8.8" PRIx32 "", address);
148 return ERROR_JTAG_DEVICE_ERROR;
151 /* Send the data out */
152 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
153 mips_ejtag_drscan_32(ctx->ejtag_info, &data);
155 /* Clear the access pending bit (let the processor eat!) */
157 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
158 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
159 mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
161 jtag_add_clocks(5);
162 jtag_execute_queue();
165 return ERROR_OK;
168 static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
170 uint32_t ejtag_ctrl,data;
171 int offset;
172 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
174 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
175 mips_ejtag_drscan_32(ctx->ejtag_info, &data);
177 /* Clear access pending bit */
178 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
179 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
180 mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
182 jtag_add_clocks(5);
183 jtag_execute_queue();
185 if ((address >= MIPS32_PRACC_PARAM_IN)
186 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
188 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
189 ctx->local_iparam[offset] = data;
191 else if ((address >= MIPS32_PRACC_PARAM_OUT)
192 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
194 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
195 ctx->local_oparam[offset] = data;
197 else if (address == MIPS32_PRACC_STACK)
199 /* save data onto our stack */
200 ctx->stack[ctx->stack_offset++] = data;
202 else
204 LOG_ERROR("Error writing unexpected address %8.8" PRIx32 "", address);
205 return ERROR_JTAG_DEVICE_ERROR;
208 return ERROR_OK;
211 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)
213 uint32_t ejtag_ctrl;
214 uint32_t address, data;
215 struct mips32_pracc_context ctx;
216 int retval;
217 int pass = 0;
219 ctx.local_iparam = param_in;
220 ctx.local_oparam = param_out;
221 ctx.num_iparam = num_param_in;
222 ctx.num_oparam = num_param_out;
223 ctx.code = code;
224 ctx.code_len = code_len;
225 ctx.ejtag_info = ejtag_info;
226 ctx.stack_offset = 0;
228 while (1)
230 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
231 return retval;
233 address = data = 0;
234 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
235 mips_ejtag_drscan_32(ejtag_info, &address);
237 // printf("Adres: %.8x\n", address);
239 /* Check for read or write */
240 if (ejtag_ctrl & EJTAG_CTRL_PRNW)
242 if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
243 return retval;
245 else
247 /* Check to see if its reading at the debug vector. The first pass through
248 * the module is always read at the vector, so the first one we allow. When
249 * the second read from the vector occurs we are done and just exit. */
250 if ((address == MIPS32_PRACC_TEXT) && (pass++))
252 break;
255 if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
256 return retval;
260 if (cycle == 0)
261 break;
264 /* stack sanity check */
265 if (ctx.stack_offset != 0)
267 LOG_DEBUG("Pracc Stack not zero");
270 return ERROR_OK;
273 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
275 switch (size)
277 case 1:
278 return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
279 case 2:
280 return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
281 case 4:
282 if (count == 1)
283 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf);
284 else
285 return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
288 return ERROR_OK;
291 int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
293 static const uint32_t code[] = {
294 /* start: */
295 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
296 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
297 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
298 MIPS32_SW(8,0,15), /* sw $8,($15) */
299 MIPS32_SW(9,0,15), /* sw $9,($15) */
300 MIPS32_SW(10,0,15), /* sw $10,($15) */
301 MIPS32_SW(11,0,15), /* sw $11,($15) */
303 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
304 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
305 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
306 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
307 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
308 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
309 MIPS32_NOP,
310 /* loop: */
311 MIPS32_BEQ(0,10,9), /* beq 0, $10, end */
312 MIPS32_NOP,
314 MIPS32_LW(8,0,9), /* lw $8,0($9), Load $8 with the word @mem[$9] */
315 MIPS32_SW(8,0,11), /* sw $8,0($11) */
317 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
318 MIPS32_ADDI(9,9,4), /* $1 += 4 */
319 MIPS32_ADDI(11,11,4), /* $11 += 4 */
321 MIPS32_NOP,
322 MIPS32_B(NEG16(9)), /* b loop */
323 MIPS32_NOP,
324 /* end: */
325 MIPS32_LW(11,0,15), /* lw $11,($15) */
326 MIPS32_LW(10,0,15), /* lw $10,($15) */
327 MIPS32_LW(9,0,15), /* lw $9,($15) */
328 MIPS32_LW(8,0,15), /* lw $8,($15) */
329 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
330 MIPS32_NOP,
331 MIPS32_B(NEG16(31)), /* b start */
332 MIPS32_NOP,
335 int retval = ERROR_OK;
336 int blocksize;
337 int bytesread;
338 uint32_t param_in[2];
340 bytesread = 0;
342 while (count > 0)
344 blocksize = count;
345 if (count > 0x400)
346 blocksize = 0x400;
348 param_in[0] = addr;
349 param_in[1] = blocksize;
351 if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
352 ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
354 return retval;
357 count -= blocksize;
358 addr += blocksize;
359 bytesread += blocksize;
362 return retval;
365 int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
367 static const uint32_t code[] = {
368 /* start: */
369 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
370 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
371 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
372 MIPS32_SW(8,0,15), /* sw $8,($15) */
374 MIPS32_LW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), //load R8 @ param_in[0] = address
376 MIPS32_LW(8,0,8), /* lw $8,0($8), Load $8 with the word @mem[$8] */
377 MIPS32_SW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_OUT),15), /* sw $8,0($9) */
379 MIPS32_LW(8,0,15), /* lw $8,($15) */
380 MIPS32_B(NEG16(9)), //was 17 /* b start */
381 MIPS32_MFC0(15,31,0), //this instruction will be executed (MIPS executes instruction after jump) /* move COP0 DeSave to $15 */
382 MIPS32_NOP,
385 int retval = ERROR_OK;
386 uint32_t param_in[1];
388 param_in[0] = addr;
390 if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
391 ARRAY_SIZE(param_in), param_in, sizeof(uint32_t), buf, 1)) != ERROR_OK)
393 return retval;
396 return retval;
399 int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
401 static const uint32_t code[] = {
402 /* start: */
403 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
404 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
405 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
406 MIPS32_SW(8,0,15), /* sw $8,($15) */
407 MIPS32_SW(9,0,15), /* sw $9,($15) */
408 MIPS32_SW(10,0,15), /* sw $10,($15) */
409 MIPS32_SW(11,0,15), /* sw $11,($15) */
411 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
412 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
413 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
414 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
415 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
416 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
417 MIPS32_NOP,
418 /* loop: */
419 MIPS32_BEQ(0,10,9), /* beq 0, $10, end */
420 MIPS32_NOP,
422 MIPS32_LHU(8,0,9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
423 MIPS32_SW(8,0,11), /* sw $8,0($11) */
425 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
426 MIPS32_ADDI(9,9,2), /* $9 += 2 */
427 MIPS32_ADDI(11,11,4), /* $11 += 4 */
428 MIPS32_NOP,
429 MIPS32_B(NEG16(9)), /* b loop */
430 MIPS32_NOP,
432 MIPS32_LW(11,0,15), /* lw $11,($15) */
433 MIPS32_LW(10,0,15), /* lw $10,($15) */
434 MIPS32_LW(9,0,15), /* lw $9,($15) */
435 MIPS32_LW(8,0,15), /* lw $8,($15) */
436 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
437 MIPS32_NOP,
438 MIPS32_B(NEG16(31)), /* b start */
439 MIPS32_NOP,
442 // /* TODO remove array */
443 uint32_t *param_out = malloc(count * sizeof(uint32_t));
444 int i;
446 // int retval;
447 int blocksize;
448 int bytesread;
449 uint32_t param_in[2];
451 bytesread = 0;
453 //while (count > 0)
455 blocksize = count;
456 if (count > 0x400)
457 blocksize = 0x400;
459 param_in[0] = addr;
460 param_in[1] = blocksize;
462 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
463 ARRAY_SIZE(param_in), param_in, count, param_out, 1);
465 // count -= blocksize;
466 // addr += blocksize;
467 // bytesread += blocksize;
470 for (i = 0; i < count; i++)
472 buf[i] = param_out[i];
475 free(param_out);
477 return ERROR_OK;
480 int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
482 static const uint32_t code[] = {
483 /* start: */
484 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
485 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
486 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
487 MIPS32_SW(8,0,15), /* sw $8,($15) */
488 MIPS32_SW(9,0,15), /* sw $9,($15) */
489 MIPS32_SW(10,0,15), /* sw $10,($15) */
490 MIPS32_SW(11,0,15), /* sw $11,($15) */
492 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
493 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
494 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
495 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
496 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
497 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
498 MIPS32_NOP,
499 /* loop: */
500 MIPS32_BEQ(0,10,9), /* beq 0, $10, end */
501 MIPS32_NOP,
503 MIPS32_LBU(8,0,9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
504 MIPS32_SW(8,0,11), /* sw $8,0($11) */
506 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
507 MIPS32_ADDI(9,9,1), /* $9 += 1 */
508 MIPS32_ADDI(11,11,4), /* $11 += 4 */
509 MIPS32_NOP,
510 MIPS32_B(NEG16(9)), /* b loop */
511 MIPS32_NOP,
512 /* end: */
513 MIPS32_LW(11,0,15), /* lw $11,($15) */
514 MIPS32_LW(10,0,15), /* lw $10,($15) */
515 MIPS32_LW(9,0,15), /* lw $9,($15) */
516 MIPS32_LW(8,0,15), /* lw $8,($15) */
517 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
518 MIPS32_NOP,
519 MIPS32_B(NEG16(31)), /* b start */
520 MIPS32_NOP,
523 // /* TODO remove array */
524 uint32_t *param_out = malloc(count * sizeof(uint32_t));
525 int i;
527 // int retval;
528 int blocksize;
529 int bytesread;
530 uint32_t param_in[2];
532 bytesread = 0;
534 // while (count > 0)
536 blocksize = count;
537 if (count > 0x400)
538 blocksize = 0x400;
540 param_in[0] = addr;
541 param_in[1] = blocksize;
543 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
544 ARRAY_SIZE(param_in), param_in, count, param_out, 1);
546 // count -= blocksize;
547 // addr += blocksize;
548 // bytesread += blocksize;
551 for (i = 0; i < count; i++)
553 buf[i] = param_out[i];
556 free(param_out);
558 return ERROR_OK;
561 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
563 switch (size)
565 case 1:
566 return mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
567 case 2:
568 return mips32_pracc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
569 case 4:
570 if (count == 1)
571 return mips32_pracc_write_u32(ejtag_info, addr, (uint32_t*)buf);
572 else
573 return mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
576 return ERROR_OK;
579 int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
582 //NC: use destination pointer as loop counter (last address is in $10)
583 static const uint32_t code[] = {
584 /* start: */
585 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
586 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
587 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
588 MIPS32_SW(8,0,15), /* sw $8,($15) */
589 MIPS32_SW(9,0,15), /* sw $9,($15) */
590 MIPS32_SW(10,0,15), /* sw $10,($15) */
591 MIPS32_SW(11,0,15), /* sw $11,($15) */
593 MIPS32_ADDI(8,15,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)), //$8= MIPS32_PRACC_PARAM_IN
594 MIPS32_LW(9,0,8), /* Load write addr to $9 */
595 MIPS32_LW(10,4,8), //last address /* Load write count to $10 */
596 MIPS32_ADDI(8,8,8), // $8 += 8 beginning of data
598 //loop:
599 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
600 MIPS32_SW(11,0,9), /* sw $11,0($9) */
602 MIPS32_ADDI(9,9,4), /* $9 += 4 */
603 MIPS32_BNE(10,9,NEG16(4)), //was 9 BNE $10, 9, loop /* b loop */
604 MIPS32_ADDI(8,8,4), //this instruction is part of the loop (one delay slot)! /* $8 += 4 */
605 /* end: */
606 MIPS32_LW(11,0,15), /* lw $11,($15) */
607 MIPS32_LW(10,0,15), /* lw $10,($15) */
608 MIPS32_LW(9,0,15), /* lw $9,($15) */
609 MIPS32_LW(8,0,15), /* lw $8,($15) */
610 MIPS32_B(NEG16(21)), //was 30 /* b start */
611 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
612 MIPS32_NOP, //this one will not be executed
615 /* TODO remove array */
616 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
617 param_in[0] = addr;
618 param_in[1] = addr + count * sizeof(uint32_t); //last address
620 memcpy(&param_in[2], buf, count * sizeof(uint32_t));
622 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
623 count + 2, param_in, 0, NULL, 1);
625 free(param_in);
627 return ERROR_OK;
630 int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
632 static const uint32_t code[] = {
633 /* start: */
634 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
635 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
636 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
637 MIPS32_SW(8,0,15), /* sw $8,($15) */
638 MIPS32_SW(9,0,15), /* sw $9,($15) */
640 MIPS32_LW(8,NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15), //load R8 @ param_in[1] = data
641 MIPS32_LW(9,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), //load R9 @ param_in[0] = address
643 MIPS32_SW(8,0,9), /* sw $8,0($9) */
645 MIPS32_LW(9,0,15), /* lw $9,($15) */
646 MIPS32_LW(8,0,15), /* lw $8,($15) */
647 MIPS32_B(NEG16(11)), /* b start */
648 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
649 MIPS32_NOP,
652 /* TODO remove array */
653 uint32_t param_in[1 + 1];
654 param_in[0] = addr;
655 param_in[1] = *buf;
657 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
658 ARRAY_SIZE(param_in),param_in, 0, NULL, 1);
660 return ERROR_OK;
663 int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
665 static const uint32_t code[] = {
666 /* start: */
667 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
668 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
669 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
670 MIPS32_SW(8,0,15), /* sw $8,($15) */
671 MIPS32_SW(9,0,15), /* sw $9,($15) */
672 MIPS32_SW(10,0,15), /* sw $10,($15) */
673 MIPS32_SW(11,0,15), /* sw $11,($15) */
675 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
676 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
677 MIPS32_LW(9,0,8), /* Load write addr to $9 */
678 MIPS32_LW(10,4,8), /* Load write count to $10 */
679 MIPS32_ADDI(8,8,8), /* $8 += 8 */
680 MIPS32_NOP,
681 /* loop: */
682 MIPS32_BEQ(0,10,9), /* beq $0, $10, end */
683 MIPS32_NOP,
685 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
686 MIPS32_SH(11,0,9), /* sh $11,0($9) */
688 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
689 MIPS32_ADDI(9,9,2), /* $9 += 2 */
690 MIPS32_ADDI(8,8,4), /* $8 += 4 */
692 MIPS32_NOP,
693 MIPS32_B(NEG16(9)), /* b loop */
694 MIPS32_NOP,
695 /* end: */
696 MIPS32_LW(11,0,15), /* lw $11,($15) */
697 MIPS32_LW(10,0,15), /* lw $10,($15) */
698 MIPS32_LW(9,0,15), /* lw $9,($15) */
699 MIPS32_LW(8,0,15), /* lw $8,($15) */
700 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
701 MIPS32_NOP,
702 MIPS32_B(NEG16(30)), /* b start */
703 MIPS32_NOP,
706 /* TODO remove array */
707 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
708 int i;
709 param_in[0] = addr;
710 param_in[1] = count;
712 for (i = 0; i < count; i++)
714 param_in[i + 2] = buf[i];
717 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
718 count + 2, param_in, 0, NULL, 1);
720 free(param_in);
722 return ERROR_OK;
725 int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
727 static const uint32_t code[] = {
728 /* start: */
729 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
730 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
731 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
732 MIPS32_SW(8,0,15), /* sw $8,($15) */
733 MIPS32_SW(9,0,15), /* sw $9,($15) */
734 MIPS32_SW(10,0,15), /* sw $10,($15) */
735 MIPS32_SW(11,0,15), /* sw $11,($15) */
737 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
738 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
739 MIPS32_LW(9,0,8), /* Load write addr to $9 */
740 MIPS32_LW(10,4,8), /* Load write count to $10 */
741 MIPS32_ADDI(8,8,8), /* $8 += 8 */
742 MIPS32_NOP,
743 /* loop: */
744 MIPS32_BEQ(0,10,9), /* beq $0, $10, end */
745 MIPS32_NOP,
747 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
748 MIPS32_SB(11,0,9), /* sb $11,0($9) */
750 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
751 MIPS32_ADDI(9,9,1), /* $9 += 1 */
752 MIPS32_ADDI(8,8,4), /* $8 += 4 */
754 MIPS32_NOP,
755 MIPS32_B(NEG16(9)), /* b loop */
756 MIPS32_NOP,
757 /* end: */
758 MIPS32_LW(11,0,15), /* lw $11,($15) */
759 MIPS32_LW(10,0,15), /* lw $10,($15) */
760 MIPS32_LW(9,0,15), /* lw $9,($15) */
761 MIPS32_LW(8,0,15), /* lw $8,($15) */
762 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
763 MIPS32_NOP,
764 MIPS32_B(NEG16(30)), /* b start */
765 MIPS32_NOP,
768 /* TODO remove array */
769 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
770 int retval;
771 int i;
772 param_in[0] = addr;
773 param_in[1] = count;
775 for (i = 0; i < count; i++)
777 param_in[i + 2] = buf[i];
780 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
781 count +2, param_in, 0, NULL, 1);
783 free(param_in);
785 return retval;
788 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
790 static const uint32_t code[] = {
791 /* start: */
792 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $2 = MIPS32_PRACC_PARAM_IN */
793 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
794 MIPS32_LW(1,1*4,2), /* lw $1,1*4($2) */
795 MIPS32_LW(15,15*4,2), /* lw $15,15*4($2) */
796 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
797 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
798 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
799 MIPS32_SW(1,0,15), /* sw $1,($15) */
800 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $1 = MIPS32_PRACC_PARAM_IN */
801 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
802 MIPS32_LW(3,3*4,1), /* lw $3,3*4($1) */
803 MIPS32_LW(4,4*4,1), /* lw $4,4*4($1) */
804 MIPS32_LW(5,5*4,1), /* lw $5,5*4($1) */
805 MIPS32_LW(6,6*4,1), /* lw $6,6*4($1) */
806 MIPS32_LW(7,7*4,1), /* lw $7,7*4($1) */
807 MIPS32_LW(8,8*4,1), /* lw $8,8*4($1) */
808 MIPS32_LW(9,9*4,1), /* lw $9,9*4($1) */
809 MIPS32_LW(10,10*4,1), /* lw $10,10*4($1) */
810 MIPS32_LW(11,11*4,1), /* lw $11,11*4($1) */
811 MIPS32_LW(12,12*4,1), /* lw $12,12*4($1) */
812 MIPS32_LW(13,13*4,1), /* lw $13,13*4($1) */
813 MIPS32_LW(14,14*4,1), /* lw $14,14*4($1) */
814 MIPS32_LW(16,16*4,1), /* lw $16,16*4($1) */
815 MIPS32_LW(17,17*4,1), /* lw $17,17*4($1) */
816 MIPS32_LW(18,18*4,1), /* lw $18,18*4($1) */
817 MIPS32_LW(19,19*4,1), /* lw $19,19*4($1) */
818 MIPS32_LW(20,20*4,1), /* lw $20,20*4($1) */
819 MIPS32_LW(21,21*4,1), /* lw $21,21*4($1) */
820 MIPS32_LW(22,22*4,1), /* lw $22,22*4($1) */
821 MIPS32_LW(23,23*4,1), /* lw $23,23*4($1) */
822 MIPS32_LW(24,24*4,1), /* lw $24,24*4($1) */
823 MIPS32_LW(25,25*4,1), /* lw $25,25*4($1) */
824 MIPS32_LW(26,26*4,1), /* lw $26,26*4($1) */
825 MIPS32_LW(27,27*4,1), /* lw $27,27*4($1) */
826 MIPS32_LW(28,28*4,1), /* lw $28,28*4($1) */
827 MIPS32_LW(29,29*4,1), /* lw $29,29*4($1) */
828 MIPS32_LW(30,30*4,1), /* lw $30,30*4($1) */
829 MIPS32_LW(31,31*4,1), /* lw $31,31*4($1) */
831 MIPS32_LW(2,32*4,1), /* lw $2,32*4($1) */
832 MIPS32_MTC0(2,12,0), /* move $2 to status */
833 MIPS32_LW(2,33*4,1), /* lw $2,33*4($1) */
834 MIPS32_MTLO(2), /* move $2 to lo */
835 MIPS32_LW(2,34*4,1), /* lw $2,34*4($1) */
836 MIPS32_MTHI(2), /* move $2 to hi */
837 MIPS32_LW(2,35*4,1), /* lw $2,35*4($1) */
838 MIPS32_MTC0(2,8,0), /* move $2 to badvaddr */
839 MIPS32_LW(2,36*4,1), /* lw $2,36*4($1) */
840 MIPS32_MTC0(2,13,0), /* move $2 to cause*/
841 MIPS32_LW(2,37*4,1), /* lw $2,37*4($1) */
842 MIPS32_MTC0(2,24,0), /* move $2 to pc */
844 MIPS32_LW(2,2*4,1), /* lw $2,2*4($1) */
845 MIPS32_LW(1,0,15), /* lw $1,($15) */
846 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
847 MIPS32_NOP,
848 MIPS32_B(NEG16(55)), /* b start */
849 MIPS32_NOP,
852 int retval;
854 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
855 38, regs, 0, NULL, 1);
857 return retval;
860 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
862 static const uint32_t code[] = {
863 /* start: */
864 MIPS32_MTC0(2,31,0), /* move $2 to COP0 DeSave */
865 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $2 = MIPS32_PRACC_PARAM_OUT */
866 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
867 MIPS32_SW(0,0*4,2), /* sw $0,0*4($2) */
868 MIPS32_SW(1,1*4,2), /* sw $1,1*4($2) */
869 MIPS32_SW(15,15*4,2), /* sw $15,15*4($2) */
870 MIPS32_MFC0(2,31,0), /* move COP0 DeSave to $2 */
871 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
872 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
873 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
874 MIPS32_SW(1,0,15), /* sw $1,($15) */
875 MIPS32_SW(2,0,15), /* sw $2,($15) */
876 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
877 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
878 MIPS32_SW(2,2*4,1), /* sw $2,2*4($1) */
879 MIPS32_SW(3,3*4,1), /* sw $3,3*4($1) */
880 MIPS32_SW(4,4*4,1), /* sw $4,4*4($1) */
881 MIPS32_SW(5,5*4,1), /* sw $5,5*4($1) */
882 MIPS32_SW(6,6*4,1), /* sw $6,6*4($1) */
883 MIPS32_SW(7,7*4,1), /* sw $7,7*4($1) */
884 MIPS32_SW(8,8*4,1), /* sw $8,8*4($1) */
885 MIPS32_SW(9,9*4,1), /* sw $9,9*4($1) */
886 MIPS32_SW(10,10*4,1), /* sw $10,10*4($1) */
887 MIPS32_SW(11,11*4,1), /* sw $11,11*4($1) */
888 MIPS32_SW(12,12*4,1), /* sw $12,12*4($1) */
889 MIPS32_SW(13,13*4,1), /* sw $13,13*4($1) */
890 MIPS32_SW(14,14*4,1), /* sw $14,14*4($1) */
891 MIPS32_SW(16,16*4,1), /* sw $16,16*4($1) */
892 MIPS32_SW(17,17*4,1), /* sw $17,17*4($1) */
893 MIPS32_SW(18,18*4,1), /* sw $18,18*4($1) */
894 MIPS32_SW(19,19*4,1), /* sw $19,19*4($1) */
895 MIPS32_SW(20,20*4,1), /* sw $20,20*4($1) */
896 MIPS32_SW(21,21*4,1), /* sw $21,21*4($1) */
897 MIPS32_SW(22,22*4,1), /* sw $22,22*4($1) */
898 MIPS32_SW(23,23*4,1), /* sw $23,23*4($1) */
899 MIPS32_SW(24,24*4,1), /* sw $24,24*4($1) */
900 MIPS32_SW(25,25*4,1), /* sw $25,25*4($1) */
901 MIPS32_SW(26,26*4,1), /* sw $26,26*4($1) */
902 MIPS32_SW(27,27*4,1), /* sw $27,27*4($1) */
903 MIPS32_SW(28,28*4,1), /* sw $28,28*4($1) */
904 MIPS32_SW(29,29*4,1), /* sw $29,29*4($1) */
905 MIPS32_SW(30,30*4,1), /* sw $30,30*4($1) */
906 MIPS32_SW(31,31*4,1), /* sw $31,31*4($1) */
908 MIPS32_MFC0(2,12,0), /* move status to $2 */
909 MIPS32_SW(2,32*4,1), /* sw $2,32*4($1) */
910 MIPS32_MFLO(2), /* move lo to $2 */
911 MIPS32_SW(2,33*4,1), /* sw $2,33*4($1) */
912 MIPS32_MFHI(2), /* move hi to $2 */
913 MIPS32_SW(2,34*4,1), /* sw $2,34*4($1) */
914 MIPS32_MFC0(2,8,0), /* move badvaddr to $2 */
915 MIPS32_SW(2,35*4,1), /* sw $2,35*4($1) */
916 MIPS32_MFC0(2,13,0), /* move cause to $2 */
917 MIPS32_SW(2,36*4,1), /* sw $2,36*4($1) */
918 MIPS32_MFC0(2,24,0), /* move pc to $2 */
919 MIPS32_SW(2,37*4,1), /* sw $2,37*4($1) */
921 MIPS32_LW(2,0,15), /* lw $2,($15) */
922 MIPS32_LW(1,0,15), /* lw $1,($15) */
923 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
924 MIPS32_NOP,
925 MIPS32_B(NEG16(60)), /* b start */
926 MIPS32_NOP,
929 int retval;
931 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
932 0, NULL, 38, regs, 1);
934 return retval;