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