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
);
130 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
)
384 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
385 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
), /* $15 = MIPS32_PRACC_BASE_ADDR */
386 MIPS32_SW(8, PRACC_STACK_OFFSET
, 15), /* sw $8,PRACC_STACK_OFFSET($15) */
388 MIPS32_LUI(8, UPPER16((addr
+ 0x8000))), /* load $8 with modified upper address */
389 MIPS32_LW(8, LOWER16(addr
), 8), /* lw $8, LOWER16(addr)($8) */
390 MIPS32_SW(8, PRACC_OUT_OFFSET
, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
392 MIPS32_LW(8, PRACC_STACK_OFFSET
, 15), /* lw $8,PRACC_STACK_OFFSET($15) */
393 MIPS32_B(NEG16(8)), /* b start */
394 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
397 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 0, NULL
, 1, buf
, 1);
400 static int mips32_pracc_read_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
402 static const uint32_t code
[] = {
404 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
405 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
406 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
407 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
408 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
409 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
410 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
412 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
413 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
414 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
415 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
416 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
417 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
419 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
422 MIPS32_LHU(8, 0, 9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
423 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
425 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
426 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
427 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
428 MIPS32_B(NEG16(8)), /* b loop */
431 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
432 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
433 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
434 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
435 MIPS32_B(NEG16(27)), /* b start */
436 MIPS32_MFC0(15, 30, 0), /* move COP0 DeSave to $15 */
439 /* TODO remove array */
440 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
441 if (param_out
== NULL
) {
442 LOG_ERROR("Out of memory");
446 int retval
= ERROR_OK
;
449 uint32_t param_in
[2];
457 param_in
[1] = blocksize
;
459 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
460 ARRAY_SIZE(param_in
), param_in
, blocksize
, ¶m_out
[hwordsread
], 1);
462 if (retval
!= ERROR_OK
)
466 addr
+= blocksize
*sizeof(uint16_t);
467 hwordsread
+= blocksize
;
471 for (i
= 0; i
< hwordsread
; i
++)
472 buf
[i
] = param_out
[i
];
478 static int mips32_pracc_read_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
480 static const uint32_t code
[] = {
482 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
483 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
484 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
485 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
486 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
487 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
488 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
490 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
491 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
492 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
493 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
494 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
495 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
497 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
500 MIPS32_LBU(8, 0, 9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
501 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
503 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
504 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
505 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
506 MIPS32_B(NEG16(8)), /* b loop */
509 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
510 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
511 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
512 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
513 MIPS32_B(NEG16(27)), /* b start */
514 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
517 /* TODO remove array */
518 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
519 if (param_out
== NULL
) {
520 LOG_ERROR("Out of memory");
524 int retval
= ERROR_OK
;
526 uint32_t param_in
[2];
535 param_in
[1] = blocksize
;
537 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
538 ARRAY_SIZE(param_in
), param_in
, count
, ¶m_out
[bytesread
], 1);
540 if (retval
!= ERROR_OK
)
545 bytesread
+= blocksize
;
548 for (i
= 0; i
< bytesread
; i
++)
549 buf
[i
] = param_out
[i
];
555 int mips32_cp0_read(struct mips_ejtag
*ejtag_info
, uint32_t *val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
558 * Do not make this code static, but regenerate it every time,
559 * as 3th element has to be changed to add parameters
563 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
564 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
), /* $15 = MIPS32_PRACC_BASE_ADDR */
565 MIPS32_SW(8, PRACC_STACK_OFFSET
, 15), /* sw $8,PRACC_STACK_OFFSET($15) */
567 /* 3 */ MIPS32_MFC0(8, 0, 0), /* move COP0 [cp0_reg select] to $8 */
568 MIPS32_SW(8, PRACC_OUT_OFFSET
, 15), /* sw $8,PRACC_OUT_OFFSET($15) */
570 MIPS32_LW(8, PRACC_STACK_OFFSET
, 15), /* lw $8,PRACC_STACK_OFFSET($15) */
571 MIPS32_B(NEG16(7)), /* b start */
572 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
576 * Note that our input parametes cp0_reg and cp0_sel
577 * are numbers (not gprs) which make part of mfc0 instruction opcode.
579 * These are not fix, but can be different for each mips32_cp0_read() function call,
580 * and that is why we must insert them directly into opcode,
581 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
582 * and put them into the gprs later from MIPS32_PRACC_STACK
583 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
584 * but plain (immediate) number.
586 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
587 * In order to insert our parameters, we must change rd and funct fields.
589 code
[3] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct of MIPS32_R_INST macro */
591 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 0, NULL
, 1, val
, 1);
594 int mips32_cp0_write(struct mips_ejtag
*ejtag_info
, uint32_t val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
598 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
599 MIPS32_LUI(15, UPPER16(val
)), /* Load val to $15 */
600 MIPS32_ORI(15, 15, LOWER16(val
)),
602 /* 3 */ MIPS32_MTC0(15, 0, 0), /* move $15 to COP0 [cp0_reg select] */
604 MIPS32_B(NEG16(5)), /* b start */
605 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
609 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
610 * In order to insert our parameters, we must change rd and funct fields.
612 code
[3] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct fields of MIPS32_R_INST macro */
614 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 0, NULL
, 0, NULL
, 1);
618 * \b mips32_pracc_sync_cache
620 * Synchronize Caches to Make Instruction Writes Effective
621 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
622 * Document Number: MD00086, Revision 2.00, June 9, 2003)
624 * When the instruction stream is written, the SYNCI instruction should be used
625 * in conjunction with other instructions to make the newly-written instructions effective.
628 * A program that loads another program into memory is actually writing the D- side cache.
629 * The instructions it has loaded can't be executed until they reach the I-cache.
631 * After the instructions have been written, the loader should arrange
632 * to write back any containing D-cache line and invalidate any locations
633 * already in the I-cache.
635 * You can do that with cache instructions, but those instructions are only available in kernel mode,
636 * and a loader writing instructions for the use of its own process need not be privileged software.
638 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
639 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
640 * That is, it arranges a D-cache write-back and an I-cache invalidate.
642 * To employ synci at user level, you need to know the size of a cache line,
643 * and that can be obtained with a rdhwr SYNCI_Step
644 * from one of the standard “hardware registers”.
646 static int mips32_pracc_sync_cache(struct mips_ejtag
*ejtag_info
,
647 uint32_t start_addr
, uint32_t end_addr
)
649 static const uint32_t code
[] = {
651 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
652 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
653 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
654 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
655 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
656 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
657 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
659 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
660 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
661 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
662 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
664 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP
), /* $11 = MIPS32_SYNCI_STEP */
665 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
668 MIPS32_SYNCI(0, 9), /* synci 0($9) */
669 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
670 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
671 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
674 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
675 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
676 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
677 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
678 MIPS32_B(NEG16(24)), /* b start */
679 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
682 /* TODO remove array */
683 uint32_t *param_in
= malloc(2 * sizeof(uint32_t));
685 param_in
[0] = start_addr
;
686 param_in
[1] = end_addr
;
688 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 2, param_in
, 0, NULL
, 1);
696 * \b mips32_pracc_clean_invalidate_cache
698 * Writeback D$ and Invalidate I$
699 * so that the instructions written can be visible to CPU
701 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag
*ejtag_info
,
702 uint32_t start_addr
, uint32_t end_addr
)
704 static const uint32_t code
[] = {
706 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
707 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
708 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
709 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
710 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
711 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
712 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
714 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
715 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
716 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
717 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
718 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
721 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
722 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
725 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK
, 0, 9), /* cache Hit_Writeback_D, 0($9) */
726 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE
, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
728 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
730 MIPS32_B(NEG16(7)), /* b cache_loop */
733 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
734 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
735 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
736 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
737 MIPS32_B(NEG16(25)), /* b start */
738 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
742 * Find cache line size in bytes
747 mips32_cp0_read(ejtag_info
, &conf
, 16, 1);
748 dl
= (conf
& MIPS32_CONFIG1_DL_MASK
) >> MIPS32_CONFIG1_DL_SHIFT
;
750 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
753 /* TODO remove array */
754 uint32_t *param_in
= malloc(3 * sizeof(uint32_t));
756 param_in
[0] = start_addr
;
757 param_in
[1] = end_addr
;
760 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 3, param_in
, 0, NULL
, 1);
768 int mips32_pracc_write_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
774 retval
= mips32_pracc_write_mem8(ejtag_info
, addr
, count
, (uint8_t *)buf
);
777 retval
= mips32_pracc_write_mem16(ejtag_info
, addr
, count
, (uint16_t *)buf
);
781 retval
= mips32_pracc_write_u32(ejtag_info
, addr
, (uint32_t *)buf
);
783 retval
= mips32_pracc_write_mem32(ejtag_info
, addr
, count
, (uint32_t *)buf
);
790 * If we are in the cachable regoion and cache is activated,
791 * we must clean D$ + invalidate I$ after we did the write,
792 * so that changes do not continue to live only in D$, but to be
793 * replicated in I$ also (maybe we wrote the istructions)
798 if ((KSEGX(addr
) == KSEG1
) || ((addr
>= 0xff200000) && (addr
<= 0xff3fffff)))
799 return retval
; /*Nothing to do*/
801 mips32_cp0_read(ejtag_info
, &conf
, 16, 0);
803 switch (KSEGX(addr
)) {
805 cached
= (conf
& MIPS32_CONFIG0_KU_MASK
) >> MIPS32_CONFIG0_KU_SHIFT
;
808 cached
= (conf
& MIPS32_CONFIG0_K0_MASK
) >> MIPS32_CONFIG0_K0_SHIFT
;
812 cached
= (conf
& MIPS32_CONFIG0_K23_MASK
) >> MIPS32_CONFIG0_K23_SHIFT
;
820 * Check cachablitiy bits coherency algorithm -
821 * is the region cacheable or uncached.
822 * If cacheable we have to synchronize the cache
825 uint32_t start_addr
, end_addr
;
829 end_addr
= addr
+ count
* size
;
831 /** select cache synchronisation mechanism based on Architecture Release */
832 rel
= (conf
& MIPS32_CONFIG0_AR_MASK
) >> MIPS32_CONFIG0_AR_SHIFT
;
834 case MIPS32_ARCH_REL1
:
835 /* MIPS32/64 Release 1 - we must use cache instruction */
836 mips32_pracc_clean_invalidate_cache(ejtag_info
, start_addr
, end_addr
);
838 case MIPS32_ARCH_REL2
:
839 /* MIPS32/64 Release 2 - we can use synci instruction */
840 mips32_pracc_sync_cache(ejtag_info
, start_addr
, end_addr
);
851 static int mips32_pracc_write_mem32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint32_t *buf
)
853 static const uint32_t code
[] = {
855 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
856 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
857 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
858 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
859 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
860 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
861 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
863 MIPS32_ADDI(8, 15, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)), /* $8= MIPS32_PRACC_PARAM_IN */
864 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
865 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
866 MIPS32_ADDI(8, 8, 8), /* $8 += 8 beginning of data */
869 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
870 MIPS32_SW(11, 0, 9), /* sw $11,0($9) */
872 MIPS32_ADDI(9, 9, 4), /* $9 += 4 */
873 MIPS32_BNE(10, 9, NEG16(4)), /* bne $10, $9, loop */
874 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
877 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
878 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
879 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
880 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
881 MIPS32_B(NEG16(21)), /* b start */
882 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
885 /* TODO remove array */
886 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
888 param_in
[1] = addr
+ (count
* sizeof(uint32_t)); /* last address */
890 memcpy(¶m_in
[2], buf
, count
* sizeof(uint32_t));
893 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
894 count
+ 2, param_in
, 0, NULL
, 1);
901 static int mips32_pracc_write_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
903 static const uint32_t code
[] = {
905 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
906 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
907 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
908 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
909 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
911 MIPS32_LW(8, NEG16((MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)-4), 15), /* load R8 @ param_in[1] = data */
912 MIPS32_LW(9, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
), 15), /* load R9 @ param_in[0] = address */
914 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
916 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
917 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
918 MIPS32_B(NEG16(11)), /* b start */
919 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
922 /* TODO remove array */
923 uint32_t param_in
[1 + 1];
927 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
928 ARRAY_SIZE(param_in
), param_in
, 0, NULL
, 1);
931 static int mips32_pracc_write_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
933 static const uint32_t code
[] = {
935 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
936 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
937 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
938 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
939 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
940 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
941 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
943 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
944 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
945 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
946 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
947 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
949 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
952 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
953 MIPS32_SH(11, 0, 9), /* sh $11,0($9) */
955 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
956 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
957 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
959 MIPS32_B(NEG16(8)), /* b loop */
962 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
963 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
964 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
965 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
966 MIPS32_B(NEG16(26)), /* b start */
967 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
970 /* TODO remove array */
971 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
976 for (i
= 0; i
< count
; i
++)
977 param_in
[i
+ 2] = buf
[i
];
980 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
981 count
+ 2, param_in
, 0, NULL
, 1);
988 static int mips32_pracc_write_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
990 static const uint32_t code
[] = {
992 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
993 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
994 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
995 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
996 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
997 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
998 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
1000 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
1001 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1002 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
1003 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
1004 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
1006 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
1009 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
1010 MIPS32_SB(11, 0, 9), /* sb $11,0($9) */
1012 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
1013 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
1014 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
1016 MIPS32_B(NEG16(8)), /* b loop */
1019 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
1020 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
1021 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
1022 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1023 MIPS32_B(NEG16(26)), /* b start */
1024 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1027 /* TODO remove array */
1028 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
1032 param_in
[1] = count
;
1034 for (i
= 0; i
< count
; i
++)
1035 param_in
[i
+ 2] = buf
[i
];
1037 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1038 count
+ 2, param_in
, 0, NULL
, 1);
1045 int mips32_pracc_write_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1047 static const uint32_t code
[] = {
1049 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $2 = MIPS32_PRACC_PARAM_IN */
1050 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1051 MIPS32_LW(1, 1*4, 2), /* lw $1,1*4($2) */
1052 MIPS32_LW(15, 15*4, 2), /* lw $15,15*4($2) */
1053 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1054 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1055 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1056 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1057 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $1 = MIPS32_PRACC_PARAM_IN */
1058 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1059 MIPS32_LW(3, 3*4, 1), /* lw $3,3*4($1) */
1060 MIPS32_LW(4, 4*4, 1), /* lw $4,4*4($1) */
1061 MIPS32_LW(5, 5*4, 1), /* lw $5,5*4($1) */
1062 MIPS32_LW(6, 6*4, 1), /* lw $6,6*4($1) */
1063 MIPS32_LW(7, 7*4, 1), /* lw $7,7*4($1) */
1064 MIPS32_LW(8, 8*4, 1), /* lw $8,8*4($1) */
1065 MIPS32_LW(9, 9*4, 1), /* lw $9,9*4($1) */
1066 MIPS32_LW(10, 10*4, 1), /* lw $10,10*4($1) */
1067 MIPS32_LW(11, 11*4, 1), /* lw $11,11*4($1) */
1068 MIPS32_LW(12, 12*4, 1), /* lw $12,12*4($1) */
1069 MIPS32_LW(13, 13*4, 1), /* lw $13,13*4($1) */
1070 MIPS32_LW(14, 14*4, 1), /* lw $14,14*4($1) */
1071 MIPS32_LW(16, 16*4, 1), /* lw $16,16*4($1) */
1072 MIPS32_LW(17, 17*4, 1), /* lw $17,17*4($1) */
1073 MIPS32_LW(18, 18*4, 1), /* lw $18,18*4($1) */
1074 MIPS32_LW(19, 19*4, 1), /* lw $19,19*4($1) */
1075 MIPS32_LW(20, 20*4, 1), /* lw $20,20*4($1) */
1076 MIPS32_LW(21, 21*4, 1), /* lw $21,21*4($1) */
1077 MIPS32_LW(22, 22*4, 1), /* lw $22,22*4($1) */
1078 MIPS32_LW(23, 23*4, 1), /* lw $23,23*4($1) */
1079 MIPS32_LW(24, 24*4, 1), /* lw $24,24*4($1) */
1080 MIPS32_LW(25, 25*4, 1), /* lw $25,25*4($1) */
1081 MIPS32_LW(26, 26*4, 1), /* lw $26,26*4($1) */
1082 MIPS32_LW(27, 27*4, 1), /* lw $27,27*4($1) */
1083 MIPS32_LW(28, 28*4, 1), /* lw $28,28*4($1) */
1084 MIPS32_LW(29, 29*4, 1), /* lw $29,29*4($1) */
1085 MIPS32_LW(30, 30*4, 1), /* lw $30,30*4($1) */
1086 MIPS32_LW(31, 31*4, 1), /* lw $31,31*4($1) */
1088 MIPS32_LW(2, 32*4, 1), /* lw $2,32*4($1) */
1089 MIPS32_MTC0(2, 12, 0), /* move $2 to status */
1090 MIPS32_LW(2, 33*4, 1), /* lw $2,33*4($1) */
1091 MIPS32_MTLO(2), /* move $2 to lo */
1092 MIPS32_LW(2, 34*4, 1), /* lw $2,34*4($1) */
1093 MIPS32_MTHI(2), /* move $2 to hi */
1094 MIPS32_LW(2, 35*4, 1), /* lw $2,35*4($1) */
1095 MIPS32_MTC0(2, 8, 0), /* move $2 to badvaddr */
1096 MIPS32_LW(2, 36*4, 1), /* lw $2,36*4($1) */
1097 MIPS32_MTC0(2, 13, 0), /* move $2 to cause*/
1098 MIPS32_LW(2, 37*4, 1), /* lw $2,37*4($1) */
1099 MIPS32_MTC0(2, 24, 0), /* move $2 to depc (pc) */
1101 MIPS32_LW(2, 2*4, 1), /* lw $2,2*4($1) */
1102 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1103 MIPS32_B(NEG16(53)), /* b start */
1104 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1109 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1110 MIPS32NUMCOREREGS
, regs
, 0, NULL
, 1);
1115 int mips32_pracc_read_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1117 static const uint32_t code
[] = {
1119 MIPS32_MTC0(2, 31, 0), /* move $2 to COP0 DeSave */
1120 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $2 = MIPS32_PRACC_PARAM_OUT */
1121 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1122 MIPS32_SW(0, 0*4, 2), /* sw $0,0*4($2) */
1123 MIPS32_SW(1, 1*4, 2), /* sw $1,1*4($2) */
1124 MIPS32_SW(15, 15*4, 2), /* sw $15,15*4($2) */
1125 MIPS32_MFC0(2, 31, 0), /* move COP0 DeSave to $2 */
1126 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1127 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1128 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1129 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1130 MIPS32_SW(2, 0, 15), /* sw $2,($15) */
1131 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $1 = MIPS32_PRACC_PARAM_OUT */
1132 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1133 MIPS32_SW(2, 2*4, 1), /* sw $2,2*4($1) */
1134 MIPS32_SW(3, 3*4, 1), /* sw $3,3*4($1) */
1135 MIPS32_SW(4, 4*4, 1), /* sw $4,4*4($1) */
1136 MIPS32_SW(5, 5*4, 1), /* sw $5,5*4($1) */
1137 MIPS32_SW(6, 6*4, 1), /* sw $6,6*4($1) */
1138 MIPS32_SW(7, 7*4, 1), /* sw $7,7*4($1) */
1139 MIPS32_SW(8, 8*4, 1), /* sw $8,8*4($1) */
1140 MIPS32_SW(9, 9*4, 1), /* sw $9,9*4($1) */
1141 MIPS32_SW(10, 10*4, 1), /* sw $10,10*4($1) */
1142 MIPS32_SW(11, 11*4, 1), /* sw $11,11*4($1) */
1143 MIPS32_SW(12, 12*4, 1), /* sw $12,12*4($1) */
1144 MIPS32_SW(13, 13*4, 1), /* sw $13,13*4($1) */
1145 MIPS32_SW(14, 14*4, 1), /* sw $14,14*4($1) */
1146 MIPS32_SW(16, 16*4, 1), /* sw $16,16*4($1) */
1147 MIPS32_SW(17, 17*4, 1), /* sw $17,17*4($1) */
1148 MIPS32_SW(18, 18*4, 1), /* sw $18,18*4($1) */
1149 MIPS32_SW(19, 19*4, 1), /* sw $19,19*4($1) */
1150 MIPS32_SW(20, 20*4, 1), /* sw $20,20*4($1) */
1151 MIPS32_SW(21, 21*4, 1), /* sw $21,21*4($1) */
1152 MIPS32_SW(22, 22*4, 1), /* sw $22,22*4($1) */
1153 MIPS32_SW(23, 23*4, 1), /* sw $23,23*4($1) */
1154 MIPS32_SW(24, 24*4, 1), /* sw $24,24*4($1) */
1155 MIPS32_SW(25, 25*4, 1), /* sw $25,25*4($1) */
1156 MIPS32_SW(26, 26*4, 1), /* sw $26,26*4($1) */
1157 MIPS32_SW(27, 27*4, 1), /* sw $27,27*4($1) */
1158 MIPS32_SW(28, 28*4, 1), /* sw $28,28*4($1) */
1159 MIPS32_SW(29, 29*4, 1), /* sw $29,29*4($1) */
1160 MIPS32_SW(30, 30*4, 1), /* sw $30,30*4($1) */
1161 MIPS32_SW(31, 31*4, 1), /* sw $31,31*4($1) */
1163 MIPS32_MFC0(2, 12, 0), /* move status to $2 */
1164 MIPS32_SW(2, 32*4, 1), /* sw $2,32*4($1) */
1165 MIPS32_MFLO(2), /* move lo to $2 */
1166 MIPS32_SW(2, 33*4, 1), /* sw $2,33*4($1) */
1167 MIPS32_MFHI(2), /* move hi to $2 */
1168 MIPS32_SW(2, 34*4, 1), /* sw $2,34*4($1) */
1169 MIPS32_MFC0(2, 8, 0), /* move badvaddr to $2 */
1170 MIPS32_SW(2, 35*4, 1), /* sw $2,35*4($1) */
1171 MIPS32_MFC0(2, 13, 0), /* move cause to $2 */
1172 MIPS32_SW(2, 36*4, 1), /* sw $2,36*4($1) */
1173 MIPS32_MFC0(2, 24, 0), /* move depc (pc) to $2 */
1174 MIPS32_SW(2, 37*4, 1), /* sw $2,37*4($1) */
1176 MIPS32_LW(2, 0, 15), /* lw $2,($15) */
1177 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1178 MIPS32_B(NEG16(58)), /* b start */
1179 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1184 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1185 0, NULL
, MIPS32NUMCOREREGS
, regs
, 1);
1190 /* fastdata upload/download requires an initialized working area
1191 * to load the download code; it should not be called otherwise
1192 * fetch order from the fastdata area
1197 int mips32_pracc_fastdata_xfer(struct mips_ejtag
*ejtag_info
, struct working_area
*source
,
1198 int write_t
, uint32_t addr
, int count
, uint32_t *buf
)
1200 uint32_t handler_code
[] = {
1201 /* caution when editing, table is modified below */
1202 /* r15 points to the start of this code */
1203 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1204 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1205 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1206 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1207 /* start of fastdata area in t0 */
1208 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA
)),
1209 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA
)),
1210 MIPS32_LW(9, 0, 8), /* start addr in t1 */
1211 MIPS32_LW(10, 0, 8), /* end addr to t2 */
1213 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
1214 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
1215 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
1216 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
1218 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1219 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1220 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1221 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1223 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT
)),
1224 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT
)),
1225 MIPS32_JR(15), /* jr start */
1226 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1229 uint32_t jmp_code
[] = {
1230 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1231 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
1232 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
1233 MIPS32_JR(15), /* jump to ram program */
1238 uint32_t val
, ejtag_ctrl
, address
;
1240 if (source
->size
< MIPS32_FASTDATA_HANDLER_SIZE
)
1241 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1244 handler_code
[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
1245 handler_code
[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
1247 handler_code
[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
1248 handler_code
[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
1251 /* write program into RAM */
1252 if (write_t
!= ejtag_info
->fast_access_save
) {
1253 mips32_pracc_write_mem32(ejtag_info
, source
->address
, ARRAY_SIZE(handler_code
), handler_code
);
1254 /* save previous operation to speed to any consecutive read/writes */
1255 ejtag_info
->fast_access_save
= write_t
;
1258 LOG_DEBUG("%s using 0x%.8" PRIx32
" for write handler", __func__
, source
->address
);
1260 jmp_code
[1] |= UPPER16(source
->address
);
1261 jmp_code
[2] |= LOWER16(source
->address
);
1263 for (i
= 0; i
< (int) ARRAY_SIZE(jmp_code
); i
++) {
1264 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1265 if (retval
!= ERROR_OK
)
1268 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_DATA
);
1269 mips_ejtag_drscan_32_out(ejtag_info
, jmp_code
[i
]);
1271 /* Clear the access pending bit (let the processor eat!) */
1272 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
1273 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
1274 mips_ejtag_drscan_32_out(ejtag_info
, ejtag_ctrl
);
1277 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1278 if (retval
!= ERROR_OK
)
1281 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1283 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1284 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1285 if (retval
!= ERROR_OK
)
1288 if (address
!= MIPS32_PRACC_FASTDATA_AREA
)
1291 /* wait PrAcc pending bit for FASTDATA write */
1292 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1293 if (retval
!= ERROR_OK
)
1296 /* Send the load start address */
1298 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_FASTDATA
);
1299 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1301 /* Send the load end address */
1302 val
= addr
+ (count
- 1) * 4;
1303 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1305 for (i
= 0; i
< count
; i
++) {
1306 retval
= mips_ejtag_fastdata_scan(ejtag_info
, write_t
, buf
++);
1307 if (retval
!= ERROR_OK
)
1311 retval
= jtag_execute_queue();
1312 if (retval
!= ERROR_OK
) {
1313 LOG_ERROR("fastdata load failed");
1317 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1318 if (retval
!= ERROR_OK
)
1322 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1323 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1324 if (retval
!= ERROR_OK
)
1327 if (address
!= MIPS32_PRACC_TEXT
)
1328 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)