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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)