John McCarthy <jgmcc@magma.ca> cleans up the usage of the
[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                         return mips32_pracc_read_mem32(ejtag_info, addr, count, (u32*)buf);
222         }
223         
224         return ERROR_OK;
225 }
226
227 int mips32_pracc_read_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
228 {       
229         u32 code[] = {
230                                                                                                                         /* start: */
231                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
232                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
233                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
234                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
235                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
236                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
237                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
238                         
239                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
240                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
241                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
242                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
243                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
244                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
245                 MIPS32_NOP,
246                                                                                                                         /* loop: */
247                 MIPS32_BEQ(0,10,9),                                                                     /* beq 0, $10, end */
248                 MIPS32_NOP,
249                 
250                 MIPS32_LW(12,0,9),                                                                      /* lw $12,0($9), Load $12 with the word @mem[$9] */
251                 MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
252                 
253                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
254                 MIPS32_ADDI(9,9,4),                                                             /* $1+=4 */
255                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
256                 
257                 MIPS32_NOP,
258                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
259                 MIPS32_NOP,
260                                                                                                                         /* end: */
261                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
262                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
263                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
264                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
265                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
266                 MIPS32_NOP,
267                 MIPS32_B(NEG16(31)),                                                            /* b start */
268                 MIPS32_NOP,
269         };
270         
271         int retval=ERROR_OK;
272         int blocksize;
273         int bytesread;
274         u32 param_in[2];
275         
276         bytesread = 0;
277         
278         while (count > 0)
279         {       
280                 blocksize = count;
281                 if (count > 0x400)
282                         blocksize = 0x400;
283                 
284                 param_in[0] = addr;
285                 param_in[1] = blocksize;
286                 
287                 if ((retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, 
288                         sizeof(param_in)/sizeof(param_in[0]), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
289                 {
290                         return retval;
291                 }
292                 
293                 count -= blocksize;
294                 addr += blocksize;
295                 bytesread += blocksize;
296         }
297
298         return retval;
299 }
300
301 int mips32_pracc_read_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
302 {
303         u32 code[] = {
304                                                                                                                         /* start: */
305                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
306                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
307                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
308                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
309                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
310                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
311                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
312                         
313                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
314                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
315                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
316                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
317                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
318                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
319                 MIPS32_NOP,
320                                                                                                                         /* loop: */
321                 MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
322                 MIPS32_NOP,
323                 
324                 MIPS32_LHU(12,0,9),                                                             /* lw $12,0($9), Load $12 with the halfword @mem[$9] */
325                 MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
326                 
327                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
328                 MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
329                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
330                 MIPS32_NOP,
331                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
332                 MIPS32_NOP,
333
334                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
335                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
336                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
337                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
338                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
339                 MIPS32_NOP,
340                 MIPS32_B(NEG16(31)),                                                            /* b start */
341                 MIPS32_NOP,
342         };
343
344 //      /* TODO remove array */
345         u32 param_out[count];
346         int i;
347         
348 //      int retval;
349         int blocksize;
350         int bytesread;
351         u32 param_in[2];
352         
353         bytesread = 0;
354         
355         //while (count > 0)
356         {       
357                 blocksize = count;
358                 if (count > 0x400)
359                         blocksize = 0x400;
360                 
361                 param_in[0] = addr;
362                 param_in[1] = blocksize;
363                 
364                 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
365                         sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
366                 
367 //              count -= blocksize;
368 //              addr += blocksize;
369 //              bytesread += blocksize;
370         }
371         
372         for (i = 0; i < count; i++)
373         {
374                 buf[i] = param_out[i];
375         }
376         
377         return ERROR_OK;
378 }
379
380 int mips32_pracc_read_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
381 {
382         u32 code[] = {
383                                                                                                                         /* start: */
384                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
385                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
386                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
387                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
388                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
389                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
390                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
391                         
392                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
393                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
394                 MIPS32_LW(9,0,8),                                                                       /* $9=mem[$8]; read addr */
395                 MIPS32_LW(10,4,8),                                                                      /* $10=mem[$8+4]; read count */
396                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11=MIPS32_PRACC_PARAM_OUT */
397                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
398                 MIPS32_NOP,
399                                                                                                                         /* loop: */
400                 MIPS32_BEQ(0,10,9),                                                             /* beq 0, $10, end */
401                 MIPS32_NOP,
402                 
403                 MIPS32_LBU(12,0,9),                                                             /* lw $12,0($9), Load t4 with the byte @mem[t1] */
404                 MIPS32_SW(12,0,11),                                                             /* sw $12,0($11) */
405                 
406                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
407                 MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
408                 MIPS32_ADDI(11,11,4),                                                           /* $11+=4 */
409                 MIPS32_NOP,
410                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
411                 MIPS32_NOP,
412                                                                                                                         /* end: */
413                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
414                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
415                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
416                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
417                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
418                 MIPS32_NOP,
419                 MIPS32_B(NEG16(31)),                                                            /* b start */
420                 MIPS32_NOP,
421         };
422         
423 //      /* TODO remove array */
424         u32 param_out[count];
425         int i;
426         
427 //      int retval;
428         int blocksize;
429         int bytesread;
430         u32 param_in[2];
431         
432         bytesread = 0;
433         
434 //      while (count > 0)
435         {       
436                 blocksize = count;
437                 if (count > 0x400)
438                         blocksize = 0x400;
439                 
440                 param_in[0] = addr;
441                 param_in[1] = blocksize;
442                 
443                 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
444                         sizeof(param_in)/sizeof(param_in[0]), param_in, count, param_out, 1);
445                 
446 //              count -= blocksize;
447 //              addr += blocksize;
448 //              bytesread += blocksize;
449         }
450         
451         for (i = 0; i < count; i++)
452         {
453                 buf[i] = param_out[i];
454         }
455
456         return ERROR_OK;
457 }
458
459 int mips32_pracc_write_mem(mips_ejtag_t *ejtag_info, u32 addr, int size, int count, void *buf)
460 {
461         switch (size)
462         {
463                 case 1:
464                         return mips32_pracc_write_mem8(ejtag_info, addr, count, (u8*)buf);
465                 case 2:
466                         return mips32_pracc_write_mem16(ejtag_info, addr, count,(u16*)buf);
467                 case 4:
468                         return mips32_pracc_write_mem32(ejtag_info, addr, count, (u32*)buf);
469         }
470         
471         return ERROR_OK;
472 }
473
474 int mips32_pracc_write_mem32(mips_ejtag_t *ejtag_info, u32 addr, int count, u32 *buf)
475 {
476         u32 code[] = {
477                                                                                                                         /* start: */
478                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
479                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
480                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
481                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
482                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
483                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
484                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
485                 
486                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
487                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
488                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
489                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
490                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
491                 MIPS32_NOP,
492                                                                                                                         /* loop: */
493                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
494                 MIPS32_NOP,
495                 
496                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
497                 MIPS32_SW(11,0,9),                                                                      /* sw $11,0($9) */
498                 
499                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
500                 MIPS32_ADDI(9,9,4),                                                             /* $9+=4 */
501                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
502                 MIPS32_NOP,
503                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
504                 MIPS32_NOP,
505                                                                                                                         /* end: */
506                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
507                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
508                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
509                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
510                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
511                 MIPS32_NOP,
512                 MIPS32_B(NEG16(30)),                                                            /* b start */
513                 MIPS32_NOP,
514         };
515         
516         /* TODO remove array */
517         u32 param_in[count+2];
518         param_in[0] = addr;
519         param_in[1] = count;
520         
521         memcpy(&param_in[2], buf, count * sizeof(u32));
522         
523         mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
524                 sizeof(param_in)/sizeof(param_in[0]),param_in, 0, NULL, 1);
525
526         return ERROR_OK;
527 }
528
529 int mips32_pracc_write_mem16(mips_ejtag_t *ejtag_info, u32 addr, int count, u16 *buf)
530 {
531         u32 code[] = {
532                                                                                                                         /* start: */
533                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
534                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
535                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
536                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
537                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
538                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
539                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
540                 
541                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
542                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
543                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
544                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
545                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
546                 MIPS32_NOP,
547                                                                                                                         /* loop: */
548                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
549                 MIPS32_NOP,
550                 
551                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
552                 MIPS32_SH(11,0,9),                                                                      /* sh $11,0($9) */
553                 
554                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
555                 MIPS32_ADDI(9,9,2),                                                             /* $9+=2 */
556                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
557                 
558                 MIPS32_NOP,
559                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
560                 MIPS32_NOP,
561                                                                                                                         /* end: */
562                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
563                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
564                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
565                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
566                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
567                 MIPS32_NOP,
568                 MIPS32_B(NEG16(30)),                                                            /* b start */
569                 MIPS32_NOP,
570         };
571         
572         /* TODO remove array */
573         u32 param_in[count+2];
574         int i;
575         param_in[0] = addr;
576         param_in[1] = count;
577         
578         for (i = 0; i < count; i++)
579         {
580                 param_in[i+2] = buf[i];
581         }
582         
583         mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
584                 sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
585
586         return ERROR_OK;
587 }
588
589 int mips32_pracc_write_mem8(mips_ejtag_t *ejtag_info, u32 addr, int count, u8 *buf)
590 {
591         u32 code[] = {
592                                                                                                                         /* start: */
593                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
594                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
595                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
596                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
597                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
598                 MIPS32_SW(10,0,15),                                                             /* sw $10,($15) */
599                 MIPS32_SW(11,0,15),                                                             /* sw $10,($15) */
600                 
601                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
602                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
603                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
604                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
605                 MIPS32_ADDI(8,8,8),                                                             /* $8+=8 */
606                 MIPS32_NOP,
607                                                                                                                         /* loop: */
608                 MIPS32_BEQ(0,10,9),                                                                     /* beq $0, $10, end */
609                 MIPS32_NOP,
610                 
611                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
612                 MIPS32_SB(11,0,9),                                                                      /* sb $11,0($9) */
613                 
614                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
615                 MIPS32_ADDI(9,9,1),                                                             /* $9+=1 */
616                 MIPS32_ADDI(8,8,4),                                                             /* $8+=4 */
617                 
618                 MIPS32_NOP,
619                 MIPS32_B(NEG16(9)),                                                                     /* b loop */
620                 MIPS32_NOP,
621                                                                                                                         /* end: */
622                 MIPS32_LW(11,0,15),                                                             /* sw $11,($15) */
623                 MIPS32_LW(10,0,15),                                                             /* sw $10,($15) */
624                 MIPS32_LW(9,0,15),                                                                      /* sw $9,($15) */
625                 MIPS32_LW(8,0,15),                                                                      /* sw $8,($15) */
626                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
627                 MIPS32_NOP,
628                 MIPS32_B(NEG16(30)),                                                            /* b start */
629                 MIPS32_NOP,
630         };
631         
632         /* TODO remove array */
633         u32 param_in[count+2];
634         int retval;
635         int i;
636         param_in[0] = addr;
637         param_in[1] = count;
638         
639         for (i = 0; i < count; i++)
640         {
641                 param_in[i+2] = buf[i];
642         }
643         
644         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
645                 sizeof(param_in)/sizeof(param_in[0]), param_in, 0, NULL, 1);
646
647         return retval;
648 }
649
650 int mips32_pracc_write_regs(mips_ejtag_t *ejtag_info, u32 *regs)
651 {
652         /* TODO restore all core registers */
653         
654         u32 code[] = {
655                                                                                                                 /* start: */
656                 MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
657                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $2 = MIPS32_PRACC_PARAM_IN */
658                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
659                 /*MIPS32_LW(0,0*4,2),*/                                                 /* lw $0,0*4($2) */
660                 MIPS32_LW(1,1*4,2),                                                     /* lw $1,1*4($2) */
661                 MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
662                 
663                 MIPS32_MTC0(1,31,0),                                                    /* move $1 to COP0 DeSave */
664                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $1 = MIPS32_PRACC_PARAM_IN */
665                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
666                 MIPS32_LW(2,2*4,1),                                                     /* lw $2,2*4($1) */
667                 MIPS32_LW(3,3*4,1),                                                     /* lw $3,3*4($1) */
668                 MIPS32_LW(4,4*4,1),                                                     /* lw $4,4*4($1) */
669                 MIPS32_LW(5,5*4,1),                                                     /* lw $5,5*4($1) */
670                 MIPS32_LW(6,6*4,1),                                                     /* lw $6,6*4($1) */
671                 MIPS32_LW(7,7*4,1),                                                     /* lw $7,7*4($1) */
672                 MIPS32_LW(8,8*4,1),                                                     /* lw $8,8*4($1) */
673                 MIPS32_LW(9,9*4,1),                                                     /* lw $9,9*4($1) */
674                 MIPS32_LW(10,10*4,1),                                                   /* lw $10,10*4($1) */
675                 MIPS32_LW(11,11*4,1),                                                   /* lw $11,11*4($1) */
676                 MIPS32_LW(12,12*4,1),                                                   /* lw $12,12*4($1) */
677                 MIPS32_LW(13,13*4,1),                                                   /* lw $13,13*4($1) */
678                 MIPS32_LW(14,14*4,1),                                                   /* lw $14,14*4($1) */
679                 MIPS32_LW(15,15*4,1),                                                   /* lw $15,15*4($1) */
680                 MIPS32_LW(16,16*4,1),                                                   /* lw $16,16*4($1) */
681                 MIPS32_LW(17,17*4,1),                                                   /* lw $17,17*4($1) */
682                 MIPS32_LW(18,18*4,1),                                                   /* lw $18,18*4($1) */
683                 MIPS32_LW(19,19*4,1),                                                   /* lw $19,19*4($1) */
684                 MIPS32_LW(20,20*4,1),                                                   /* lw $20,20*4($1) */
685                 MIPS32_LW(21,21*4,1),                                                   /* lw $21,21*4($1) */
686                 MIPS32_LW(22,22*4,1),                                                   /* lw $22,22*4($1) */
687                 MIPS32_LW(23,23*4,1),                                                   /* lw $23,23*4($1) */
688                 MIPS32_LW(24,24*4,1),                                                   /* lw $24,24*4($1) */
689                 MIPS32_LW(25,25*4,1),                                                   /* lw $25,25*4($1) */
690                 MIPS32_LW(26,26*4,1),                                                   /* lw $26,26*4($1) */
691                 MIPS32_LW(27,27*4,1),                                                   /* lw $27,27*4($1) */
692                 MIPS32_LW(28,28*4,1),                                                   /* lw $28,28*4($1) */
693                 MIPS32_LW(29,29*4,1),                                                   /* lw $29,29*4($1) */
694                 MIPS32_LW(30,30*4,1),                                                   /* lw $30,30*4($1) */
695                 MIPS32_LW(31,31*4,1),                                                   /* lw $31,31*4($1) */
696                 
697                 MIPS32_MFC0(1,31,0),                                                    /* move COP0 DeSave to $1 */
698                 MIPS32_NOP,
699                 MIPS32_B(NEG16(41)),                                                    /* b start */
700                 MIPS32_NOP,
701         };
702         
703         int retval;
704         
705         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
706                 32, regs, 0, NULL, 1);
707         
708         return retval;
709 }
710
711 int mips32_pracc_read_regs(mips_ejtag_t *ejtag_info, u32 *regs)
712 {
713         u32 code[] = {
714                                                                                                                 /* start: */
715                 MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
716                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $2 = MIPS32_PRACC_PARAM_OUT */
717                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
718                 MIPS32_SW(0,0*4,2),                                                             /* sw $0,0*4($2) */
719                 MIPS32_SW(1,1*4,2),                                                     /* sw $1,1*4($2) */
720                 MIPS32_SW(15,15*4,2),                                                   /* sw $15,15*4($2) */
721                 MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
722                 MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
723                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),     /* $15 = MIPS32_PRACC_STACK */
724                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
725                 MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
726                 MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
727                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
728                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
729                 MIPS32_SW(2,2*4,1),                                                     /* sw $2,2*4($1) */
730                 MIPS32_SW(3,3*4,1),                                                     /* sw $3,3*4($1) */
731                 MIPS32_SW(4,4*4,1),                                                     /* sw $4,4*4($1) */
732                 MIPS32_SW(5,5*4,1),                                                     /* sw $5,5*4($1) */
733                 MIPS32_SW(6,6*4,1),                                                     /* sw $6,6*4($1) */
734                 MIPS32_SW(7,7*4,1),                                                     /* sw $7,7*4($1) */
735                 MIPS32_SW(8,8*4,1),                                                     /* sw $8,8*4($1) */
736                 MIPS32_SW(9,9*4,1),                                                     /* sw $9,9*4($1) */
737                 MIPS32_SW(10,10*4,1),                                                   /* sw $10,10*4($1) */
738                 MIPS32_SW(11,11*4,1),                                                   /* sw $11,11*4($1) */
739                 MIPS32_SW(12,12*4,1),                                                   /* sw $12,12*4($1) */
740                 MIPS32_SW(13,13*4,1),                                                   /* sw $13,13*4($1) */
741                 MIPS32_SW(14,14*4,1),                                                   /* sw $14,14*4($1) */
742                 MIPS32_SW(16,16*4,1),                                                   /* sw $16,16*4($1) */
743                 MIPS32_SW(17,17*4,1),                                                   /* sw $17,17*4($1) */
744                 MIPS32_SW(18,18*4,1),                                                   /* sw $18,18*4($1) */
745                 MIPS32_SW(19,19*4,1),                                                   /* sw $19,19*4($1) */
746                 MIPS32_SW(20,20*4,1),                                                   /* sw $20,20*4($1) */
747                 MIPS32_SW(21,21*4,1),                                                   /* sw $21,21*4($1) */
748                 MIPS32_SW(22,22*4,1),                                                   /* sw $22,22*4($1) */
749                 MIPS32_SW(23,23*4,1),                                                   /* sw $23,23*4($1) */
750                 MIPS32_SW(24,24*4,1),                                                   /* sw $24,24*4($1) */
751                 MIPS32_SW(25,25*4,1),                                                   /* sw $25,25*4($1) */
752                 MIPS32_SW(26,26*4,1),                                                   /* sw $26,26*4($1) */
753                 MIPS32_SW(27,27*4,1),                                                   /* sw $27,27*4($1) */
754                 MIPS32_SW(28,28*4,1),                                                   /* sw $28,28*4($1) */
755                 MIPS32_SW(29,29*4,1),                                                   /* sw $29,29*4($1) */
756                 MIPS32_SW(30,30*4,1),                                                   /* sw $30,30*4($1) */
757                 MIPS32_SW(31,31*4,1),                                                   /* sw $31,31*4($1) */
758                 
759                 MIPS32_MFC0(2,12,0),                                                    /* move status to $2 */
760                 MIPS32_SW(2,32*4,1),                                                    /* sw $2,32*4($1) */
761                 MIPS32_LO(2),                                                                   /* move lo to $2 */
762                 MIPS32_SW(2,33*4,1),                                                    /* sw $2,33*4($1) */
763                 MIPS32_HI(2),                                                                   /* move hi to $2 */
764                 MIPS32_SW(2,34*4,1),                                                    /* sw $2,34*4($1) */
765                 MIPS32_MFC0(2,8,0),                                                             /* move badvaddr to $2 */
766                 MIPS32_SW(2,35*4,1),                                                    /* sw $2,35*4($1) */
767                 MIPS32_MFC0(2,13,0),                                                    /* move cause to $2 */
768                 MIPS32_SW(2,36*4,1),                                                    /* sw $2,36*4($1) */
769                 MIPS32_MFC0(2,24,0),                                                    /* move pc to $2 */
770                 MIPS32_SW(2,37*4,1),                                                    /* sw $2,37*4($1) */
771                 
772                 MIPS32_LW(2,0,15),                                                              /* sw $2,($15) */
773                 MIPS32_LW(1,0,15),                                                              /* sw $1,($15) */
774                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
775                 MIPS32_NOP,
776                 MIPS32_B(NEG16(60)),                                                    /* b start */
777                 MIPS32_NOP,
778         };
779         
780         int retval;
781         
782         retval = mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
783                 0, NULL, 38, regs, 1);
784         
785         return retval;
786 }