John McCarthy <jgmcc@magma.ca> pic32mx flash fixups and speedups
[fw/openocd] / src / target / mips32_pracc.c
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  ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27 #include "log.h"
28 #include "mips32.h"
29 #include "mips32_pracc.h"
30
31 typedef struct {
32         u32 *local_iparam;
33         int num_iparam;
34         u32 *local_oparam;
35         int num_oparam;
36         u32 *code;
37         int code_len;
38         u32 stack[32];
39         int stack_offset;
40         mips_ejtag_t *ejtag_info;
41 } mips32_pracc_context;
42
43 static int wait_for_pracc_rw(mips_ejtag_t *ejtag_info, u32 *ctrl)
44 {
45         u32 ejtag_ctrl;
46         
47         while (1) 
48         {
49                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
50                 ejtag_ctrl = ejtag_info->ejtag_ctrl;
51                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
52                 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
53                         break;
54                 LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
55                 return ERROR_JTAG_DEVICE_ERROR;
56         }
57         
58         *ctrl = ejtag_ctrl;
59         return ERROR_OK;
60 }
61
62 static int mips32_pracc_exec_read(mips32_pracc_context *ctx, u32 address)
63 {
64         mips_ejtag_t *ejtag_info = ctx->ejtag_info;
65         int offset;
66         u32 ejtag_ctrl, data;
67
68         if ((address >= MIPS32_PRACC_PARAM_IN)
69                 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
70         {
71                 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
72                 data = ctx->local_iparam[offset];
73         }
74         else if ((address >= MIPS32_PRACC_PARAM_OUT)
75                 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
76         {
77                 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
78                 data = ctx->local_oparam[offset];
79         }
80         else if ((address >= MIPS32_PRACC_TEXT)
81                 && (address <= MIPS32_PRACC_TEXT + ctx->code_len*4))
82         {
83                 offset = (address - MIPS32_PRACC_TEXT) / 4;
84                 data = ctx->code[offset];
85         }
86         else if (address == MIPS32_PRACC_STACK)
87         {
88                 /* save to our debug stack */
89                 data = ctx->stack[--ctx->stack_offset];
90         }
91         else
92         {
93                 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
94                  * to start of debug vector */
95                 
96                 data = 0;
97                 LOG_ERROR("Error reading unexpected address");
98                 return ERROR_JTAG_DEVICE_ERROR;
99         }
100         
101         /* Send the data out */
102         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
103         mips_ejtag_drscan_32(ctx->ejtag_info, &data);
104
105         /* Clear the access pending bit (let the processor eat!) */
106         ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
107         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
108         mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
109         
110         return ERROR_OK;
111 }
112
113 static int mips32_pracc_exec_write(mips32_pracc_context *ctx, u32 address)
114 {
115         u32 ejtag_ctrl,data;
116         int offset;
117         mips_ejtag_t *ejtag_info = ctx->ejtag_info;
118         
119         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
120         mips_ejtag_drscan_32(ctx->ejtag_info, &data);
121         
122         /* Clear access pending bit */
123         ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
124         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
125         mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
126         
127         if ((address >= MIPS32_PRACC_PARAM_IN)
128                 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
129         {
130                 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
131                 ctx->local_iparam[offset] = data;
132         }
133         else if ((address >= MIPS32_PRACC_PARAM_OUT )
134                 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
135         {
136                 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
137                 ctx->local_oparam[offset] = data;
138         }
139         else if (address == MIPS32_PRACC_STACK)
140         {
141                 /* save data onto our stack */
142                 ctx->stack[ctx->stack_offset++] = data;
143         }
144         else
145         {
146                 LOG_ERROR("Error writing unexpected address");
147                 return ERROR_JTAG_DEVICE_ERROR;
148         }
149         
150         return ERROR_OK;
151 }
152
153 int mips32_pracc_exec( mips_ejtag_t *ejtag_info, int code_len, u32 *code, int num_param_in, u32 *param_in, int num_param_out, u32 *param_out, int cycle)
154 {
155         u32 ejtag_ctrl;
156         u32 address, data;
157         mips32_pracc_context ctx;
158         int retval;
159         int pass = 0;
160         
161         ctx.local_iparam = param_in;
162         ctx.local_oparam = param_out;
163         ctx.num_iparam = num_param_in;
164         ctx.num_oparam = num_param_out;
165         ctx.code = code;
166         ctx.code_len = code_len;
167         ctx.ejtag_info = ejtag_info;
168         ctx.stack_offset = 0;
169         
170         while (1)
171         {
172                 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
173                         return retval;
174                 
175                 address = data = 0;
176                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
177                 mips_ejtag_drscan_32(ejtag_info, &address);
178                 
179                 /* Check for read or write */
180                 if (ejtag_ctrl & EJTAG_CTRL_PRNW)
181                 {
182                         if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
183                                 return retval;
184                 }
185                 else
186                 {
187                         /* Check to see if its reading at the debug vector. The first pass through
188                          * the module is always read at the vector, so the first one we allow.  When
189                          * the second read from the vector occurs we are done and just exit. */
190                         if ((address == MIPS32_PRACC_TEXT) && (pass++))
191                         {
192                                 break;
193                         }
194                         
195                         if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
196                                 return retval;
197                 }
198                 
199                 if (cycle == 0)
200                         break;
201         }
202         
203         /* stack sanity check */
204         if (ctx.stack_offset != 0)
205         {
206                 LOG_DEBUG("Pracc Stack not zero");
207         }
208         
209         return ERROR_OK;
210 }
211
212 int mips32_pracc_read_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
213 {
214         switch (size)
215         {
216                 case 1:
217                         return mips32_pracc_read_mem8(ejtag_info, addr, count, (u8*)buf);
218                 case 2:
219                         return mips32_pracc_read_mem16(ejtag_info, addr, count, (u16*)buf);
220                 case 4:
221                         if(count==1)
222                                 return mips32_pracc_read_u32(ejtag_info, addr, (u32*)buf);
223                         else
224                                 return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf);
225         }
226         
227         return ERROR_OK;
228 }
229
230 int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
231 {       
232         u32 code[] = {
233                                                                                                                         /* start: */
234                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
235                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
236                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
237                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
238                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
239                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
240                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
241                         
242                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
243                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
244                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
245                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
246                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
247                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
248                 MIPS32_NOP,
249                                                                                                                         /* loop: */
250                 MIPS32_BEQ(0,10,9),                                                                     /* beq 0, $10, end */
251                 MIPS32_NOP,
252                 
253                 MIPS32_LW(8,0,9),                                                                       /* lw $8,0($9), Load $8 with the word @mem[$9] */
254                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
255                 
256                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
257                 MIPS32_ADDI(9,9,4),                                                             /* $1+=4 */
258                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
259                 
260                 MIPS32_NOP,
261                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
262                 MIPS32_NOP,
263                                                                                                                         /* end: */
264                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
265                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
266                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
267                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
268                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
269                 MIPS32_NOP,
270                 MIPS32_B(NEG16(31)),                                                            /* b start */
271                 MIPS32_NOP,
272         };
273         
274         int retval = ERROR_OK;
275         int blocksize;
276         int bytesread;
277         u32 param_in[2];
278         
279         bytesread = 0;
280         
281         while (count > 0)
282         {       
283                 blocksize = count;
284                 if (count > 0x400)
285                         blocksize = 0x400;
286                 
287                 param_in[0] = addr;
288                 param_in[1] = blocksize;
289                 
290                 if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, 
291                         sizeof(param_in)/sizeof(param_in[0]), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
292                 {
293                         return retval;
294                 }
295                 
296                 count -= blocksize;
297                 addr += blocksize;
298                 bytesread += blocksize;
299         }
300
301         return retval;
302 }
303
304 int mips32_pracc_read_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf)
305 {
306         u32 code[] = {
307                                                                                                                         /* start: */
308                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
309                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
310                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
311                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
312                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
313
314                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
315                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
316                 MIPS32_LW(8,0,8),                                                                       /* $8=mem[$8]; read addr */
317                 MIPS32_LUI(9,UPPER16(MIPS32_PRACC_PARAM_OUT)),          /* $9=MIPS32_PRACC_PARAM_OUT */
318                 MIPS32_ORI(9,9,LOWER16(MIPS32_PRACC_PARAM_OUT)),
319
320                 MIPS32_LW(8,0,8),                                                                       /* lw $8,0($8), Load $8 with the word @mem[$8] */
321                 MIPS32_SW(8,0,9),                                                                       /* sw $8,0($9) */
322
323                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
324                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
325                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
326                 MIPS32_NOP,
327                 MIPS32_B(NEG16(17)),                                                            /* b start */
328                 MIPS32_NOP,
329         };
330
331         int retval = ERROR_OK;
332         u32 param_in[1];
333
334         param_in[0] = addr;
335
336         if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, 
337                 sizeof(param_in)/sizeof(param_in[0]), param_in, sizeof(u32), buf, 1)) != ERROR_OK)
338         {
339                 return retval;
340         }
341
342         return retval;
343 }
344
345 int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
346 {
347         u32 code[] = {
348                                                                                                                         /* start: */
349                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
350                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
351                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
352                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
353                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
354                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
355                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
356                         
357                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
358                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
359                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
360                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
361                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
362                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
363                 MIPS32_NOP,
364                                                                                                                         /* loop: */
365                 MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
366                 MIPS32_NOP,
367                 
368                 MIPS32_LHU(8,0,9),                                                                      /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
369                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
370                 
371                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
372                 MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
373                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
374                 MIPS32_NOP,
375                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
376                 MIPS32_NOP,
377
378                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
379                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
380                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
381                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
382                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
383                 MIPS32_NOP,
384                 MIPS32_B(NEG16(31)),                                                            /* b start */
385                 MIPS32_NOP,
386         };
387
388 //      /* TODO remove array */
389         u32 param_out[count];
390         int i;
391         
392 //      int retval;
393         int blocksize;
394         int bytesread;
395         u32 param_in[2];
396         
397         bytesread = 0;
398         
399         //while (count > 0)
400         {       
401                 blocksize = count;
402                 if (count > 0x400)
403                         blocksize = 0x400;
404                 
405                 param_in[0] = addr;
406                 param_in[1] = blocksize;
407                 
408                 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
409                         sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
410                 
411 //              count -= blocksize;
412 //              addr += blocksize;
413 //              bytesread += blocksize;
414         }
415         
416         for (i = 0; i < count; i++)
417         {
418                 buf[i] = param_out[i];
419         }
420         
421         return ERROR_OK;
422 }
423
424 int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
425 {
426         u32 code[] = {
427                                                                                                                         /* start: */
428                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
429                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
430                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
431                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
432                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
433                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
434                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
435                         
436                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
437                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
438                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
439                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
440                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
441                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
442                 MIPS32_NOP,
443                                                                                                                         /* loop: */
444                 MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
445                 MIPS32_NOP,
446                 
447                 MIPS32_LBU(8,0,9),                                                                      /* lw $8,0($9), Load t4 with the byte @mem[t1] */
448                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
449                 
450                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
451                 MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
452                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
453                 MIPS32_NOP,
454                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
455                 MIPS32_NOP,
456                                                                                                                         /* end: */
457                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
458                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
459                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
460                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
461                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
462                 MIPS32_NOP,
463                 MIPS32_B(NEG16(31)),                                                            /* b start */
464                 MIPS32_NOP,
465         };
466         
467 //      /* TODO remove array */
468         u32 param_out[count];
469         int i;
470         
471 //      int retval;
472         int blocksize;
473         int bytesread;
474         u32 param_in[2];
475         
476         bytesread = 0;
477         
478 //      while (count > 0)
479         {       
480                 blocksize = count;
481                 if (count > 0x400)
482                         blocksize = 0x400;
483                 
484                 param_in[0] = addr;
485                 param_in[1] = blocksize;
486                 
487                 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
488                         sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
489                 
490 //              count -= blocksize;
491 //              addr += blocksize;
492 //              bytesread += blocksize;
493         }
494         
495         for (i = 0; i < count; i++)
496         {
497                 buf[i] = param_out[i];
498         }
499
500         return ERROR_OK;
501 }
502
503 int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
504 {
505         switch (size)
506         {
507                 case 1:
508                         return mips32_pracc_write_mem8(ejtag_info, addr, count, (u8*)buf);
509                 case 2:
510                         return mips32_pracc_write_mem16(ejtag_info, addr, count,(u16*)buf);
511                 case 4:
512                         if(count==1)
513                                 return mips32_pracc_write_u32(ejtag_info, addr, (u32*)buf);
514                         else
515                                 return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf);
516         }
517         
518         return ERROR_OK;
519 }
520
521 int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
522 {
523         u32 code[] = {
524                                                                                                                         /* start: */
525                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
526                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
527                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
528                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
529                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
530                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
531                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
532                 
533                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
534                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
535                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
536                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
537                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
538                 MIPS32_NOP,
539                                                                                                                         /* loop: */
540                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
541                 MIPS32_NOP,
542                 
543                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
544                 MIPS32_SW(11,0,9),                                                                      /* sw $11,0($9) */
545                 
546                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
547                 MIPS32_ADDI(9,9,4),                                                             /* $9+=4 */
548                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
549                 MIPS32_NOP,
550                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
551                 MIPS32_NOP,
552                                                                                                                         /* end: */
553                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
554                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
555                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
556                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
557                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
558                 MIPS32_NOP,
559                 MIPS32_B(NEG16(30)),                                                            /* b start */
560                 MIPS32_NOP,
561         };
562         
563         /* TODO remove array */
564         u32 param_in[count+2];
565         param_in[0] = addr;
566         param_in[1] = count;
567         
568         memcpy(&param_in[2], buf, count * sizeof(u32));
569         
570         mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
571                 sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1);
572
573         return ERROR_OK;
574 }
575
576 int mips32_pracc_write_u32(mips_ejtag_t *ejtag_info, u32 addr, u32 *buf)
577 {
578         u32 code[] = {
579                                                                                                                         /* start: */
580                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
581                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
582                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
583                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
584                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
585
586                 MIPS32_LUI(8,UPPER16((MIPS32_PRACC_PARAM_IN+4))),       /* $8 = MIPS32_PRACC_PARAM_IN+4 */
587                 MIPS32_ORI(8,8,LOWER16((MIPS32_PRACC_PARAM_IN+4))),
588                 MIPS32_LW(9,NEG16(4),8),                                                        /* Load write addr to $9 */
589
590                 MIPS32_LW(8,0,8),                                                                       /* lw $8,0($8), Load $8 with the word @mem[$8] */
591                 MIPS32_SW(8,0,9),                                                                       /* sw $8,0($9) */
592
593                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
594                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
595                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
596                 MIPS32_NOP,
597                 MIPS32_B(NEG16(15)),                                                            /* b start */
598                 MIPS32_NOP,
599         };
600
601         /* TODO remove array */
602         u32 param_in[1+1];
603         param_in[0] = addr;
604         param_in[1] = *buf;
605
606         mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
607                 sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1);
608
609         return ERROR_OK;
610 }
611
612 int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
613 {
614         u32 code[] = {
615                                                                                                                         /* start: */
616                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
617                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
618                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
619                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
620                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
621                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
622                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
623                 
624                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
625                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
626                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
627                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
628                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
629                 MIPS32_NOP,
630                                                                                                                         /* loop: */
631                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
632                 MIPS32_NOP,
633                 
634                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
635                 MIPS32_SH(11,0,9),                                                                      /* sh $11,0($9) */
636                 
637                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
638                 MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
639                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
640                 
641                 MIPS32_NOP,
642                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
643                 MIPS32_NOP,
644                                                                                                                         /* end: */
645                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
646                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
647                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
648                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
649                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
650                 MIPS32_NOP,
651                 MIPS32_B(NEG16(30)),                                                            /* b start */
652                 MIPS32_NOP,
653         };
654         
655         /* TODO remove array */
656         u32 param_in[count+2];
657         int i;
658         param_in[0] = addr;
659         param_in[1] = count;
660         
661         for (i = 0; i < count; i++)
662         {
663                 param_in[i+2] = buf[i];
664         }
665         
666         mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
667                 sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
668
669         return ERROR_OK;
670 }
671
672 int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
673 {
674         u32 code[] = {
675                                                                                                                         /* start: */
676                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
677                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
678                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
679                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
680                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
681                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
682                 MIPS32_SW(11,0,15),                                                             /* sw $11,($15) */
683                 
684                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
685                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
686                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
687                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
688                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
689                 MIPS32_NOP,
690                                                                                                                         /* loop: */
691                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
692                 MIPS32_NOP,
693                 
694                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
695                 MIPS32_SB(11,0,9),                                                                      /* sb $11,0($9) */
696                 
697                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
698                 MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
699                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
700                 
701                 MIPS32_NOP,
702                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
703                 MIPS32_NOP,
704                                                                                                                         /* end: */
705                 MIPS32_LW(11,0,15),                                                             /* lw $11,($15) */
706                 MIPS32_LW(10,0,15),                                                             /* lw $10,($15) */
707                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
708                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
709                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
710                 MIPS32_NOP,
711                 MIPS32_B(NEG16(30)),                                                            /* b start */
712                 MIPS32_NOP,
713         };
714         
715         /* TODO remove array */
716         u32 param_in[count+2];
717         int retval;
718         int i;
719         param_in[0] = addr;
720         param_in[1] = count;
721         
722         for (i = 0; i < count; i++)
723         {
724                 param_in[i+2] = buf[i];
725         }
726         
727         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
728                 sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
729
730         return retval;
731 }
732
733 int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs)
734 {
735         u32 code[] = {
736                                                                                                                 /* start: */
737                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $2 = MIPS32_PRACC_PARAM_IN */
738                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
739                 MIPS32_LW(1,1*4,2),                                                     /* lw $1,1*4($2) */
740                 MIPS32_LW(15,15*4,2),                                                   /* lw $15,15*4($2) */
741                 MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
742                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
743                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
744                 MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
745                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $1 = MIPS32_PRACC_PARAM_IN */
746                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
747                 MIPS32_LW(3,3*4,1),                                                     /* lw $3,3*4($1) */
748                 MIPS32_LW(4,4*4,1),                                                     /* lw $4,4*4($1) */
749                 MIPS32_LW(5,5*4,1),                                                     /* lw $5,5*4($1) */
750                 MIPS32_LW(6,6*4,1),                                                     /* lw $6,6*4($1) */
751                 MIPS32_LW(7,7*4,1),                                                     /* lw $7,7*4($1) */
752                 MIPS32_LW(8,8*4,1),                                                     /* lw $8,8*4($1) */
753                 MIPS32_LW(9,9*4,1),                                                     /* lw $9,9*4($1) */
754                 MIPS32_LW(10,10*4,1),                                                   /* lw $10,10*4($1) */
755                 MIPS32_LW(11,11*4,1),                                                   /* lw $11,11*4($1) */
756                 MIPS32_LW(12,12*4,1),                                                   /* lw $12,12*4($1) */
757                 MIPS32_LW(13,13*4,1),                                                   /* lw $13,13*4($1) */
758                 MIPS32_LW(14,14*4,1),                                                   /* lw $14,14*4($1) */
759                 MIPS32_LW(16,16*4,1),                                                   /* lw $16,16*4($1) */
760                 MIPS32_LW(17,17*4,1),                                                   /* lw $17,17*4($1) */
761                 MIPS32_LW(18,18*4,1),                                                   /* lw $18,18*4($1) */
762                 MIPS32_LW(19,19*4,1),                                                   /* lw $19,19*4($1) */
763                 MIPS32_LW(20,20*4,1),                                                   /* lw $20,20*4($1) */
764                 MIPS32_LW(21,21*4,1),                                                   /* lw $21,21*4($1) */
765                 MIPS32_LW(22,22*4,1),                                                   /* lw $22,22*4($1) */
766                 MIPS32_LW(23,23*4,1),                                                   /* lw $23,23*4($1) */
767                 MIPS32_LW(24,24*4,1),                                                   /* lw $24,24*4($1) */
768                 MIPS32_LW(25,25*4,1),                                                   /* lw $25,25*4($1) */
769                 MIPS32_LW(26,26*4,1),                                                   /* lw $26,26*4($1) */
770                 MIPS32_LW(27,27*4,1),                                                   /* lw $27,27*4($1) */
771                 MIPS32_LW(28,28*4,1),                                                   /* lw $28,28*4($1) */
772                 MIPS32_LW(29,29*4,1),                                                   /* lw $29,29*4($1) */
773                 MIPS32_LW(30,30*4,1),                                                   /* lw $30,30*4($1) */
774                 MIPS32_LW(31,31*4,1),                                                   /* lw $31,31*4($1) */
775                 
776                 MIPS32_LW(2,32*4,1),                                                    /* lw $2,32*4($1) */
777                 MIPS32_MTC0(2,12,0),                                                    /* move $2 to status */
778                 MIPS32_LW(2,33*4,1),                                                    /* lw $2,33*4($1) */
779                 MIPS32_MTLO(2),                                                                 /* move $2 to lo */
780                 MIPS32_LW(2,34*4,1),                                                    /* lw $2,34*4($1) */
781                 MIPS32_MTHI(2),                                                                 /* move $2 to hi */
782                 MIPS32_LW(2,35*4,1),                                                    /* lw $2,35*4($1) */
783                 MIPS32_MTC0(2,8,0),                                                             /* move $2 to badvaddr */
784                 MIPS32_LW(2,36*4,1),                                                    /* lw $2,36*4($1) */
785                 MIPS32_MTC0(2,13,0),                                                    /* move $2 to cause*/
786                 MIPS32_LW(2,37*4,1),                                                    /* lw $2,37*4($1) */
787                 MIPS32_MTC0(2,24,0),                                                    /* move $2 to pc */
788                 
789                 MIPS32_LW(2,2*4,1),                                                     /* lw $2,2*4($1) */
790                 MIPS32_LW(1,0,15),                                                              /* lw $1,($15) */
791                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
792                 MIPS32_NOP,
793                 MIPS32_B(NEG16(55)),                                                    /* b start */
794                 MIPS32_NOP,
795         };
796         
797         int retval;
798         
799         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
800                 38, regs, 0, NULL, 1);
801         
802         return retval;
803 }
804
805 int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs)
806 {
807         u32 code[] = {
808                                                                                                                 /* start: */
809                 MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
810                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $2 = MIPS32_PRACC_PARAM_OUT */
811                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
812                 MIPS32_SW(0,0*4,2),                                                             /* sw $0,0*4($2) */
813                 MIPS32_SW(1,1*4,2),                                                     /* sw $1,1*4($2) */
814                 MIPS32_SW(15,15*4,2),                                                   /* sw $15,15*4($2) */
815                 MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
816                 MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
817                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
818                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
819                 MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
820                 MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
821                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
822                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
823                 MIPS32_SW(2,2*4,1),                                                     /* sw $2,2*4($1) */
824                 MIPS32_SW(3,3*4,1),                                                     /* sw $3,3*4($1) */
825                 MIPS32_SW(4,4*4,1),                                                     /* sw $4,4*4($1) */
826                 MIPS32_SW(5,5*4,1),                                                     /* sw $5,5*4($1) */
827                 MIPS32_SW(6,6*4,1),                                                     /* sw $6,6*4($1) */
828                 MIPS32_SW(7,7*4,1),                                                     /* sw $7,7*4($1) */
829                 MIPS32_SW(8,8*4,1),                                                     /* sw $8,8*4($1) */
830                 MIPS32_SW(9,9*4,1),                                                     /* sw $9,9*4($1) */
831                 MIPS32_SW(10,10*4,1),                                                   /* sw $10,10*4($1) */
832                 MIPS32_SW(11,11*4,1),                                                   /* sw $11,11*4($1) */
833                 MIPS32_SW(12,12*4,1),                                                   /* sw $12,12*4($1) */
834                 MIPS32_SW(13,13*4,1),                                                   /* sw $13,13*4($1) */
835                 MIPS32_SW(14,14*4,1),                                                   /* sw $14,14*4($1) */
836                 MIPS32_SW(16,16*4,1),                                                   /* sw $16,16*4($1) */
837                 MIPS32_SW(17,17*4,1),                                                   /* sw $17,17*4($1) */
838                 MIPS32_SW(18,18*4,1),                                                   /* sw $18,18*4($1) */
839                 MIPS32_SW(19,19*4,1),                                                   /* sw $19,19*4($1) */
840                 MIPS32_SW(20,20*4,1),                                                   /* sw $20,20*4($1) */
841                 MIPS32_SW(21,21*4,1),                                                   /* sw $21,21*4($1) */
842                 MIPS32_SW(22,22*4,1),                                                   /* sw $22,22*4($1) */
843                 MIPS32_SW(23,23*4,1),                                                   /* sw $23,23*4($1) */
844                 MIPS32_SW(24,24*4,1),                                                   /* sw $24,24*4($1) */
845                 MIPS32_SW(25,25*4,1),                                                   /* sw $25,25*4($1) */
846                 MIPS32_SW(26,26*4,1),                                                   /* sw $26,26*4($1) */
847                 MIPS32_SW(27,27*4,1),                                                   /* sw $27,27*4($1) */
848                 MIPS32_SW(28,28*4,1),                                                   /* sw $28,28*4($1) */
849                 MIPS32_SW(29,29*4,1),                                                   /* sw $29,29*4($1) */
850                 MIPS32_SW(30,30*4,1),                                                   /* sw $30,30*4($1) */
851                 MIPS32_SW(31,31*4,1),                                                   /* sw $31,31*4($1) */
852                 
853                 MIPS32_MFC0(2,12,0),                                                    /* move status to $2 */
854                 MIPS32_SW(2,32*4,1),                                                    /* sw $2,32*4($1) */
855                 MIPS32_MFLO(2),                                                                 /* move lo to $2 */
856                 MIPS32_SW(2,33*4,1),                                                    /* sw $2,33*4($1) */
857                 MIPS32_MFHI(2),                                                                 /* move hi to $2 */
858                 MIPS32_SW(2,34*4,1),                                                    /* sw $2,34*4($1) */
859                 MIPS32_MFC0(2,8,0),                                                             /* move badvaddr to $2 */
860                 MIPS32_SW(2,35*4,1),                                                    /* sw $2,35*4($1) */
861                 MIPS32_MFC0(2,13,0),                                                    /* move cause to $2 */
862                 MIPS32_SW(2,36*4,1),                                                    /* sw $2,36*4($1) */
863                 MIPS32_MFC0(2,24,0),                                                    /* move pc to $2 */
864                 MIPS32_SW(2,37*4,1),                                                    /* sw $2,37*4($1) */
865                 
866                 MIPS32_LW(2,0,15),                                                              /* lw $2,($15) */
867                 MIPS32_LW(1,0,15),                                                              /* lw $1,($15) */
868                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
869                 MIPS32_NOP,
870                 MIPS32_B(NEG16(60)),                                                    /* b start */
871                 MIPS32_NOP,
872         };
873         
874         int retval;
875         
876         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
877                 0, NULL, 38, regs, 1);
878         
879         return retval;
880 }