Corrected waiting on PrAcc in wait_for_pracc_rw(). Added necessary check that PrAcc...
[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  *   Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com>          *
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  *   This program is distributed in the hope that it will be useful,       *
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
17  *   GNU General Public License for more details.                          *
18  *                                                                         *
19  *   You should have received a copy of the GNU General Public License     *
20  *   along with this program; if not, write to the                         *
21  *   Free Software Foundation, Inc.,                                       *
22  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
23  ***************************************************************************/
24
25 /*
26 This version has optimized assembly routines for 32 bit operations:
27 - read word
28 - write word
29 - write array of words
30
31 One thing to be aware of is that the MIPS32 cpu will execute the
32 instruction after a branch instruction (one delay slot).
33
34 For example:
35
36     LW $2, ($5 +10)
37     B foo
38     LW $1, ($2 +100)
39
40 The LW $1, ($2 +100) instruction is also executed. If this is
41 not wanted a NOP can be inserted:
42
43     LW $2, ($5 +10)
44     B foo
45     NOP
46     LW $1, ($2 +100)
47
48 or the code can be changed to:
49
50     B foo
51     LW $2, ($5 +10)
52     LW $1, ($2 +100)
53
54 The original code contained NOPs. I have removed these and moved
55 the branches.
56
57 I also moved the PRACC_STACK to 0xFF204000. This allows
58 the use of 16 bits offsets to get pointers to the input
59 and output area relative to the stack. Note that the stack
60 isn't really a stack (the stack pointer is not 'moving')
61 but a FIFO simulated in software.
62
63 These changes result in a 35% speed increase when programming an
64 external flash.
65
66 More improvement could be gained if the registers do no need
67 to be preserved but in that case the routines should be aware
68 OpenOCD is used as a flash programmer or as a debug tool.
69
70 Nico Coesel
71 */
72
73 #ifdef HAVE_CONFIG_H
74 #include "config.h"
75 #endif
76
77 #include <helper/time_support.h>
78
79 #include "mips32.h"
80 #include "mips32_pracc.h"
81
82 struct mips32_pracc_context
83 {
84         uint32_t *local_iparam;
85         int num_iparam;
86         uint32_t *local_oparam;
87         int num_oparam;
88         const uint32_t *code;
89         int code_len;
90         uint32_t stack[32];
91         int stack_offset;
92         struct mips_ejtag *ejtag_info;
93 };
94
95 static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info,
96                 uint32_t addr, int count, uint8_t *buf);
97 static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info,
98                 uint32_t addr, int count, uint16_t *buf);
99 static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info,
100                 uint32_t addr, int count, uint32_t *buf);
101 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info,
102                 uint32_t addr, uint32_t *buf);
103
104 static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info,
105                 uint32_t addr, int count, uint8_t *buf);
106 static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info,
107                 uint32_t addr, int count, uint16_t *buf);
108 static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info,
109                 uint32_t addr, int count, uint32_t *buf);
110 static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info,
111                 uint32_t addr, uint32_t *buf);
112
113 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
114 {
115         uint32_t ejtag_ctrl;
116         long long then = timeval_ms();
117         int timeout;
118
119         /* wait for the PrAcc to become "1" */
120         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
121         ejtag_ctrl = ejtag_info->ejtag_ctrl;
122
123         int retval;
124         if ((retval = jtag_execute_queue()) != ERROR_OK)
125         {
126                 LOG_ERROR("fastdata load failed");
127                 return retval;
128         }
129
130         while (1)
131         {
132                 retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
133                 if (retval != ERROR_OK)
134                         return retval;
135
136                 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
137                         break;
138
139                 if ( (timeout = timeval_ms()-then) > 1000 )
140                 {
141                         LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
142                         return ERROR_JTAG_DEVICE_ERROR;
143                 }
144         }
145
146         *ctrl = ejtag_ctrl;
147         return ERROR_OK;
148 }
149
150 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
151 {
152         struct mips_ejtag *ejtag_info = ctx->ejtag_info;
153         int offset;
154         uint32_t ejtag_ctrl, data;
155
156         if ((address >= MIPS32_PRACC_PARAM_IN)
157                 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
158         {
159                 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
160                 data = ctx->local_iparam[offset];
161         }
162         else if ((address >= MIPS32_PRACC_PARAM_OUT)
163                 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
164         {
165                 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
166                 data = ctx->local_oparam[offset];
167         }
168         else if ((address >= MIPS32_PRACC_TEXT)
169                 && (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4))
170         {
171                 offset = (address - MIPS32_PRACC_TEXT) / 4;
172                 data = ctx->code[offset];
173         }
174         else if (address == MIPS32_PRACC_STACK)
175         {
176                 /* save to our debug stack */
177                 data = ctx->stack[--ctx->stack_offset];
178         }
179         else
180         {
181                 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
182                  * to start of debug vector */
183
184                 data = 0;
185                 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
186                 return ERROR_JTAG_DEVICE_ERROR;
187         }
188
189         /* Send the data out */
190         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
191         mips_ejtag_drscan_32(ctx->ejtag_info, &data);
192
193         /* Clear the access pending bit (let the processor eat!) */
194         ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
195         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
196         mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
197
198         return jtag_execute_queue();
199 }
200
201 static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
202 {
203         uint32_t ejtag_ctrl,data;
204         int offset;
205         struct mips_ejtag *ejtag_info = ctx->ejtag_info;
206         int retval;
207
208         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA);
209         retval = mips_ejtag_drscan_32(ctx->ejtag_info, &data);
210         if (retval != ERROR_OK)
211                 return retval;
212
213         /* Clear access pending bit */
214         ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
215         mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL);
216         mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
217
218         retval = jtag_execute_queue();
219         if (retval != ERROR_OK)
220                 return retval;
221
222         if ((address >= MIPS32_PRACC_PARAM_IN)
223                 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
224         {
225                 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
226                 ctx->local_iparam[offset] = data;
227         }
228         else if ((address >= MIPS32_PRACC_PARAM_OUT)
229                 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
230         {
231                 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
232                 ctx->local_oparam[offset] = data;
233         }
234         else if (address == MIPS32_PRACC_STACK)
235         {
236                 /* save data onto our stack */
237                 ctx->stack[ctx->stack_offset++] = data;
238         }
239         else
240         {
241                 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
242                 return ERROR_JTAG_DEVICE_ERROR;
243         }
244
245         return ERROR_OK;
246 }
247
248 int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code,
249                 int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
250 {
251         uint32_t ejtag_ctrl;
252         uint32_t address, data;
253         struct mips32_pracc_context ctx;
254         int retval;
255         int pass = 0;
256
257         ctx.local_iparam = param_in;
258         ctx.local_oparam = param_out;
259         ctx.num_iparam = num_param_in;
260         ctx.num_oparam = num_param_out;
261         ctx.code = code;
262         ctx.code_len = code_len;
263         ctx.ejtag_info = ejtag_info;
264         ctx.stack_offset = 0;
265
266         while (1)
267         {
268                 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
269                         return retval;
270
271                 address = data = 0;
272                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
273                 retval = mips_ejtag_drscan_32(ejtag_info, &address);
274                 if (retval != ERROR_OK)
275                         return retval;
276
277                 /* Check for read or write */
278                 if (ejtag_ctrl & EJTAG_CTRL_PRNW)
279                 {
280                         if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
281                                 return retval;
282                 }
283                 else
284                 {
285                         /* Check to see if its reading at the debug vector. The first pass through
286                          * the module is always read at the vector, so the first one we allow.  When
287                          * the second read from the vector occurs we are done and just exit. */
288                         if ((address == MIPS32_PRACC_TEXT) && (pass++))
289                         {
290                                 break;
291                         }
292
293                         if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
294                                 return retval;
295                 }
296
297                 if (cycle == 0)
298                         break;
299         }
300
301         /* stack sanity check */
302         if (ctx.stack_offset != 0)
303         {
304                 LOG_DEBUG("Pracc Stack not zero");
305         }
306
307         return ERROR_OK;
308 }
309
310 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
311 {
312         switch (size)
313         {
314                 case 1:
315                         return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
316                 case 2:
317                         return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
318                 case 4:
319                         if (count == 1)
320                                 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf);
321                         else
322                                 return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
323         }
324
325         return ERROR_OK;
326 }
327
328 static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
329 {
330         static const uint32_t code[] = {
331                                                                                                                         /* start: */
332                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
333                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
334                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
335                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
336                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
337                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
338                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
339
340                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
341                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
342                 MIPS32_LW(9,0,8),                                                                       /* $9 = mem[$8]; read addr */
343                 MIPS32_LW(10,4,8),                                                                      /* $10 = mem[$8 + 4]; read count */
344                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11 = MIPS32_PRACC_PARAM_OUT */
345                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
346                                                                                                                         /* loop: */
347                 MIPS32_BEQ(0,10,8),                                                                     /* beq 0, $10, end */
348                 MIPS32_NOP,
349
350                 MIPS32_LW(8,0,9),                                                                       /* lw $8,0($9), Load $8 with the word @mem[$9] */
351                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
352
353                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
354                 MIPS32_ADDI(9,9,4),                                                                     /* $1 += 4 */
355                 MIPS32_ADDI(11,11,4),                                                           /* $11 += 4 */
356
357                 MIPS32_B(NEG16(8)),                                                                     /* b loop */
358                 MIPS32_NOP,
359                                                                                                                         /* end: */
360                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
361                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
362                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
363                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
364                 MIPS32_B(NEG16(27)),                                                            /* b start */
365                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
366         };
367
368         int retval = ERROR_OK;
369         int blocksize;
370         int bytesread;
371         uint32_t param_in[2];
372
373         bytesread = 0;
374
375         while (count > 0)
376         {
377                 blocksize = count;
378                 if (count > 0x400)
379                         blocksize = 0x400;
380
381                 param_in[0] = addr;
382                 param_in[1] = blocksize;
383
384                 if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
385                         ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
386                 {
387                         return retval;
388                 }
389
390                 count -= blocksize;
391                 addr += blocksize;
392                 bytesread += blocksize;
393         }
394
395         return retval;
396 }
397
398 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
399 {
400         static const 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
407                 MIPS32_LW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN),15), /* load R8 @ param_in[0] = address */
408
409                 MIPS32_LW(8,0,8),                                                                       /* lw $8,0($8), Load $8 with the word @mem[$8] */
410                 MIPS32_SW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_OUT),15), /* store R8 @ param_out[0] */
411
412                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
413                 MIPS32_B(NEG16(9)),                                                                     /* b start */
414                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
415         };
416
417         int retval = ERROR_OK;
418         uint32_t param_in[1];
419
420         param_in[0] = addr;
421
422         if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
423                 ARRAY_SIZE(param_in), param_in, 1, buf, 1)) != ERROR_OK)
424         {
425                 return retval;
426         }
427
428         return retval;
429 }
430
431 static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
432 {
433         static const uint32_t code[] = {
434                                                                                                                         /* start: */
435                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
436                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
437                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
438                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
439                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
440                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
441                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
442
443                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
444                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
445                 MIPS32_LW(9,0,8),                                                                       /* $9 = mem[$8]; read addr */
446                 MIPS32_LW(10,4,8),                                                                      /* $10 = mem[$8 + 4]; read count */
447                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11 = MIPS32_PRACC_PARAM_OUT */
448                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
449                                                                                                                         /* loop: */
450                 MIPS32_BEQ(0,10,8),                                                                     /* beq 0, $10, end */
451                 MIPS32_NOP,
452
453                 MIPS32_LHU(8,0,9),                                                                      /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
454                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
455
456                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
457                 MIPS32_ADDI(9,9,2),                                                                     /* $9 += 2 */
458                 MIPS32_ADDI(11,11,4),                                                           /* $11 += 4 */
459                 MIPS32_B(NEG16(8)),                                                                     /* b loop */
460                 MIPS32_NOP,
461                                                                                                                         /* end: */
462                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
463                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
464                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
465                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
466                 MIPS32_B(NEG16(27)),                                                            /* b start */
467                 MIPS32_MFC0(15,30,0),                                                           /* move COP0 DeSave to $15 */
468         };
469
470         /* TODO remove array */
471         uint32_t *param_out = malloc(count * sizeof(uint32_t));
472         int i;
473
474         int retval = ERROR_OK;
475         int blocksize;
476         int bytesread;
477         uint32_t param_in[2];
478
479         bytesread = 0;
480
481         //while (count > 0)
482         {
483                 blocksize = count;
484                 if (count > 0x400)
485                         blocksize = 0x400;
486
487                 param_in[0] = addr;
488                 param_in[1] = blocksize;
489
490                 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
491                         ARRAY_SIZE(param_in), param_in, count, param_out, 1);
492
493 //              count -= blocksize;
494 //              addr += blocksize;
495 //              bytesread += blocksize;
496         }
497
498         for (i = 0; i < count; i++)
499         {
500                 buf[i] = param_out[i];
501         }
502
503         free(param_out);
504
505         return retval;
506 }
507
508 static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
509 {
510         static const uint32_t code[] = {
511                                                                                                                         /* start: */
512                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
513                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
514                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
515                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
516                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
517                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
518                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
519
520                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
521                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
522                 MIPS32_LW(9,0,8),                                                                       /* $9 = mem[$8]; read addr */
523                 MIPS32_LW(10,4,8),                                                                      /* $10 = mem[$8 + 4]; read count */
524                 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)),         /* $11 = MIPS32_PRACC_PARAM_OUT */
525                 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
526                                                                                                                         /* loop: */
527                 MIPS32_BEQ(0,10,8),                                                                     /* beq 0, $10, end */
528                 MIPS32_NOP,
529
530                 MIPS32_LBU(8,0,9),                                                                      /* lw $8,0($9), Load t4 with the byte @mem[t1] */
531                 MIPS32_SW(8,0,11),                                                                      /* sw $8,0($11) */
532
533                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
534                 MIPS32_ADDI(9,9,1),                                                                     /* $9 += 1 */
535                 MIPS32_ADDI(11,11,4),                                                           /* $11 += 4 */
536                 MIPS32_B(NEG16(8)),                                                                     /* b loop */
537                 MIPS32_NOP,
538                                                                                                                         /* end: */
539                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
540                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
541                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
542                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
543                 MIPS32_B(NEG16(27)),                                                            /* b start */
544                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
545         };
546
547         /* TODO remove array */
548         uint32_t *param_out = malloc(count * sizeof(uint32_t));
549         int i;
550
551         int retval = ERROR_OK;
552         int blocksize;
553         int bytesread;
554         uint32_t param_in[2];
555
556         bytesread = 0;
557
558 //      while (count > 0)
559         {
560                 blocksize = count;
561                 if (count > 0x400)
562                         blocksize = 0x400;
563
564                 param_in[0] = addr;
565                 param_in[1] = blocksize;
566
567                 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
568                         ARRAY_SIZE(param_in), param_in, count, param_out, 1);
569
570 //              count -= blocksize;
571 //              addr += blocksize;
572 //              bytesread += blocksize;
573         }
574
575         for (i = 0; i < count; i++)
576         {
577                 buf[i] = param_out[i];
578         }
579
580         free(param_out);
581
582         return retval;
583 }
584
585 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
586 {
587         switch (size)
588         {
589                 case 1:
590                         return mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
591                 case 2:
592                         return mips32_pracc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
593                 case 4:
594                         if (count == 1)
595                                 return mips32_pracc_write_u32(ejtag_info, addr, (uint32_t*)buf);
596                         else
597                                 return mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
598         }
599
600         return ERROR_OK;
601 }
602
603 static int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
604 {
605         static const uint32_t code[] = {
606                                                                                                                         /* start: */
607                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
608                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
609                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
610                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
611                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
612                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
613                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
614
615                 MIPS32_ADDI(8,15,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)),  /* $8= MIPS32_PRACC_PARAM_IN */
616                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
617                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
618                 MIPS32_ADDI(8,8,8),                                                                     /* $8 += 8 beginning of data */
619
620                                                                                                                         /* loop: */
621                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
622                 MIPS32_SW(11,0,9),                                                                      /* sw $11,0($9) */
623
624                 MIPS32_ADDI(9,9,4),                                                                     /* $9 += 4 */
625                 MIPS32_BNE(10,9,NEG16(4)),                                                      /* bne $10, $9, loop */
626                 MIPS32_ADDI(8,8,4),                                                                     /* $8 += 4 */
627
628                                                                                                                         /* end: */
629                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
630                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
631                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
632                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
633                 MIPS32_B(NEG16(21)),                                                            /* b start */
634                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
635         };
636
637         /* TODO remove array */
638         uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
639         param_in[0] = addr;
640         param_in[1] = addr + (count * sizeof(uint32_t));        /* last address */
641
642         memcpy(&param_in[2], buf, count * sizeof(uint32_t));
643
644         int retval;
645         retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
646                 count + 2, param_in, 0, NULL, 1);
647
648         free(param_in);
649
650         return retval;
651 }
652
653 static int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
654 {
655         static const uint32_t code[] = {
656                                                                                                                         /* start: */
657                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
658                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
659                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
660                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
661                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
662
663                 MIPS32_LW(8,NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15),   /* load R8 @ param_in[1] = data */
664                 MIPS32_LW(9,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15),               /* load R9 @ param_in[0] = address */
665
666                 MIPS32_SW(8,0,9),                                                                       /* sw $8,0($9) */
667
668                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
669                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
670                 MIPS32_B(NEG16(11)),                                                            /* b start */
671                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
672         };
673
674         /* TODO remove array */
675         uint32_t param_in[1 + 1];
676         param_in[0] = addr;
677         param_in[1] = *buf;
678
679         return mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
680                 ARRAY_SIZE(param_in), param_in, 0, NULL, 1);
681 }
682
683 static int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
684 {
685         static const uint32_t code[] = {
686                                                                                                                         /* start: */
687                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
688                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
689                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
690                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
691                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
692                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
693                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
694
695                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
696                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
697                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
698                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
699                 MIPS32_ADDI(8,8,8),                                                                     /* $8 += 8 */
700                                                                                                                         /* loop: */
701                 MIPS32_BEQ(0,10,8),                                                                     /* beq $0, $10, end */
702                 MIPS32_NOP,
703
704                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
705                 MIPS32_SH(11,0,9),                                                                      /* sh $11,0($9) */
706
707                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
708                 MIPS32_ADDI(9,9,2),                                                                     /* $9 += 2 */
709                 MIPS32_ADDI(8,8,4),                                                                     /* $8 += 4 */
710
711                 MIPS32_B(NEG16(8)),                                                                     /* b loop */
712                 MIPS32_NOP,
713                                                                                                                         /* end: */
714                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
715                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
716                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
717                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
718                 MIPS32_B(NEG16(26)),                                                            /* b start */
719                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
720         };
721
722         /* TODO remove array */
723         uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
724         int i;
725         param_in[0] = addr;
726         param_in[1] = count;
727
728         for (i = 0; i < count; i++)
729         {
730                 param_in[i + 2] = buf[i];
731         }
732
733         int retval;
734         retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
735                 count + 2, param_in, 0, NULL, 1);
736
737         free(param_in);
738
739         return retval;
740 }
741
742 static int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
743 {
744         static const uint32_t code[] = {
745                                                                                                                         /* start: */
746                 MIPS32_MTC0(15,31,0),                                                           /* move $15 to COP0 DeSave */
747                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),                     /* $15 = MIPS32_PRACC_STACK */
748                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
749                 MIPS32_SW(8,0,15),                                                                      /* sw $8,($15) */
750                 MIPS32_SW(9,0,15),                                                                      /* sw $9,($15) */
751                 MIPS32_SW(10,0,15),                                                                     /* sw $10,($15) */
752                 MIPS32_SW(11,0,15),                                                                     /* sw $11,($15) */
753
754                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)),           /* $8 = MIPS32_PRACC_PARAM_IN */
755                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
756                 MIPS32_LW(9,0,8),                                                                       /* Load write addr to $9 */
757                 MIPS32_LW(10,4,8),                                                                      /* Load write count to $10 */
758                 MIPS32_ADDI(8,8,8),                                                                     /* $8 += 8 */
759                                                                                                                         /* loop: */
760                 MIPS32_BEQ(0,10,8),                                                                     /* beq $0, $10, end */
761                 MIPS32_NOP,
762
763                 MIPS32_LW(11,0,8),                                                                      /* lw $11,0($8), Load $11 with the word @mem[$8] */
764                 MIPS32_SB(11,0,9),                                                                      /* sb $11,0($9) */
765
766                 MIPS32_ADDI(10,10,NEG16(1)),                                            /* $10-- */
767                 MIPS32_ADDI(9,9,1),                                                                     /* $9 += 1 */
768                 MIPS32_ADDI(8,8,4),                                                                     /* $8 += 4 */
769
770                 MIPS32_B(NEG16(8)),                                                                     /* b loop */
771                 MIPS32_NOP,
772                                                                                                                         /* end: */
773                 MIPS32_LW(11,0,15),                                                                     /* lw $11,($15) */
774                 MIPS32_LW(10,0,15),                                                                     /* lw $10,($15) */
775                 MIPS32_LW(9,0,15),                                                                      /* lw $9,($15) */
776                 MIPS32_LW(8,0,15),                                                                      /* lw $8,($15) */
777                 MIPS32_B(NEG16(26)),                                                            /* b start */
778                 MIPS32_MFC0(15,31,0),                                                           /* move COP0 DeSave to $15 */
779         };
780
781         /* TODO remove array */
782         uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
783         int retval;
784         int i;
785         param_in[0] = addr;
786         param_in[1] = count;
787
788         for (i = 0; i < count; i++)
789         {
790                 param_in[i + 2] = buf[i];
791         }
792
793         retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
794                 count + 2, param_in, 0, NULL, 1);
795
796         free(param_in);
797
798         return retval;
799 }
800
801 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
802 {
803         static const uint32_t code[] = {
804                                                                                                                 /* start: */
805                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $2 = MIPS32_PRACC_PARAM_IN */
806                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
807                 MIPS32_LW(1,1*4,2),                                                             /* lw $1,1*4($2) */
808                 MIPS32_LW(15,15*4,2),                                                   /* lw $15,15*4($2) */
809                 MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
810                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
811                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
812                 MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
813                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)),   /* $1 = MIPS32_PRACC_PARAM_IN */
814                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
815                 MIPS32_LW(3,3*4,1),                                                             /* lw $3,3*4($1) */
816                 MIPS32_LW(4,4*4,1),                                                             /* lw $4,4*4($1) */
817                 MIPS32_LW(5,5*4,1),                                                             /* lw $5,5*4($1) */
818                 MIPS32_LW(6,6*4,1),                                                             /* lw $6,6*4($1) */
819                 MIPS32_LW(7,7*4,1),                                                             /* lw $7,7*4($1) */
820                 MIPS32_LW(8,8*4,1),                                                             /* lw $8,8*4($1) */
821                 MIPS32_LW(9,9*4,1),                                                             /* lw $9,9*4($1) */
822                 MIPS32_LW(10,10*4,1),                                                   /* lw $10,10*4($1) */
823                 MIPS32_LW(11,11*4,1),                                                   /* lw $11,11*4($1) */
824                 MIPS32_LW(12,12*4,1),                                                   /* lw $12,12*4($1) */
825                 MIPS32_LW(13,13*4,1),                                                   /* lw $13,13*4($1) */
826                 MIPS32_LW(14,14*4,1),                                                   /* lw $14,14*4($1) */
827                 MIPS32_LW(16,16*4,1),                                                   /* lw $16,16*4($1) */
828                 MIPS32_LW(17,17*4,1),                                                   /* lw $17,17*4($1) */
829                 MIPS32_LW(18,18*4,1),                                                   /* lw $18,18*4($1) */
830                 MIPS32_LW(19,19*4,1),                                                   /* lw $19,19*4($1) */
831                 MIPS32_LW(20,20*4,1),                                                   /* lw $20,20*4($1) */
832                 MIPS32_LW(21,21*4,1),                                                   /* lw $21,21*4($1) */
833                 MIPS32_LW(22,22*4,1),                                                   /* lw $22,22*4($1) */
834                 MIPS32_LW(23,23*4,1),                                                   /* lw $23,23*4($1) */
835                 MIPS32_LW(24,24*4,1),                                                   /* lw $24,24*4($1) */
836                 MIPS32_LW(25,25*4,1),                                                   /* lw $25,25*4($1) */
837                 MIPS32_LW(26,26*4,1),                                                   /* lw $26,26*4($1) */
838                 MIPS32_LW(27,27*4,1),                                                   /* lw $27,27*4($1) */
839                 MIPS32_LW(28,28*4,1),                                                   /* lw $28,28*4($1) */
840                 MIPS32_LW(29,29*4,1),                                                   /* lw $29,29*4($1) */
841                 MIPS32_LW(30,30*4,1),                                                   /* lw $30,30*4($1) */
842                 MIPS32_LW(31,31*4,1),                                                   /* lw $31,31*4($1) */
843
844                 MIPS32_LW(2,32*4,1),                                                    /* lw $2,32*4($1) */
845                 MIPS32_MTC0(2,12,0),                                                    /* move $2 to status */
846                 MIPS32_LW(2,33*4,1),                                                    /* lw $2,33*4($1) */
847                 MIPS32_MTLO(2),                                                                 /* move $2 to lo */
848                 MIPS32_LW(2,34*4,1),                                                    /* lw $2,34*4($1) */
849                 MIPS32_MTHI(2),                                                                 /* move $2 to hi */
850                 MIPS32_LW(2,35*4,1),                                                    /* lw $2,35*4($1) */
851                 MIPS32_MTC0(2,8,0),                                                             /* move $2 to badvaddr */
852                 MIPS32_LW(2,36*4,1),                                                    /* lw $2,36*4($1) */
853                 MIPS32_MTC0(2,13,0),                                                    /* move $2 to cause*/
854                 MIPS32_LW(2,37*4,1),                                                    /* lw $2,37*4($1) */
855                 MIPS32_MTC0(2,24,0),                                                    /* move $2 to depc (pc) */
856
857                 MIPS32_LW(2,2*4,1),                                                             /* lw $2,2*4($1) */
858                 MIPS32_LW(1,0,15),                                                              /* lw $1,($15) */
859                 MIPS32_B(NEG16(53)),                                                    /* b start */
860                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
861         };
862
863         int retval;
864
865         retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
866                         MIPS32NUMCOREREGS, regs, 0, NULL, 1);
867
868         return retval;
869 }
870
871 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
872 {
873         static const uint32_t code[] = {
874                                                                                                                 /* start: */
875                 MIPS32_MTC0(2,31,0),                                                    /* move $2 to COP0 DeSave */
876                 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $2 = MIPS32_PRACC_PARAM_OUT */
877                 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
878                 MIPS32_SW(0,0*4,2),                                                             /* sw $0,0*4($2) */
879                 MIPS32_SW(1,1*4,2),                                                             /* sw $1,1*4($2) */
880                 MIPS32_SW(15,15*4,2),                                                   /* sw $15,15*4($2) */
881                 MIPS32_MFC0(2,31,0),                                                    /* move COP0 DeSave to $2 */
882                 MIPS32_MTC0(15,31,0),                                                   /* move $15 to COP0 DeSave */
883                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)),             /* $15 = MIPS32_PRACC_STACK */
884                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
885                 MIPS32_SW(1,0,15),                                                              /* sw $1,($15) */
886                 MIPS32_SW(2,0,15),                                                              /* sw $2,($15) */
887                 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)),  /* $1 = MIPS32_PRACC_PARAM_OUT */
888                 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
889                 MIPS32_SW(2,2*4,1),                                                             /* sw $2,2*4($1) */
890                 MIPS32_SW(3,3*4,1),                                                             /* sw $3,3*4($1) */
891                 MIPS32_SW(4,4*4,1),                                                             /* sw $4,4*4($1) */
892                 MIPS32_SW(5,5*4,1),                                                             /* sw $5,5*4($1) */
893                 MIPS32_SW(6,6*4,1),                                                             /* sw $6,6*4($1) */
894                 MIPS32_SW(7,7*4,1),                                                             /* sw $7,7*4($1) */
895                 MIPS32_SW(8,8*4,1),                                                             /* sw $8,8*4($1) */
896                 MIPS32_SW(9,9*4,1),                                                             /* sw $9,9*4($1) */
897                 MIPS32_SW(10,10*4,1),                                                   /* sw $10,10*4($1) */
898                 MIPS32_SW(11,11*4,1),                                                   /* sw $11,11*4($1) */
899                 MIPS32_SW(12,12*4,1),                                                   /* sw $12,12*4($1) */
900                 MIPS32_SW(13,13*4,1),                                                   /* sw $13,13*4($1) */
901                 MIPS32_SW(14,14*4,1),                                                   /* sw $14,14*4($1) */
902                 MIPS32_SW(16,16*4,1),                                                   /* sw $16,16*4($1) */
903                 MIPS32_SW(17,17*4,1),                                                   /* sw $17,17*4($1) */
904                 MIPS32_SW(18,18*4,1),                                                   /* sw $18,18*4($1) */
905                 MIPS32_SW(19,19*4,1),                                                   /* sw $19,19*4($1) */
906                 MIPS32_SW(20,20*4,1),                                                   /* sw $20,20*4($1) */
907                 MIPS32_SW(21,21*4,1),                                                   /* sw $21,21*4($1) */
908                 MIPS32_SW(22,22*4,1),                                                   /* sw $22,22*4($1) */
909                 MIPS32_SW(23,23*4,1),                                                   /* sw $23,23*4($1) */
910                 MIPS32_SW(24,24*4,1),                                                   /* sw $24,24*4($1) */
911                 MIPS32_SW(25,25*4,1),                                                   /* sw $25,25*4($1) */
912                 MIPS32_SW(26,26*4,1),                                                   /* sw $26,26*4($1) */
913                 MIPS32_SW(27,27*4,1),                                                   /* sw $27,27*4($1) */
914                 MIPS32_SW(28,28*4,1),                                                   /* sw $28,28*4($1) */
915                 MIPS32_SW(29,29*4,1),                                                   /* sw $29,29*4($1) */
916                 MIPS32_SW(30,30*4,1),                                                   /* sw $30,30*4($1) */
917                 MIPS32_SW(31,31*4,1),                                                   /* sw $31,31*4($1) */
918
919                 MIPS32_MFC0(2,12,0),                                                    /* move status to $2 */
920                 MIPS32_SW(2,32*4,1),                                                    /* sw $2,32*4($1) */
921                 MIPS32_MFLO(2),                                                                 /* move lo to $2 */
922                 MIPS32_SW(2,33*4,1),                                                    /* sw $2,33*4($1) */
923                 MIPS32_MFHI(2),                                                                 /* move hi to $2 */
924                 MIPS32_SW(2,34*4,1),                                                    /* sw $2,34*4($1) */
925                 MIPS32_MFC0(2,8,0),                                                             /* move badvaddr to $2 */
926                 MIPS32_SW(2,35*4,1),                                                    /* sw $2,35*4($1) */
927                 MIPS32_MFC0(2,13,0),                                                    /* move cause to $2 */
928                 MIPS32_SW(2,36*4,1),                                                    /* sw $2,36*4($1) */
929                 MIPS32_MFC0(2,24,0),                                                    /* move depc (pc) to $2 */
930                 MIPS32_SW(2,37*4,1),                                                    /* sw $2,37*4($1) */
931
932                 MIPS32_LW(2,0,15),                                                              /* lw $2,($15) */
933                 MIPS32_LW(1,0,15),                                                              /* lw $1,($15) */
934                 MIPS32_B(NEG16(58)),                                                    /* b start */
935                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
936         };
937
938         int retval;
939
940         retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
941                 0, NULL, MIPS32NUMCOREREGS, regs, 1);
942
943         return retval;
944 }
945
946 /* fastdata upload/download requires an initialized working area
947  * to load the download code; it should not be called otherwise
948  * fetch order from the fastdata area
949  * 1. start addr
950  * 2. end addr
951  * 3. data ...
952  */
953 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
954                                                                 int write_t, uint32_t addr, int count, uint32_t *buf)
955 {
956         uint32_t handler_code[] = {
957                 /* caution when editing, table is modified below */
958                 /* r15 points to the start of this code */
959                 MIPS32_SW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15),
960                 MIPS32_SW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15),
961                 MIPS32_SW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15),
962                 MIPS32_SW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15),
963                 /* start of fastdata area in t0 */
964                 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
965                 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
966                 MIPS32_LW(9,0,8),                                                               /* start addr in t1 */
967                 MIPS32_LW(10,0,8),                                                              /* end addr to t2 */
968                                                                                                                 /* loop: */
969                 /* 8 */ MIPS32_LW(11,0,0),                                              /* lw t3,[t8 | r9] */
970                 /* 9 */ MIPS32_SW(11,0,0),                                              /* sw t3,[r9 | r8] */
971                 MIPS32_BNE(10,9,NEG16(3)),                                              /* bne $t2,t1,loop */
972                 MIPS32_ADDI(9,9,4),                                                             /* addi t1,t1,4 */
973
974                 MIPS32_LW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15),
975                 MIPS32_LW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15),
976                 MIPS32_LW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15),
977                 MIPS32_LW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15),
978
979                 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_TEXT)),
980                 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_TEXT)),
981                 MIPS32_JR(15),                                                                  /* jr start */
982                 MIPS32_MFC0(15,31,0),                                                   /* move COP0 DeSave to $15 */
983         };
984
985         uint32_t jmp_code[] = {
986                 MIPS32_MTC0(15,31,0),                   /* move $15 to COP0 DeSave */
987                 /* 1 */ MIPS32_LUI(15,0),               /* addr of working area added below */
988                 /* 2 */ MIPS32_ORI(15,15,0),    /* addr of working area added below */
989                 MIPS32_JR(15),                                  /* jump to ram program */
990                 MIPS32_NOP,
991         };
992
993         int retval, i;
994         uint32_t val, ejtag_ctrl, address;
995
996         if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
997                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
998
999         if (write_t)
1000         {
1001                 handler_code[8] = MIPS32_LW(11,0,8);    /* load data from probe at fastdata area */
1002                 handler_code[9] = MIPS32_SW(11,0,9);    /* store data to RAM @ r9 */
1003         }
1004         else
1005         {
1006                 handler_code[8] = MIPS32_LW(11,0,9);    /* load data from RAM @ r9 */
1007                 handler_code[9] = MIPS32_SW(11,0,8);    /* store data to probe at fastdata area */
1008         }
1009
1010         /* write program into RAM */
1011         if (write_t != ejtag_info->fast_access_save)
1012         {
1013                 mips32_pracc_write_mem32(ejtag_info, source->address, ARRAY_SIZE(handler_code), handler_code);
1014                 /* save previous operation to speed to any consecutive read/writes */
1015                 ejtag_info->fast_access_save = write_t;
1016         }
1017
1018         LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address);
1019
1020         jmp_code[1] |= UPPER16(source->address);
1021         jmp_code[2] |= LOWER16(source->address);
1022
1023         for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++)
1024         {
1025                 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1026                         return retval;
1027
1028                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
1029                 mips_ejtag_drscan_32(ejtag_info, &jmp_code[i]);
1030
1031                 /* Clear the access pending bit (let the processor eat!) */
1032                 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
1033                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
1034                 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
1035         }
1036
1037         if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1038                 return retval;
1039
1040         /* next fetch to dmseg should be in FASTDATA_AREA, check */
1041         address = 0;
1042         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1043         retval = mips_ejtag_drscan_32(ejtag_info, &address);
1044         if (retval != ERROR_OK)
1045                 return retval;
1046
1047         if (address != MIPS32_PRACC_FASTDATA_AREA)
1048                 return ERROR_FAIL;
1049
1050         /* wait PrAcc pending bit for FASTDATA write */
1051         if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1052                 return retval;
1053
1054         /* Send the load start address */
1055         val = addr;
1056         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1057         mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1058
1059         /* Send the load end address */
1060         val = addr + (count - 1) * 4;
1061         mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1062
1063         for (i = 0; i < count; i++)
1064         {
1065                 if ((retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++)) != ERROR_OK)
1066                         return retval;
1067         }
1068
1069         if ((retval = jtag_execute_queue()) != ERROR_OK)
1070         {
1071                 LOG_ERROR("fastdata load failed");
1072                 return retval;
1073         }
1074
1075         if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1076                 return retval;
1077
1078         address = 0;
1079         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
1080         retval = mips_ejtag_drscan_32(ejtag_info, &address);
1081         if (retval != ERROR_OK)
1082                 return retval;
1083
1084         if (address != MIPS32_PRACC_TEXT)
1085                 LOG_ERROR("mini program did not return to start");
1086
1087         return retval;
1088 }