1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
5 * Copyright (C) 2008 by David T.L. Wong *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
9 * Copyright (C) 2011 by Drasko DRASKOVIC *
10 * drasko.draskovic@gmail.com *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the *
24 * Free Software Foundation, Inc., *
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
26 ***************************************************************************/
29 * This version has optimized assembly routines for 32 bit operations:
32 * - write array of words
34 * One thing to be aware of is that the MIPS32 cpu will execute the
35 * instruction after a branch instruction (one delay slot).
42 * The LW $1, ($2 +100) instruction is also executed. If this is
43 * not wanted a NOP can be inserted:
50 * or the code can be changed to:
56 * The original code contained NOPs. I have removed these and moved
59 * I also moved the PRACC_STACK to 0xFF204000. This allows
60 * the use of 16 bits offsets to get pointers to the input
61 * and output area relative to the stack. Note that the stack
62 * isn't really a stack (the stack pointer is not 'moving')
63 * but a FIFO simulated in software.
65 * These changes result in a 35% speed increase when programming an
68 * More improvement could be gained if the registers do no need
69 * to be preserved but in that case the routines should be aware
70 * OpenOCD is used as a flash programmer or as a debug tool.
79 #include <helper/time_support.h>
82 #include "mips32_pracc.h"
84 struct mips32_pracc_context
{
85 uint32_t *local_iparam
;
87 uint32_t *local_oparam
;
93 struct mips_ejtag
*ejtag_info
;
96 static int mips32_pracc_read_mem8(struct mips_ejtag
*ejtag_info
,
97 uint32_t addr
, int count
, uint8_t *buf
);
98 static int mips32_pracc_read_mem16(struct mips_ejtag
*ejtag_info
,
99 uint32_t addr
, int count
, uint16_t *buf
);
100 static int mips32_pracc_read_mem32(struct mips_ejtag
*ejtag_info
,
101 uint32_t addr
, int count
, uint32_t *buf
);
102 static int mips32_pracc_read_u32(struct mips_ejtag
*ejtag_info
,
103 uint32_t addr
, uint32_t *buf
);
105 static int mips32_pracc_write_mem8(struct mips_ejtag
*ejtag_info
,
106 uint32_t addr
, int count
, uint8_t *buf
);
107 static int mips32_pracc_write_mem16(struct mips_ejtag
*ejtag_info
,
108 uint32_t addr
, int count
, uint16_t *buf
);
109 static int mips32_pracc_write_mem32(struct mips_ejtag
*ejtag_info
,
110 uint32_t addr
, int count
, uint32_t *buf
);
111 static int mips32_pracc_write_u32(struct mips_ejtag
*ejtag_info
,
112 uint32_t addr
, uint32_t *buf
);
114 static int mips32_pracc_sync_cache(struct mips_ejtag
*ejtag_info
,
115 uint32_t start_addr
, uint32_t end_addr
);
116 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag
*ejtag_info
,
117 uint32_t start_addr
, uint32_t end_addr
);
119 static int wait_for_pracc_rw(struct mips_ejtag
*ejtag_info
, uint32_t *ctrl
)
122 long long then
= timeval_ms();
126 /* wait for the PrAcc to become "1" */
127 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
128 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
;
131 retval
= mips_ejtag_drscan_32(ejtag_info
, &ejtag_ctrl
);
132 if (retval
!= ERROR_OK
)
135 if (ejtag_ctrl
& EJTAG_CTRL_PRACC
)
138 timeout
= timeval_ms() - then
;
139 if (timeout
> 1000) {
140 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
141 return ERROR_JTAG_DEVICE_ERROR
;
149 static int mips32_pracc_exec_read(struct mips32_pracc_context
*ctx
, uint32_t address
)
151 struct mips_ejtag
*ejtag_info
= ctx
->ejtag_info
;
153 uint32_t ejtag_ctrl
, data
;
155 if ((address
>= MIPS32_PRACC_PARAM_IN
)
156 && (address
< MIPS32_PRACC_PARAM_IN
+ ctx
->num_iparam
* 4)) {
157 offset
= (address
- MIPS32_PRACC_PARAM_IN
) / 4;
158 data
= ctx
->local_iparam
[offset
];
159 } else if ((address
>= MIPS32_PRACC_PARAM_OUT
)
160 && (address
< MIPS32_PRACC_PARAM_OUT
+ ctx
->num_oparam
* 4)) {
161 offset
= (address
- MIPS32_PRACC_PARAM_OUT
) / 4;
162 data
= ctx
->local_oparam
[offset
];
163 } else if ((address
>= MIPS32_PRACC_TEXT
)
164 && (address
< MIPS32_PRACC_TEXT
+ ctx
->code_len
* 4)) {
165 offset
= (address
- MIPS32_PRACC_TEXT
) / 4;
166 data
= ctx
->code
[offset
];
167 } else if (address
== MIPS32_PRACC_STACK
) {
168 if (ctx
->stack_offset
<= 0) {
169 LOG_ERROR("Error: Pracc stack out of bounds");
170 return ERROR_JTAG_DEVICE_ERROR
;
172 /* save to our debug stack */
173 data
= ctx
->stack
[--ctx
->stack_offset
];
175 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
176 * to start of debug vector */
178 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32
"", address
);
179 return ERROR_JTAG_DEVICE_ERROR
;
182 /* Send the data out */
183 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_DATA
);
184 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, data
);
186 /* Clear the access pending bit (let the processor eat!) */
187 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
188 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_CONTROL
);
189 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, ejtag_ctrl
);
191 return jtag_execute_queue();
194 static int mips32_pracc_exec_write(struct mips32_pracc_context
*ctx
, uint32_t address
)
196 uint32_t ejtag_ctrl
, data
;
198 struct mips_ejtag
*ejtag_info
= ctx
->ejtag_info
;
201 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_DATA
);
202 retval
= mips_ejtag_drscan_32(ctx
->ejtag_info
, &data
);
203 if (retval
!= ERROR_OK
)
206 /* Clear access pending bit */
207 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
208 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_CONTROL
);
209 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, ejtag_ctrl
);
211 retval
= jtag_execute_queue();
212 if (retval
!= ERROR_OK
)
215 if ((address
>= MIPS32_PRACC_PARAM_IN
)
216 && (address
< MIPS32_PRACC_PARAM_IN
+ ctx
->num_iparam
* 4)) {
217 offset
= (address
- MIPS32_PRACC_PARAM_IN
) / 4;
218 ctx
->local_iparam
[offset
] = data
;
219 } else if ((address
>= MIPS32_PRACC_PARAM_OUT
)
220 && (address
< MIPS32_PRACC_PARAM_OUT
+ ctx
->num_oparam
* 4)) {
221 offset
= (address
- MIPS32_PRACC_PARAM_OUT
) / 4;
222 ctx
->local_oparam
[offset
] = data
;
223 } else if (address
== MIPS32_PRACC_STACK
) {
224 if (ctx
->stack_offset
>= 32) {
225 LOG_ERROR("Error: Pracc stack out of bounds");
226 return ERROR_JTAG_DEVICE_ERROR
;
228 /* save data onto our stack */
229 ctx
->stack
[ctx
->stack_offset
++] = data
;
231 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32
"", address
);
232 return ERROR_JTAG_DEVICE_ERROR
;
238 int mips32_pracc_exec(struct mips_ejtag
*ejtag_info
, int code_len
, const uint32_t *code
,
239 int num_param_in
, uint32_t *param_in
, int num_param_out
, uint32_t *param_out
, int cycle
)
243 struct mips32_pracc_context ctx
;
247 ctx
.local_iparam
= param_in
;
248 ctx
.local_oparam
= param_out
;
249 ctx
.num_iparam
= num_param_in
;
250 ctx
.num_oparam
= num_param_out
;
252 ctx
.code_len
= code_len
;
253 ctx
.ejtag_info
= ejtag_info
;
254 ctx
.stack_offset
= 0;
257 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
258 if (retval
!= ERROR_OK
)
262 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
263 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
264 if (retval
!= ERROR_OK
)
267 /* Check for read or write */
268 if (ejtag_ctrl
& EJTAG_CTRL_PRNW
) {
269 retval
= mips32_pracc_exec_write(&ctx
, address
);
270 if (retval
!= ERROR_OK
)
273 /* Check to see if its reading at the debug vector. The first pass through
274 * the module is always read at the vector, so the first one we allow. When
275 * the second read from the vector occurs we are done and just exit. */
276 if ((address
== MIPS32_PRACC_TEXT
) && (pass
++))
279 retval
= mips32_pracc_exec_read(&ctx
, address
);
280 if (retval
!= ERROR_OK
)
288 /* stack sanity check */
289 if (ctx
.stack_offset
!= 0)
290 LOG_DEBUG("Pracc Stack not zero");
295 int mips32_pracc_read_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
299 return mips32_pracc_read_mem8(ejtag_info
, addr
, count
, (uint8_t *)buf
);
301 return mips32_pracc_read_mem16(ejtag_info
, addr
, count
, (uint16_t *)buf
);
304 return mips32_pracc_read_u32(ejtag_info
, addr
, (uint32_t *)buf
);
306 return mips32_pracc_read_mem32(ejtag_info
, addr
, count
, (uint32_t *)buf
);
312 static int mips32_pracc_read_mem32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint32_t *buf
)
314 static const uint32_t code
[] = {
316 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
317 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
318 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
319 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
320 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
321 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
322 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
324 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
325 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
326 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
327 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
328 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
329 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
331 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
334 MIPS32_LW(8, 0, 9), /* lw $8,0($9), Load $8 with the word @mem[$9] */
335 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
337 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
338 MIPS32_ADDI(9, 9, 4), /* $1 += 4 */
339 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
341 MIPS32_B(NEG16(8)), /* b loop */
344 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
345 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
346 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
347 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
348 MIPS32_B(NEG16(27)), /* b start */
349 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
352 int retval
= ERROR_OK
;
355 uint32_t param_in
[2];
365 param_in
[1] = blocksize
;
367 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
368 ARRAY_SIZE(param_in
), param_in
, blocksize
, &buf
[wordsread
], 1);
369 if (retval
!= ERROR_OK
)
373 addr
+= blocksize
*sizeof(uint32_t);
374 wordsread
+= blocksize
;
380 static int mips32_pracc_read_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
382 static const uint32_t code
[] = {
384 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
385 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
386 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
387 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
389 MIPS32_LW(8, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
), 15), /* load R8 @ param_in[0] = address */
391 MIPS32_LW(8, 0, 8), /* lw $8,0($8), Load $8 with the word @mem[$8] */
392 MIPS32_SW(8, NEG16(MIPS32_PRACC_STACK
- MIPS32_PRACC_PARAM_OUT
), 15), /* store R8 @ param_out[0] */
394 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
395 MIPS32_B(NEG16(9)), /* b start */
396 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
399 int retval
= ERROR_OK
;
400 uint32_t param_in
[1];
404 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
405 ARRAY_SIZE(param_in
), param_in
, 1, buf
, 1);
406 if (retval
!= ERROR_OK
)
412 static int mips32_pracc_read_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
414 static const uint32_t code
[] = {
416 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
417 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
418 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
419 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
420 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
421 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
422 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
424 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
425 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
426 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
427 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
428 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
429 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
431 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
434 MIPS32_LHU(8, 0, 9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
435 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
437 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
438 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
439 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
440 MIPS32_B(NEG16(8)), /* b loop */
443 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
444 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
445 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
446 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
447 MIPS32_B(NEG16(27)), /* b start */
448 MIPS32_MFC0(15, 30, 0), /* move COP0 DeSave to $15 */
451 /* TODO remove array */
452 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
453 if (param_out
== NULL
) {
454 LOG_ERROR("Out of memory");
458 int retval
= ERROR_OK
;
461 uint32_t param_in
[2];
469 param_in
[1] = blocksize
;
471 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
472 ARRAY_SIZE(param_in
), param_in
, blocksize
, ¶m_out
[hwordsread
], 1);
474 if (retval
!= ERROR_OK
)
478 addr
+= blocksize
*sizeof(uint16_t);
479 hwordsread
+= blocksize
;
483 for (i
= 0; i
< hwordsread
; i
++)
484 buf
[i
] = param_out
[i
];
490 static int mips32_pracc_read_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
492 static const uint32_t code
[] = {
494 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
495 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
496 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
497 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
498 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
499 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
500 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
502 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
503 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
504 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
505 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
506 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
507 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
509 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
512 MIPS32_LBU(8, 0, 9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
513 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
515 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
516 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
517 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
518 MIPS32_B(NEG16(8)), /* b loop */
521 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
522 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
523 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
524 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
525 MIPS32_B(NEG16(27)), /* b start */
526 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
529 /* TODO remove array */
530 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
531 if (param_out
== NULL
) {
532 LOG_ERROR("Out of memory");
536 int retval
= ERROR_OK
;
538 uint32_t param_in
[2];
547 param_in
[1] = blocksize
;
549 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
550 ARRAY_SIZE(param_in
), param_in
, count
, ¶m_out
[bytesread
], 1);
552 if (retval
!= ERROR_OK
)
557 bytesread
+= blocksize
;
560 for (i
= 0; i
< bytesread
; i
++)
561 buf
[i
] = param_out
[i
];
567 int mips32_cp0_read(struct mips_ejtag
*ejtag_info
, uint32_t *val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
570 * Do not make this code static, but regenerate it every time,
571 * as 5th element has to be changed to add parameters
575 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
576 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
577 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
578 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
579 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
581 /* 5 */ MIPS32_MFC0(8, 0, 0), /* move COP0 [cp0_reg select] to $8 */
583 MIPS32_LUI(9, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
584 MIPS32_ORI(9, 9, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
585 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
587 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
588 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
589 MIPS32_B(NEG16(12)), /* b start */
590 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
594 * Note that our input parametes cp0_reg and cp0_sel
595 * are numbers (not gprs) which make part of mfc0 instruction opcode.
597 * These are not fix, but can be different for each mips32_cp0_read() function call,
598 * and that is why we must insert them directly into opcode,
599 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
600 * and put them into the gprs later from MIPS32_PRACC_STACK
601 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
602 * but plain (immediate) number.
604 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
605 * In order to insert our parameters, we must change rd and funct fields.
607 code
[5] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct of MIPS32_R_INST macro */
609 /* TODO remove array */
610 uint32_t *param_out
= val
;
613 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 0, NULL
, 1, param_out
, 1);
618 int mips32_cp0_write(struct mips_ejtag
*ejtag_info
,
619 uint32_t val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
623 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
624 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
625 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
626 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
627 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
629 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
630 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
631 MIPS32_LW(9, 0, 8), /* Load write val to $9 */
633 /* 8 */ MIPS32_MTC0(9, 0, 0), /* move $9 to COP0 [cp0_reg select] */
635 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
636 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
637 MIPS32_B(NEG16(12)), /* b start */
638 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
642 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
643 * In order to insert our parameters, we must change rd and funct fields.
645 code
[8] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct fields of MIPS32_R_INST macro */
647 /* TODO remove array */
648 uint32_t *param_in
= malloc(1 * sizeof(uint32_t));
652 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 1, param_in
, 0, NULL
, 1);
660 * \b mips32_pracc_sync_cache
662 * Synchronize Caches to Make Instruction Writes Effective
663 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
664 * Document Number: MD00086, Revision 2.00, June 9, 2003)
666 * When the instruction stream is written, the SYNCI instruction should be used
667 * in conjunction with other instructions to make the newly-written instructions effective.
670 * A program that loads another program into memory is actually writing the D- side cache.
671 * The instructions it has loaded can't be executed until they reach the I-cache.
673 * After the instructions have been written, the loader should arrange
674 * to write back any containing D-cache line and invalidate any locations
675 * already in the I-cache.
677 * You can do that with cache instructions, but those instructions are only available in kernel mode,
678 * and a loader writing instructions for the use of its own process need not be privileged software.
680 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
681 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
682 * That is, it arranges a D-cache write-back and an I-cache invalidate.
684 * To employ synci at user level, you need to know the size of a cache line,
685 * and that can be obtained with a rdhwr SYNCI_Step
686 * from one of the standard “hardware registers”.
688 static int mips32_pracc_sync_cache(struct mips_ejtag
*ejtag_info
,
689 uint32_t start_addr
, uint32_t end_addr
)
691 static const uint32_t code
[] = {
693 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
694 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
695 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
696 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
697 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
698 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
699 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
701 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
702 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
703 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
704 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
706 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP
), /* $11 = MIPS32_SYNCI_STEP */
707 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
710 MIPS32_SYNCI(0, 9), /* synci 0($9) */
711 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
712 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
713 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
716 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
717 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
718 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
719 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
720 MIPS32_B(NEG16(24)), /* b start */
721 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
724 /* TODO remove array */
725 uint32_t *param_in
= malloc(2 * sizeof(uint32_t));
727 param_in
[0] = start_addr
;
728 param_in
[1] = end_addr
;
730 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 2, param_in
, 0, NULL
, 1);
738 * \b mips32_pracc_clean_invalidate_cache
740 * Writeback D$ and Invalidate I$
741 * so that the instructions written can be visible to CPU
743 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag
*ejtag_info
,
744 uint32_t start_addr
, uint32_t end_addr
)
746 static const uint32_t code
[] = {
748 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
749 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
750 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
751 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
752 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
753 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
754 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
756 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
757 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
758 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
759 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
760 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
763 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
764 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
767 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK
, 0, 9), /* cache Hit_Writeback_D, 0($9) */
768 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE
, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
770 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
772 MIPS32_B(NEG16(7)), /* b cache_loop */
775 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
776 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
777 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
778 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
779 MIPS32_B(NEG16(25)), /* b start */
780 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
784 * Find cache line size in bytes
789 mips32_cp0_read(ejtag_info
, &conf
, 16, 1);
790 dl
= (conf
& MIPS32_CONFIG1_DL_MASK
) >> MIPS32_CONFIG1_DL_SHIFT
;
792 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
795 /* TODO remove array */
796 uint32_t *param_in
= malloc(3 * sizeof(uint32_t));
798 param_in
[0] = start_addr
;
799 param_in
[1] = end_addr
;
802 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 3, param_in
, 0, NULL
, 1);
810 int mips32_pracc_write_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
816 retval
= mips32_pracc_write_mem8(ejtag_info
, addr
, count
, (uint8_t *)buf
);
819 retval
= mips32_pracc_write_mem16(ejtag_info
, addr
, count
, (uint16_t *)buf
);
823 retval
= mips32_pracc_write_u32(ejtag_info
, addr
, (uint32_t *)buf
);
825 retval
= mips32_pracc_write_mem32(ejtag_info
, addr
, count
, (uint32_t *)buf
);
832 * If we are in the cachable regoion and cache is activated,
833 * we must clean D$ + invalidate I$ after we did the write,
834 * so that changes do not continue to live only in D$, but to be
835 * replicated in I$ also (maybe we wrote the istructions)
840 if ((KSEGX(addr
) == KSEG1
) || ((addr
>= 0xff200000) && (addr
<= 0xff3fffff)))
841 return retval
; /*Nothing to do*/
843 mips32_cp0_read(ejtag_info
, &conf
, 16, 0);
845 switch (KSEGX(addr
)) {
847 cached
= (conf
& MIPS32_CONFIG0_KU_MASK
) >> MIPS32_CONFIG0_KU_SHIFT
;
850 cached
= (conf
& MIPS32_CONFIG0_K0_MASK
) >> MIPS32_CONFIG0_K0_SHIFT
;
854 cached
= (conf
& MIPS32_CONFIG0_K23_MASK
) >> MIPS32_CONFIG0_K23_SHIFT
;
862 * Check cachablitiy bits coherency algorithm -
863 * is the region cacheable or uncached.
864 * If cacheable we have to synchronize the cache
867 uint32_t start_addr
, end_addr
;
871 end_addr
= addr
+ count
* size
;
873 /** select cache synchronisation mechanism based on Architecture Release */
874 rel
= (conf
& MIPS32_CONFIG0_AR_MASK
) >> MIPS32_CONFIG0_AR_SHIFT
;
876 case MIPS32_ARCH_REL1
:
877 /* MIPS32/64 Release 1 - we must use cache instruction */
878 mips32_pracc_clean_invalidate_cache(ejtag_info
, start_addr
, end_addr
);
880 case MIPS32_ARCH_REL2
:
881 /* MIPS32/64 Release 2 - we can use synci instruction */
882 mips32_pracc_sync_cache(ejtag_info
, start_addr
, end_addr
);
893 static int mips32_pracc_write_mem32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint32_t *buf
)
895 static const uint32_t code
[] = {
897 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
898 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
899 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
900 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
901 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
902 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
903 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
905 MIPS32_ADDI(8, 15, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)), /* $8= MIPS32_PRACC_PARAM_IN */
906 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
907 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
908 MIPS32_ADDI(8, 8, 8), /* $8 += 8 beginning of data */
911 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
912 MIPS32_SW(11, 0, 9), /* sw $11,0($9) */
914 MIPS32_ADDI(9, 9, 4), /* $9 += 4 */
915 MIPS32_BNE(10, 9, NEG16(4)), /* bne $10, $9, loop */
916 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
919 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
920 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
921 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
922 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
923 MIPS32_B(NEG16(21)), /* b start */
924 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
927 /* TODO remove array */
928 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
930 param_in
[1] = addr
+ (count
* sizeof(uint32_t)); /* last address */
932 memcpy(¶m_in
[2], buf
, count
* sizeof(uint32_t));
935 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
936 count
+ 2, param_in
, 0, NULL
, 1);
943 static int mips32_pracc_write_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
945 static const uint32_t code
[] = {
947 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
948 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
949 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
950 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
951 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
953 MIPS32_LW(8, NEG16((MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)-4), 15), /* load R8 @ param_in[1] = data */
954 MIPS32_LW(9, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
), 15), /* load R9 @ param_in[0] = address */
956 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
958 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
959 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
960 MIPS32_B(NEG16(11)), /* b start */
961 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
964 /* TODO remove array */
965 uint32_t param_in
[1 + 1];
969 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
970 ARRAY_SIZE(param_in
), param_in
, 0, NULL
, 1);
973 static int mips32_pracc_write_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
975 static const uint32_t code
[] = {
977 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
978 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
979 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
980 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
981 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
982 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
983 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
985 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
986 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
987 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
988 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
989 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
991 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
994 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
995 MIPS32_SH(11, 0, 9), /* sh $11,0($9) */
997 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
998 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
999 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
1001 MIPS32_B(NEG16(8)), /* b loop */
1004 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
1005 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
1006 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
1007 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1008 MIPS32_B(NEG16(26)), /* b start */
1009 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1012 /* TODO remove array */
1013 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
1016 param_in
[1] = count
;
1018 for (i
= 0; i
< count
; i
++)
1019 param_in
[i
+ 2] = buf
[i
];
1022 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1023 count
+ 2, param_in
, 0, NULL
, 1);
1030 static int mips32_pracc_write_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
1032 static const uint32_t code
[] = {
1034 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1035 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1036 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1037 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
1038 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
1039 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
1040 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
1042 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
1043 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1044 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
1045 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
1046 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
1048 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
1051 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
1052 MIPS32_SB(11, 0, 9), /* sb $11,0($9) */
1054 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
1055 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
1056 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
1058 MIPS32_B(NEG16(8)), /* b loop */
1061 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
1062 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
1063 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
1064 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1065 MIPS32_B(NEG16(26)), /* b start */
1066 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1069 /* TODO remove array */
1070 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
1074 param_in
[1] = count
;
1076 for (i
= 0; i
< count
; i
++)
1077 param_in
[i
+ 2] = buf
[i
];
1079 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1080 count
+ 2, param_in
, 0, NULL
, 1);
1087 int mips32_pracc_write_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1089 static const uint32_t code
[] = {
1091 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $2 = MIPS32_PRACC_PARAM_IN */
1092 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1093 MIPS32_LW(1, 1*4, 2), /* lw $1,1*4($2) */
1094 MIPS32_LW(15, 15*4, 2), /* lw $15,15*4($2) */
1095 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1096 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1097 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1098 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1099 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $1 = MIPS32_PRACC_PARAM_IN */
1100 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1101 MIPS32_LW(3, 3*4, 1), /* lw $3,3*4($1) */
1102 MIPS32_LW(4, 4*4, 1), /* lw $4,4*4($1) */
1103 MIPS32_LW(5, 5*4, 1), /* lw $5,5*4($1) */
1104 MIPS32_LW(6, 6*4, 1), /* lw $6,6*4($1) */
1105 MIPS32_LW(7, 7*4, 1), /* lw $7,7*4($1) */
1106 MIPS32_LW(8, 8*4, 1), /* lw $8,8*4($1) */
1107 MIPS32_LW(9, 9*4, 1), /* lw $9,9*4($1) */
1108 MIPS32_LW(10, 10*4, 1), /* lw $10,10*4($1) */
1109 MIPS32_LW(11, 11*4, 1), /* lw $11,11*4($1) */
1110 MIPS32_LW(12, 12*4, 1), /* lw $12,12*4($1) */
1111 MIPS32_LW(13, 13*4, 1), /* lw $13,13*4($1) */
1112 MIPS32_LW(14, 14*4, 1), /* lw $14,14*4($1) */
1113 MIPS32_LW(16, 16*4, 1), /* lw $16,16*4($1) */
1114 MIPS32_LW(17, 17*4, 1), /* lw $17,17*4($1) */
1115 MIPS32_LW(18, 18*4, 1), /* lw $18,18*4($1) */
1116 MIPS32_LW(19, 19*4, 1), /* lw $19,19*4($1) */
1117 MIPS32_LW(20, 20*4, 1), /* lw $20,20*4($1) */
1118 MIPS32_LW(21, 21*4, 1), /* lw $21,21*4($1) */
1119 MIPS32_LW(22, 22*4, 1), /* lw $22,22*4($1) */
1120 MIPS32_LW(23, 23*4, 1), /* lw $23,23*4($1) */
1121 MIPS32_LW(24, 24*4, 1), /* lw $24,24*4($1) */
1122 MIPS32_LW(25, 25*4, 1), /* lw $25,25*4($1) */
1123 MIPS32_LW(26, 26*4, 1), /* lw $26,26*4($1) */
1124 MIPS32_LW(27, 27*4, 1), /* lw $27,27*4($1) */
1125 MIPS32_LW(28, 28*4, 1), /* lw $28,28*4($1) */
1126 MIPS32_LW(29, 29*4, 1), /* lw $29,29*4($1) */
1127 MIPS32_LW(30, 30*4, 1), /* lw $30,30*4($1) */
1128 MIPS32_LW(31, 31*4, 1), /* lw $31,31*4($1) */
1130 MIPS32_LW(2, 32*4, 1), /* lw $2,32*4($1) */
1131 MIPS32_MTC0(2, 12, 0), /* move $2 to status */
1132 MIPS32_LW(2, 33*4, 1), /* lw $2,33*4($1) */
1133 MIPS32_MTLO(2), /* move $2 to lo */
1134 MIPS32_LW(2, 34*4, 1), /* lw $2,34*4($1) */
1135 MIPS32_MTHI(2), /* move $2 to hi */
1136 MIPS32_LW(2, 35*4, 1), /* lw $2,35*4($1) */
1137 MIPS32_MTC0(2, 8, 0), /* move $2 to badvaddr */
1138 MIPS32_LW(2, 36*4, 1), /* lw $2,36*4($1) */
1139 MIPS32_MTC0(2, 13, 0), /* move $2 to cause*/
1140 MIPS32_LW(2, 37*4, 1), /* lw $2,37*4($1) */
1141 MIPS32_MTC0(2, 24, 0), /* move $2 to depc (pc) */
1143 MIPS32_LW(2, 2*4, 1), /* lw $2,2*4($1) */
1144 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1145 MIPS32_B(NEG16(53)), /* b start */
1146 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1151 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1152 MIPS32NUMCOREREGS
, regs
, 0, NULL
, 1);
1157 int mips32_pracc_read_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1159 static const uint32_t code
[] = {
1161 MIPS32_MTC0(2, 31, 0), /* move $2 to COP0 DeSave */
1162 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $2 = MIPS32_PRACC_PARAM_OUT */
1163 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1164 MIPS32_SW(0, 0*4, 2), /* sw $0,0*4($2) */
1165 MIPS32_SW(1, 1*4, 2), /* sw $1,1*4($2) */
1166 MIPS32_SW(15, 15*4, 2), /* sw $15,15*4($2) */
1167 MIPS32_MFC0(2, 31, 0), /* move COP0 DeSave to $2 */
1168 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1169 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1170 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1171 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1172 MIPS32_SW(2, 0, 15), /* sw $2,($15) */
1173 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $1 = MIPS32_PRACC_PARAM_OUT */
1174 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1175 MIPS32_SW(2, 2*4, 1), /* sw $2,2*4($1) */
1176 MIPS32_SW(3, 3*4, 1), /* sw $3,3*4($1) */
1177 MIPS32_SW(4, 4*4, 1), /* sw $4,4*4($1) */
1178 MIPS32_SW(5, 5*4, 1), /* sw $5,5*4($1) */
1179 MIPS32_SW(6, 6*4, 1), /* sw $6,6*4($1) */
1180 MIPS32_SW(7, 7*4, 1), /* sw $7,7*4($1) */
1181 MIPS32_SW(8, 8*4, 1), /* sw $8,8*4($1) */
1182 MIPS32_SW(9, 9*4, 1), /* sw $9,9*4($1) */
1183 MIPS32_SW(10, 10*4, 1), /* sw $10,10*4($1) */
1184 MIPS32_SW(11, 11*4, 1), /* sw $11,11*4($1) */
1185 MIPS32_SW(12, 12*4, 1), /* sw $12,12*4($1) */
1186 MIPS32_SW(13, 13*4, 1), /* sw $13,13*4($1) */
1187 MIPS32_SW(14, 14*4, 1), /* sw $14,14*4($1) */
1188 MIPS32_SW(16, 16*4, 1), /* sw $16,16*4($1) */
1189 MIPS32_SW(17, 17*4, 1), /* sw $17,17*4($1) */
1190 MIPS32_SW(18, 18*4, 1), /* sw $18,18*4($1) */
1191 MIPS32_SW(19, 19*4, 1), /* sw $19,19*4($1) */
1192 MIPS32_SW(20, 20*4, 1), /* sw $20,20*4($1) */
1193 MIPS32_SW(21, 21*4, 1), /* sw $21,21*4($1) */
1194 MIPS32_SW(22, 22*4, 1), /* sw $22,22*4($1) */
1195 MIPS32_SW(23, 23*4, 1), /* sw $23,23*4($1) */
1196 MIPS32_SW(24, 24*4, 1), /* sw $24,24*4($1) */
1197 MIPS32_SW(25, 25*4, 1), /* sw $25,25*4($1) */
1198 MIPS32_SW(26, 26*4, 1), /* sw $26,26*4($1) */
1199 MIPS32_SW(27, 27*4, 1), /* sw $27,27*4($1) */
1200 MIPS32_SW(28, 28*4, 1), /* sw $28,28*4($1) */
1201 MIPS32_SW(29, 29*4, 1), /* sw $29,29*4($1) */
1202 MIPS32_SW(30, 30*4, 1), /* sw $30,30*4($1) */
1203 MIPS32_SW(31, 31*4, 1), /* sw $31,31*4($1) */
1205 MIPS32_MFC0(2, 12, 0), /* move status to $2 */
1206 MIPS32_SW(2, 32*4, 1), /* sw $2,32*4($1) */
1207 MIPS32_MFLO(2), /* move lo to $2 */
1208 MIPS32_SW(2, 33*4, 1), /* sw $2,33*4($1) */
1209 MIPS32_MFHI(2), /* move hi to $2 */
1210 MIPS32_SW(2, 34*4, 1), /* sw $2,34*4($1) */
1211 MIPS32_MFC0(2, 8, 0), /* move badvaddr to $2 */
1212 MIPS32_SW(2, 35*4, 1), /* sw $2,35*4($1) */
1213 MIPS32_MFC0(2, 13, 0), /* move cause to $2 */
1214 MIPS32_SW(2, 36*4, 1), /* sw $2,36*4($1) */
1215 MIPS32_MFC0(2, 24, 0), /* move depc (pc) to $2 */
1216 MIPS32_SW(2, 37*4, 1), /* sw $2,37*4($1) */
1218 MIPS32_LW(2, 0, 15), /* lw $2,($15) */
1219 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1220 MIPS32_B(NEG16(58)), /* b start */
1221 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1226 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1227 0, NULL
, MIPS32NUMCOREREGS
, regs
, 1);
1232 /* fastdata upload/download requires an initialized working area
1233 * to load the download code; it should not be called otherwise
1234 * fetch order from the fastdata area
1239 int mips32_pracc_fastdata_xfer(struct mips_ejtag
*ejtag_info
, struct working_area
*source
,
1240 int write_t
, uint32_t addr
, int count
, uint32_t *buf
)
1242 uint32_t handler_code
[] = {
1243 /* caution when editing, table is modified below */
1244 /* r15 points to the start of this code */
1245 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1246 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1247 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1248 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1249 /* start of fastdata area in t0 */
1250 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA
)),
1251 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA
)),
1252 MIPS32_LW(9, 0, 8), /* start addr in t1 */
1253 MIPS32_LW(10, 0, 8), /* end addr to t2 */
1255 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
1256 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
1257 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
1258 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
1260 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1261 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1262 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1263 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1265 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT
)),
1266 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT
)),
1267 MIPS32_JR(15), /* jr start */
1268 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1271 uint32_t jmp_code
[] = {
1272 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1273 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
1274 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
1275 MIPS32_JR(15), /* jump to ram program */
1280 uint32_t val
, ejtag_ctrl
, address
;
1282 if (source
->size
< MIPS32_FASTDATA_HANDLER_SIZE
)
1283 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1286 handler_code
[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
1287 handler_code
[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
1289 handler_code
[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
1290 handler_code
[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
1293 /* write program into RAM */
1294 if (write_t
!= ejtag_info
->fast_access_save
) {
1295 mips32_pracc_write_mem32(ejtag_info
, source
->address
, ARRAY_SIZE(handler_code
), handler_code
);
1296 /* save previous operation to speed to any consecutive read/writes */
1297 ejtag_info
->fast_access_save
= write_t
;
1300 LOG_DEBUG("%s using 0x%.8" PRIx32
" for write handler", __func__
, source
->address
);
1302 jmp_code
[1] |= UPPER16(source
->address
);
1303 jmp_code
[2] |= LOWER16(source
->address
);
1305 for (i
= 0; i
< (int) ARRAY_SIZE(jmp_code
); i
++) {
1306 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1307 if (retval
!= ERROR_OK
)
1310 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_DATA
);
1311 mips_ejtag_drscan_32_out(ejtag_info
, jmp_code
[i
]);
1313 /* Clear the access pending bit (let the processor eat!) */
1314 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
1315 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
1316 mips_ejtag_drscan_32_out(ejtag_info
, ejtag_ctrl
);
1319 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1320 if (retval
!= ERROR_OK
)
1323 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1325 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1326 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1327 if (retval
!= ERROR_OK
)
1330 if (address
!= MIPS32_PRACC_FASTDATA_AREA
)
1333 /* wait PrAcc pending bit for FASTDATA write */
1334 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1335 if (retval
!= ERROR_OK
)
1338 /* Send the load start address */
1340 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_FASTDATA
);
1341 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1343 /* Send the load end address */
1344 val
= addr
+ (count
- 1) * 4;
1345 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1347 for (i
= 0; i
< count
; i
++) {
1348 retval
= mips_ejtag_fastdata_scan(ejtag_info
, write_t
, buf
++);
1349 if (retval
!= ERROR_OK
)
1353 retval
= jtag_execute_queue();
1354 if (retval
!= ERROR_OK
) {
1355 LOG_ERROR("fastdata load failed");
1359 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1360 if (retval
!= ERROR_OK
)
1364 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1365 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1366 if (retval
!= ERROR_OK
)
1369 if (address
!= MIPS32_PRACC_TEXT
)
1370 LOG_ERROR("mini program did not return to start");
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)