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 /* save to our debug stack */
169 data
= ctx
->stack
[--ctx
->stack_offset
];
171 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
172 * to start of debug vector */
174 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32
"", address
);
175 return ERROR_JTAG_DEVICE_ERROR
;
178 /* Send the data out */
179 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_DATA
);
180 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, data
);
182 /* Clear the access pending bit (let the processor eat!) */
183 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
184 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_CONTROL
);
185 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, ejtag_ctrl
);
187 return jtag_execute_queue();
190 static int mips32_pracc_exec_write(struct mips32_pracc_context
*ctx
, uint32_t address
)
192 uint32_t ejtag_ctrl
, data
;
194 struct mips_ejtag
*ejtag_info
= ctx
->ejtag_info
;
197 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_DATA
);
198 retval
= mips_ejtag_drscan_32(ctx
->ejtag_info
, &data
);
199 if (retval
!= ERROR_OK
)
202 /* Clear access pending bit */
203 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
204 mips_ejtag_set_instr(ctx
->ejtag_info
, EJTAG_INST_CONTROL
);
205 mips_ejtag_drscan_32_out(ctx
->ejtag_info
, ejtag_ctrl
);
207 retval
= jtag_execute_queue();
208 if (retval
!= ERROR_OK
)
211 if ((address
>= MIPS32_PRACC_PARAM_IN
)
212 && (address
<= MIPS32_PRACC_PARAM_IN
+ ctx
->num_iparam
* 4)) {
213 offset
= (address
- MIPS32_PRACC_PARAM_IN
) / 4;
214 ctx
->local_iparam
[offset
] = data
;
215 } else if ((address
>= MIPS32_PRACC_PARAM_OUT
)
216 && (address
<= MIPS32_PRACC_PARAM_OUT
+ ctx
->num_oparam
* 4)) {
217 offset
= (address
- MIPS32_PRACC_PARAM_OUT
) / 4;
218 ctx
->local_oparam
[offset
] = data
;
219 } else if (address
== MIPS32_PRACC_STACK
) {
220 /* save data onto our stack */
221 ctx
->stack
[ctx
->stack_offset
++] = data
;
223 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32
"", address
);
224 return ERROR_JTAG_DEVICE_ERROR
;
230 int mips32_pracc_exec(struct mips_ejtag
*ejtag_info
, int code_len
, const uint32_t *code
,
231 int num_param_in
, uint32_t *param_in
, int num_param_out
, uint32_t *param_out
, int cycle
)
234 uint32_t address
, data
;
235 struct mips32_pracc_context ctx
;
239 ctx
.local_iparam
= param_in
;
240 ctx
.local_oparam
= param_out
;
241 ctx
.num_iparam
= num_param_in
;
242 ctx
.num_oparam
= num_param_out
;
244 ctx
.code_len
= code_len
;
245 ctx
.ejtag_info
= ejtag_info
;
246 ctx
.stack_offset
= 0;
249 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
250 if (retval
!= ERROR_OK
)
254 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
255 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
256 if (retval
!= ERROR_OK
)
259 /* Check for read or write */
260 if (ejtag_ctrl
& EJTAG_CTRL_PRNW
) {
261 retval
= mips32_pracc_exec_write(&ctx
, address
);
262 if (retval
!= ERROR_OK
)
265 /* Check to see if its reading at the debug vector. The first pass through
266 * the module is always read at the vector, so the first one we allow. When
267 * the second read from the vector occurs we are done and just exit. */
268 if ((address
== MIPS32_PRACC_TEXT
) && (pass
++))
271 retval
= mips32_pracc_exec_read(&ctx
, address
);
272 if (retval
!= ERROR_OK
)
280 /* stack sanity check */
281 if (ctx
.stack_offset
!= 0)
282 LOG_DEBUG("Pracc Stack not zero");
287 int mips32_pracc_read_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
291 return mips32_pracc_read_mem8(ejtag_info
, addr
, count
, (uint8_t *)buf
);
293 return mips32_pracc_read_mem16(ejtag_info
, addr
, count
, (uint16_t *)buf
);
296 return mips32_pracc_read_u32(ejtag_info
, addr
, (uint32_t *)buf
);
298 return mips32_pracc_read_mem32(ejtag_info
, addr
, count
, (uint32_t *)buf
);
304 static int mips32_pracc_read_mem32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint32_t *buf
)
306 static const uint32_t code
[] = {
308 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
309 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
310 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
311 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
312 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
313 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
314 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
316 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
317 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
318 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
319 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
320 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
321 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
323 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
326 MIPS32_LW(8, 0, 9), /* lw $8,0($9), Load $8 with the word @mem[$9] */
327 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
329 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
330 MIPS32_ADDI(9, 9, 4), /* $1 += 4 */
331 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
333 MIPS32_B(NEG16(8)), /* b loop */
336 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
337 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
338 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
339 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
340 MIPS32_B(NEG16(27)), /* b start */
341 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
344 int retval
= ERROR_OK
;
347 uint32_t param_in
[2];
357 param_in
[1] = blocksize
;
359 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
360 ARRAY_SIZE(param_in
), param_in
, blocksize
, &buf
[wordsread
], 1);
361 if (retval
!= ERROR_OK
)
365 addr
+= blocksize
*sizeof(uint32_t);
366 wordsread
+= blocksize
;
372 static int mips32_pracc_read_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
374 static const uint32_t code
[] = {
376 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
377 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
378 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
379 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
381 MIPS32_LW(8, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
), 15), /* load R8 @ param_in[0] = address */
383 MIPS32_LW(8, 0, 8), /* lw $8,0($8), Load $8 with the word @mem[$8] */
384 MIPS32_SW(8, NEG16(MIPS32_PRACC_STACK
- MIPS32_PRACC_PARAM_OUT
), 15), /* store R8 @ param_out[0] */
386 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
387 MIPS32_B(NEG16(9)), /* b start */
388 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
391 int retval
= ERROR_OK
;
392 uint32_t param_in
[1];
396 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
397 ARRAY_SIZE(param_in
), param_in
, 1, buf
, 1);
398 if (retval
!= ERROR_OK
)
404 static int mips32_pracc_read_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
406 static const uint32_t code
[] = {
408 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
409 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
410 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
411 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
412 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
413 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
414 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
416 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
417 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
418 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
419 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
420 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
421 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
423 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
426 MIPS32_LHU(8, 0, 9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
427 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
429 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
430 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
431 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
432 MIPS32_B(NEG16(8)), /* b loop */
435 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
436 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
437 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
438 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
439 MIPS32_B(NEG16(27)), /* b start */
440 MIPS32_MFC0(15, 30, 0), /* move COP0 DeSave to $15 */
443 /* TODO remove array */
444 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
445 if (param_out
== NULL
) {
446 LOG_ERROR("Out of memory");
450 int retval
= ERROR_OK
;
453 uint32_t param_in
[2];
461 param_in
[1] = blocksize
;
463 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
464 ARRAY_SIZE(param_in
), param_in
, blocksize
, ¶m_out
[hwordsread
], 1);
466 if (retval
!= ERROR_OK
)
470 addr
+= blocksize
*sizeof(uint16_t);
471 hwordsread
+= blocksize
;
475 for (i
= 0; i
< hwordsread
; i
++)
476 buf
[i
] = param_out
[i
];
482 static int mips32_pracc_read_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
484 static const uint32_t code
[] = {
486 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
487 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
488 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
489 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
490 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
491 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
492 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
494 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
495 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
496 MIPS32_LW(9, 0, 8), /* $9 = mem[$8]; read addr */
497 MIPS32_LW(10, 4, 8), /* $10 = mem[$8 + 4]; read count */
498 MIPS32_LUI(11, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
499 MIPS32_ORI(11, 11, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
501 MIPS32_BEQ(0, 10, 8), /* beq 0, $10, end */
504 MIPS32_LBU(8, 0, 9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
505 MIPS32_SW(8, 0, 11), /* sw $8,0($11) */
507 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
508 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
509 MIPS32_ADDI(11, 11, 4), /* $11 += 4 */
510 MIPS32_B(NEG16(8)), /* b loop */
513 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
514 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
515 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
516 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
517 MIPS32_B(NEG16(27)), /* b start */
518 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
521 /* TODO remove array */
522 uint32_t *param_out
= malloc(count
* sizeof(uint32_t));
523 if (param_out
== NULL
) {
524 LOG_ERROR("Out of memory");
528 int retval
= ERROR_OK
;
530 uint32_t param_in
[2];
539 param_in
[1] = blocksize
;
541 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
542 ARRAY_SIZE(param_in
), param_in
, count
, ¶m_out
[bytesread
], 1);
544 if (retval
!= ERROR_OK
)
549 bytesread
+= blocksize
;
552 for (i
= 0; i
< bytesread
; i
++)
553 buf
[i
] = param_out
[i
];
559 int mips32_cp0_read(struct mips_ejtag
*ejtag_info
, uint32_t *val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
562 * Do not make this code static, but regenerate it every time,
563 * as 5th element has to be changed to add parameters
567 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
568 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
569 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
570 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
571 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
573 /* 5 */ MIPS32_MFC0(8, 0, 0), /* move COP0 [cp0_reg select] to $8 */
575 MIPS32_LUI(9, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $11 = MIPS32_PRACC_PARAM_OUT */
576 MIPS32_ORI(9, 9, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
577 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
579 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
580 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
581 MIPS32_B(NEG16(12)), /* b start */
582 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
586 * Note that our input parametes cp0_reg and cp0_sel
587 * are numbers (not gprs) which make part of mfc0 instruction opcode.
589 * These are not fix, but can be different for each mips32_cp0_read() function call,
590 * and that is why we must insert them directly into opcode,
591 * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
592 * and put them into the gprs later from MIPS32_PRACC_STACK
593 * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
594 * but plain (immediate) number.
596 * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
597 * In order to insert our parameters, we must change rd and funct fields.
599 code
[5] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct of MIPS32_R_INST macro */
601 /* TODO remove array */
602 uint32_t *param_out
= val
;
605 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 0, NULL
, 1, param_out
, 1);
610 int mips32_cp0_write(struct mips_ejtag
*ejtag_info
,
611 uint32_t val
, uint32_t cp0_reg
, uint32_t cp0_sel
)
615 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
616 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
617 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
618 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
619 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
621 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
622 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
623 MIPS32_LW(9, 0, 8), /* Load write val to $9 */
625 /* 8 */ MIPS32_MTC0(9, 0, 0), /* move $9 to COP0 [cp0_reg select] */
627 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
628 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
629 MIPS32_B(NEG16(12)), /* b start */
630 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
634 * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
635 * In order to insert our parameters, we must change rd and funct fields.
637 code
[8] |= (cp0_reg
<< 11) | cp0_sel
; /* change rd and funct fields of MIPS32_R_INST macro */
639 /* TODO remove array */
640 uint32_t *param_in
= malloc(1 * sizeof(uint32_t));
644 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 1, param_in
, 0, NULL
, 1);
652 * \b mips32_pracc_sync_cache
654 * Synchronize Caches to Make Instruction Writes Effective
655 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
656 * Document Number: MD00086, Revision 2.00, June 9, 2003)
658 * When the instruction stream is written, the SYNCI instruction should be used
659 * in conjunction with other instructions to make the newly-written instructions effective.
662 * A program that loads another program into memory is actually writing the D- side cache.
663 * The instructions it has loaded can't be executed until they reach the I-cache.
665 * After the instructions have been written, the loader should arrange
666 * to write back any containing D-cache line and invalidate any locations
667 * already in the I-cache.
669 * You can do that with cache instructions, but those instructions are only available in kernel mode,
670 * and a loader writing instructions for the use of its own process need not be privileged software.
672 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
673 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
674 * That is, it arranges a D-cache write-back and an I-cache invalidate.
676 * To employ synci at user level, you need to know the size of a cache line,
677 * and that can be obtained with a rdhwr SYNCI_Step
678 * from one of the standard “hardware registers”.
680 static int mips32_pracc_sync_cache(struct mips_ejtag
*ejtag_info
,
681 uint32_t start_addr
, uint32_t end_addr
)
683 static const uint32_t code
[] = {
685 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
686 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
687 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
688 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
689 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
690 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
691 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
693 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
694 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
695 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
696 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
698 MIPS32_RDHWR(11, MIPS32_SYNCI_STEP
), /* $11 = MIPS32_SYNCI_STEP */
699 MIPS32_BEQ(11, 0, 6), /* beq $11, $0, end */
702 MIPS32_SYNCI(0, 9), /* synci 0($9) */
703 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 # $8 = $10 < $9 ? 1 : 0 */
704 MIPS32_BNE(8, 0, NEG16(3)), /* bne $8, $0, synci_loop */
705 MIPS32_ADDU(9, 9, 11), /* $9 += MIPS32_SYNCI_STEP */
708 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
709 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
710 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
711 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
712 MIPS32_B(NEG16(24)), /* b start */
713 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
716 /* TODO remove array */
717 uint32_t *param_in
= malloc(2 * sizeof(uint32_t));
719 param_in
[0] = start_addr
;
720 param_in
[1] = end_addr
;
722 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 2, param_in
, 0, NULL
, 1);
730 * \b mips32_pracc_clean_invalidate_cache
732 * Writeback D$ and Invalidate I$
733 * so that the instructions written can be visible to CPU
735 static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag
*ejtag_info
,
736 uint32_t start_addr
, uint32_t end_addr
)
738 static const uint32_t code
[] = {
740 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
741 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
742 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
743 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
744 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
745 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
746 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
748 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
749 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
750 MIPS32_LW(9, 0, 8), /* Load write start_addr to $9 */
751 MIPS32_LW(10, 4, 8), /* Load write end_addr to $10 */
752 MIPS32_LW(11, 8, 8), /* Load write clsiz to $11 */
755 MIPS32_SLTU(8, 10, 9), /* sltu $8, $10, $9 : $8 <- $10 < $9 ? */
756 MIPS32_BGTZ(8, 6), /* bgtz $8, end */
759 MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK
, 0, 9), /* cache Hit_Writeback_D, 0($9) */
760 MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE
, 0, 9), /* cache Hit_Invalidate_I, 0($9) */
762 MIPS32_ADDU(9, 9, 11), /* $9 += $11 */
764 MIPS32_B(NEG16(7)), /* b cache_loop */
767 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
768 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
769 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
770 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
771 MIPS32_B(NEG16(25)), /* b start */
772 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
776 * Find cache line size in bytes
781 mips32_cp0_read(ejtag_info
, &conf
, 16, 1);
782 dl
= (conf
& MIPS32_CONFIG1_DL_MASK
) >> MIPS32_CONFIG1_DL_SHIFT
;
784 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... */
787 /* TODO remove array */
788 uint32_t *param_in
= malloc(3 * sizeof(uint32_t));
790 param_in
[0] = start_addr
;
791 param_in
[1] = end_addr
;
794 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
, 3, param_in
, 0, NULL
, 1);
802 int mips32_pracc_write_mem(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int size
, int count
, void *buf
)
808 retval
= mips32_pracc_write_mem8(ejtag_info
, addr
, count
, (uint8_t *)buf
);
811 retval
= mips32_pracc_write_mem16(ejtag_info
, addr
, count
, (uint16_t *)buf
);
815 retval
= mips32_pracc_write_u32(ejtag_info
, addr
, (uint32_t *)buf
);
817 retval
= mips32_pracc_write_mem32(ejtag_info
, addr
, count
, (uint32_t *)buf
);
824 * If we are in the cachable regoion and cache is activated,
825 * we must clean D$ + invalidate I$ after we did the write,
826 * so that changes do not continue to live only in D$, but to be
827 * replicated in I$ also (maybe we wrote the istructions)
832 if ((KSEGX(addr
) == KSEG1
) || ((addr
>= 0xff200000) && (addr
<= 0xff3fffff)))
833 return retval
; /*Nothing to do*/
835 mips32_cp0_read(ejtag_info
, &conf
, 16, 0);
837 switch (KSEGX(addr
)) {
839 cached
= (conf
& MIPS32_CONFIG0_KU_MASK
) >> MIPS32_CONFIG0_KU_SHIFT
;
842 cached
= (conf
& MIPS32_CONFIG0_K0_MASK
) >> MIPS32_CONFIG0_K0_SHIFT
;
846 cached
= (conf
& MIPS32_CONFIG0_K23_MASK
) >> MIPS32_CONFIG0_K23_SHIFT
;
854 * Check cachablitiy bits coherency algorithm -
855 * is the region cacheable or uncached.
856 * If cacheable we have to synchronize the cache
859 uint32_t start_addr
, end_addr
;
863 end_addr
= addr
+ count
* size
;
865 /** select cache synchronisation mechanism based on Architecture Release */
866 rel
= (conf
& MIPS32_CONFIG0_AR_MASK
) >> MIPS32_CONFIG0_AR_SHIFT
;
868 case MIPS32_ARCH_REL1
:
869 /* MIPS32/64 Release 1 - we must use cache instruction */
870 mips32_pracc_clean_invalidate_cache(ejtag_info
, start_addr
, end_addr
);
872 case MIPS32_ARCH_REL2
:
873 /* MIPS32/64 Release 2 - we can use synci instruction */
874 mips32_pracc_sync_cache(ejtag_info
, start_addr
, end_addr
);
885 static int mips32_pracc_write_mem32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint32_t *buf
)
887 static const uint32_t code
[] = {
889 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
890 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
891 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
892 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
893 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
894 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
895 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
897 MIPS32_ADDI(8, 15, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)), /* $8= MIPS32_PRACC_PARAM_IN */
898 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
899 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
900 MIPS32_ADDI(8, 8, 8), /* $8 += 8 beginning of data */
903 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
904 MIPS32_SW(11, 0, 9), /* sw $11,0($9) */
906 MIPS32_ADDI(9, 9, 4), /* $9 += 4 */
907 MIPS32_BNE(10, 9, NEG16(4)), /* bne $10, $9, loop */
908 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
911 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
912 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
913 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
914 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
915 MIPS32_B(NEG16(21)), /* b start */
916 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
919 /* TODO remove array */
920 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
922 param_in
[1] = addr
+ (count
* sizeof(uint32_t)); /* last address */
924 memcpy(¶m_in
[2], buf
, count
* sizeof(uint32_t));
927 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
928 count
+ 2, param_in
, 0, NULL
, 1);
935 static int mips32_pracc_write_u32(struct mips_ejtag
*ejtag_info
, uint32_t addr
, uint32_t *buf
)
937 static const uint32_t code
[] = {
939 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
940 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
941 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
942 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
943 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
945 MIPS32_LW(8, NEG16((MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
)-4), 15), /* load R8 @ param_in[1] = data */
946 MIPS32_LW(9, NEG16(MIPS32_PRACC_STACK
-MIPS32_PRACC_PARAM_IN
), 15), /* load R9 @ param_in[0] = address */
948 MIPS32_SW(8, 0, 9), /* sw $8,0($9) */
950 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
951 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
952 MIPS32_B(NEG16(11)), /* b start */
953 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
956 /* TODO remove array */
957 uint32_t param_in
[1 + 1];
961 return mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
962 ARRAY_SIZE(param_in
), param_in
, 0, NULL
, 1);
965 static int mips32_pracc_write_mem16(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint16_t *buf
)
967 static const uint32_t code
[] = {
969 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
970 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
971 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
972 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
973 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
974 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
975 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
977 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
978 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
979 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
980 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
981 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
983 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
986 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
987 MIPS32_SH(11, 0, 9), /* sh $11,0($9) */
989 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
990 MIPS32_ADDI(9, 9, 2), /* $9 += 2 */
991 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
993 MIPS32_B(NEG16(8)), /* b loop */
996 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
997 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
998 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
999 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1000 MIPS32_B(NEG16(26)), /* b start */
1001 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1004 /* TODO remove array */
1005 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
1008 param_in
[1] = count
;
1010 for (i
= 0; i
< count
; i
++)
1011 param_in
[i
+ 2] = buf
[i
];
1014 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1015 count
+ 2, param_in
, 0, NULL
, 1);
1022 static int mips32_pracc_write_mem8(struct mips_ejtag
*ejtag_info
, uint32_t addr
, int count
, uint8_t *buf
)
1024 static const uint32_t code
[] = {
1026 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1027 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1028 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1029 MIPS32_SW(8, 0, 15), /* sw $8,($15) */
1030 MIPS32_SW(9, 0, 15), /* sw $9,($15) */
1031 MIPS32_SW(10, 0, 15), /* sw $10,($15) */
1032 MIPS32_SW(11, 0, 15), /* sw $11,($15) */
1034 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $8 = MIPS32_PRACC_PARAM_IN */
1035 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1036 MIPS32_LW(9, 0, 8), /* Load write addr to $9 */
1037 MIPS32_LW(10, 4, 8), /* Load write count to $10 */
1038 MIPS32_ADDI(8, 8, 8), /* $8 += 8 */
1040 MIPS32_BEQ(0, 10, 8), /* beq $0, $10, end */
1043 MIPS32_LW(11, 0, 8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
1044 MIPS32_SB(11, 0, 9), /* sb $11,0($9) */
1046 MIPS32_ADDI(10, 10, NEG16(1)), /* $10-- */
1047 MIPS32_ADDI(9, 9, 1), /* $9 += 1 */
1048 MIPS32_ADDI(8, 8, 4), /* $8 += 4 */
1050 MIPS32_B(NEG16(8)), /* b loop */
1053 MIPS32_LW(11, 0, 15), /* lw $11,($15) */
1054 MIPS32_LW(10, 0, 15), /* lw $10,($15) */
1055 MIPS32_LW(9, 0, 15), /* lw $9,($15) */
1056 MIPS32_LW(8, 0, 15), /* lw $8,($15) */
1057 MIPS32_B(NEG16(26)), /* b start */
1058 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1061 /* TODO remove array */
1062 uint32_t *param_in
= malloc((count
+ 2) * sizeof(uint32_t));
1066 param_in
[1] = count
;
1068 for (i
= 0; i
< count
; i
++)
1069 param_in
[i
+ 2] = buf
[i
];
1071 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1072 count
+ 2, param_in
, 0, NULL
, 1);
1079 int mips32_pracc_write_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1081 static const uint32_t code
[] = {
1083 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $2 = MIPS32_PRACC_PARAM_IN */
1084 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1085 MIPS32_LW(1, 1*4, 2), /* lw $1,1*4($2) */
1086 MIPS32_LW(15, 15*4, 2), /* lw $15,15*4($2) */
1087 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1088 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1089 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1090 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1091 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_IN
)), /* $1 = MIPS32_PRACC_PARAM_IN */
1092 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_IN
)),
1093 MIPS32_LW(3, 3*4, 1), /* lw $3,3*4($1) */
1094 MIPS32_LW(4, 4*4, 1), /* lw $4,4*4($1) */
1095 MIPS32_LW(5, 5*4, 1), /* lw $5,5*4($1) */
1096 MIPS32_LW(6, 6*4, 1), /* lw $6,6*4($1) */
1097 MIPS32_LW(7, 7*4, 1), /* lw $7,7*4($1) */
1098 MIPS32_LW(8, 8*4, 1), /* lw $8,8*4($1) */
1099 MIPS32_LW(9, 9*4, 1), /* lw $9,9*4($1) */
1100 MIPS32_LW(10, 10*4, 1), /* lw $10,10*4($1) */
1101 MIPS32_LW(11, 11*4, 1), /* lw $11,11*4($1) */
1102 MIPS32_LW(12, 12*4, 1), /* lw $12,12*4($1) */
1103 MIPS32_LW(13, 13*4, 1), /* lw $13,13*4($1) */
1104 MIPS32_LW(14, 14*4, 1), /* lw $14,14*4($1) */
1105 MIPS32_LW(16, 16*4, 1), /* lw $16,16*4($1) */
1106 MIPS32_LW(17, 17*4, 1), /* lw $17,17*4($1) */
1107 MIPS32_LW(18, 18*4, 1), /* lw $18,18*4($1) */
1108 MIPS32_LW(19, 19*4, 1), /* lw $19,19*4($1) */
1109 MIPS32_LW(20, 20*4, 1), /* lw $20,20*4($1) */
1110 MIPS32_LW(21, 21*4, 1), /* lw $21,21*4($1) */
1111 MIPS32_LW(22, 22*4, 1), /* lw $22,22*4($1) */
1112 MIPS32_LW(23, 23*4, 1), /* lw $23,23*4($1) */
1113 MIPS32_LW(24, 24*4, 1), /* lw $24,24*4($1) */
1114 MIPS32_LW(25, 25*4, 1), /* lw $25,25*4($1) */
1115 MIPS32_LW(26, 26*4, 1), /* lw $26,26*4($1) */
1116 MIPS32_LW(27, 27*4, 1), /* lw $27,27*4($1) */
1117 MIPS32_LW(28, 28*4, 1), /* lw $28,28*4($1) */
1118 MIPS32_LW(29, 29*4, 1), /* lw $29,29*4($1) */
1119 MIPS32_LW(30, 30*4, 1), /* lw $30,30*4($1) */
1120 MIPS32_LW(31, 31*4, 1), /* lw $31,31*4($1) */
1122 MIPS32_LW(2, 32*4, 1), /* lw $2,32*4($1) */
1123 MIPS32_MTC0(2, 12, 0), /* move $2 to status */
1124 MIPS32_LW(2, 33*4, 1), /* lw $2,33*4($1) */
1125 MIPS32_MTLO(2), /* move $2 to lo */
1126 MIPS32_LW(2, 34*4, 1), /* lw $2,34*4($1) */
1127 MIPS32_MTHI(2), /* move $2 to hi */
1128 MIPS32_LW(2, 35*4, 1), /* lw $2,35*4($1) */
1129 MIPS32_MTC0(2, 8, 0), /* move $2 to badvaddr */
1130 MIPS32_LW(2, 36*4, 1), /* lw $2,36*4($1) */
1131 MIPS32_MTC0(2, 13, 0), /* move $2 to cause*/
1132 MIPS32_LW(2, 37*4, 1), /* lw $2,37*4($1) */
1133 MIPS32_MTC0(2, 24, 0), /* move $2 to depc (pc) */
1135 MIPS32_LW(2, 2*4, 1), /* lw $2,2*4($1) */
1136 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1137 MIPS32_B(NEG16(53)), /* b start */
1138 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1143 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1144 MIPS32NUMCOREREGS
, regs
, 0, NULL
, 1);
1149 int mips32_pracc_read_regs(struct mips_ejtag
*ejtag_info
, uint32_t *regs
)
1151 static const uint32_t code
[] = {
1153 MIPS32_MTC0(2, 31, 0), /* move $2 to COP0 DeSave */
1154 MIPS32_LUI(2, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $2 = MIPS32_PRACC_PARAM_OUT */
1155 MIPS32_ORI(2, 2, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1156 MIPS32_SW(0, 0*4, 2), /* sw $0,0*4($2) */
1157 MIPS32_SW(1, 1*4, 2), /* sw $1,1*4($2) */
1158 MIPS32_SW(15, 15*4, 2), /* sw $15,15*4($2) */
1159 MIPS32_MFC0(2, 31, 0), /* move COP0 DeSave to $2 */
1160 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1161 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_STACK
)), /* $15 = MIPS32_PRACC_STACK */
1162 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_STACK
)),
1163 MIPS32_SW(1, 0, 15), /* sw $1,($15) */
1164 MIPS32_SW(2, 0, 15), /* sw $2,($15) */
1165 MIPS32_LUI(1, UPPER16(MIPS32_PRACC_PARAM_OUT
)), /* $1 = MIPS32_PRACC_PARAM_OUT */
1166 MIPS32_ORI(1, 1, LOWER16(MIPS32_PRACC_PARAM_OUT
)),
1167 MIPS32_SW(2, 2*4, 1), /* sw $2,2*4($1) */
1168 MIPS32_SW(3, 3*4, 1), /* sw $3,3*4($1) */
1169 MIPS32_SW(4, 4*4, 1), /* sw $4,4*4($1) */
1170 MIPS32_SW(5, 5*4, 1), /* sw $5,5*4($1) */
1171 MIPS32_SW(6, 6*4, 1), /* sw $6,6*4($1) */
1172 MIPS32_SW(7, 7*4, 1), /* sw $7,7*4($1) */
1173 MIPS32_SW(8, 8*4, 1), /* sw $8,8*4($1) */
1174 MIPS32_SW(9, 9*4, 1), /* sw $9,9*4($1) */
1175 MIPS32_SW(10, 10*4, 1), /* sw $10,10*4($1) */
1176 MIPS32_SW(11, 11*4, 1), /* sw $11,11*4($1) */
1177 MIPS32_SW(12, 12*4, 1), /* sw $12,12*4($1) */
1178 MIPS32_SW(13, 13*4, 1), /* sw $13,13*4($1) */
1179 MIPS32_SW(14, 14*4, 1), /* sw $14,14*4($1) */
1180 MIPS32_SW(16, 16*4, 1), /* sw $16,16*4($1) */
1181 MIPS32_SW(17, 17*4, 1), /* sw $17,17*4($1) */
1182 MIPS32_SW(18, 18*4, 1), /* sw $18,18*4($1) */
1183 MIPS32_SW(19, 19*4, 1), /* sw $19,19*4($1) */
1184 MIPS32_SW(20, 20*4, 1), /* sw $20,20*4($1) */
1185 MIPS32_SW(21, 21*4, 1), /* sw $21,21*4($1) */
1186 MIPS32_SW(22, 22*4, 1), /* sw $22,22*4($1) */
1187 MIPS32_SW(23, 23*4, 1), /* sw $23,23*4($1) */
1188 MIPS32_SW(24, 24*4, 1), /* sw $24,24*4($1) */
1189 MIPS32_SW(25, 25*4, 1), /* sw $25,25*4($1) */
1190 MIPS32_SW(26, 26*4, 1), /* sw $26,26*4($1) */
1191 MIPS32_SW(27, 27*4, 1), /* sw $27,27*4($1) */
1192 MIPS32_SW(28, 28*4, 1), /* sw $28,28*4($1) */
1193 MIPS32_SW(29, 29*4, 1), /* sw $29,29*4($1) */
1194 MIPS32_SW(30, 30*4, 1), /* sw $30,30*4($1) */
1195 MIPS32_SW(31, 31*4, 1), /* sw $31,31*4($1) */
1197 MIPS32_MFC0(2, 12, 0), /* move status to $2 */
1198 MIPS32_SW(2, 32*4, 1), /* sw $2,32*4($1) */
1199 MIPS32_MFLO(2), /* move lo to $2 */
1200 MIPS32_SW(2, 33*4, 1), /* sw $2,33*4($1) */
1201 MIPS32_MFHI(2), /* move hi to $2 */
1202 MIPS32_SW(2, 34*4, 1), /* sw $2,34*4($1) */
1203 MIPS32_MFC0(2, 8, 0), /* move badvaddr to $2 */
1204 MIPS32_SW(2, 35*4, 1), /* sw $2,35*4($1) */
1205 MIPS32_MFC0(2, 13, 0), /* move cause to $2 */
1206 MIPS32_SW(2, 36*4, 1), /* sw $2,36*4($1) */
1207 MIPS32_MFC0(2, 24, 0), /* move depc (pc) to $2 */
1208 MIPS32_SW(2, 37*4, 1), /* sw $2,37*4($1) */
1210 MIPS32_LW(2, 0, 15), /* lw $2,($15) */
1211 MIPS32_LW(1, 0, 15), /* lw $1,($15) */
1212 MIPS32_B(NEG16(58)), /* b start */
1213 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1218 retval
= mips32_pracc_exec(ejtag_info
, ARRAY_SIZE(code
), code
,
1219 0, NULL
, MIPS32NUMCOREREGS
, regs
, 1);
1224 /* fastdata upload/download requires an initialized working area
1225 * to load the download code; it should not be called otherwise
1226 * fetch order from the fastdata area
1231 int mips32_pracc_fastdata_xfer(struct mips_ejtag
*ejtag_info
, struct working_area
*source
,
1232 int write_t
, uint32_t addr
, int count
, uint32_t *buf
)
1234 uint32_t handler_code
[] = {
1235 /* caution when editing, table is modified below */
1236 /* r15 points to the start of this code */
1237 MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1238 MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1239 MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1240 MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1241 /* start of fastdata area in t0 */
1242 MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA
)),
1243 MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA
)),
1244 MIPS32_LW(9, 0, 8), /* start addr in t1 */
1245 MIPS32_LW(10, 0, 8), /* end addr to t2 */
1247 /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
1248 /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
1249 MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
1250 MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
1252 MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE
- 4, 15),
1253 MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE
- 8, 15),
1254 MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE
- 12, 15),
1255 MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE
- 16, 15),
1257 MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT
)),
1258 MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT
)),
1259 MIPS32_JR(15), /* jr start */
1260 MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
1263 uint32_t jmp_code
[] = {
1264 MIPS32_MTC0(15, 31, 0), /* move $15 to COP0 DeSave */
1265 /* 1 */ MIPS32_LUI(15, 0), /* addr of working area added below */
1266 /* 2 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
1267 MIPS32_JR(15), /* jump to ram program */
1272 uint32_t val
, ejtag_ctrl
, address
;
1274 if (source
->size
< MIPS32_FASTDATA_HANDLER_SIZE
)
1275 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1278 handler_code
[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
1279 handler_code
[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
1281 handler_code
[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
1282 handler_code
[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
1285 /* write program into RAM */
1286 if (write_t
!= ejtag_info
->fast_access_save
) {
1287 mips32_pracc_write_mem32(ejtag_info
, source
->address
, ARRAY_SIZE(handler_code
), handler_code
);
1288 /* save previous operation to speed to any consecutive read/writes */
1289 ejtag_info
->fast_access_save
= write_t
;
1292 LOG_DEBUG("%s using 0x%.8" PRIx32
" for write handler", __func__
, source
->address
);
1294 jmp_code
[1] |= UPPER16(source
->address
);
1295 jmp_code
[2] |= LOWER16(source
->address
);
1297 for (i
= 0; i
< (int) ARRAY_SIZE(jmp_code
); i
++) {
1298 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1299 if (retval
!= ERROR_OK
)
1302 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_DATA
);
1303 mips_ejtag_drscan_32_out(ejtag_info
, jmp_code
[i
]);
1305 /* Clear the access pending bit (let the processor eat!) */
1306 ejtag_ctrl
= ejtag_info
->ejtag_ctrl
& ~EJTAG_CTRL_PRACC
;
1307 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_CONTROL
);
1308 mips_ejtag_drscan_32_out(ejtag_info
, ejtag_ctrl
);
1311 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1312 if (retval
!= ERROR_OK
)
1315 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1317 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1318 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1319 if (retval
!= ERROR_OK
)
1322 if (address
!= MIPS32_PRACC_FASTDATA_AREA
)
1325 /* wait PrAcc pending bit for FASTDATA write */
1326 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1327 if (retval
!= ERROR_OK
)
1330 /* Send the load start address */
1332 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_FASTDATA
);
1333 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1335 /* Send the load end address */
1336 val
= addr
+ (count
- 1) * 4;
1337 mips_ejtag_fastdata_scan(ejtag_info
, 1, &val
);
1339 for (i
= 0; i
< count
; i
++) {
1340 retval
= mips_ejtag_fastdata_scan(ejtag_info
, write_t
, buf
++);
1341 if (retval
!= ERROR_OK
)
1345 retval
= jtag_execute_queue();
1346 if (retval
!= ERROR_OK
) {
1347 LOG_ERROR("fastdata load failed");
1351 retval
= wait_for_pracc_rw(ejtag_info
, &ejtag_ctrl
);
1352 if (retval
!= ERROR_OK
)
1356 mips_ejtag_set_instr(ejtag_info
, EJTAG_INST_ADDRESS
);
1357 retval
= mips_ejtag_drscan_32(ejtag_info
, &address
);
1358 if (retval
!= ERROR_OK
)
1361 if (address
!= MIPS32_PRACC_TEXT
)
1362 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)