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