target: Add a debug_reason command
[openocd.git] / src / target / mips32_pracc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2008 by Spencer Oliver *
5 * spen@spen-soft.co.uk *
6 * *
7 * Copyright (C) 2008 by David T.L. Wong *
8 * *
9 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
10 * *
11 * Copyright (C) 2011 by Drasko DRASKOVIC *
12 * drasko.draskovic@gmail.com *
13 ***************************************************************************/
14
15 /*
16 * This version has optimized assembly routines for 32 bit operations:
17 * - read word
18 * - write word
19 * - write array of words
20 *
21 * One thing to be aware of is that the MIPS32 cpu will execute the
22 * instruction after a branch instruction (one delay slot).
23 *
24 * For example:
25 * LW $2, ($5 +10)
26 * B foo
27 * LW $1, ($2 +100)
28 *
29 * The LW $1, ($2 +100) instruction is also executed. If this is
30 * not wanted a NOP can be inserted:
31 *
32 * LW $2, ($5 +10)
33 * B foo
34 * NOP
35 * LW $1, ($2 +100)
36 *
37 * or the code can be changed to:
38 *
39 * B foo
40 * LW $2, ($5 +10)
41 * LW $1, ($2 +100)
42 *
43 * The original code contained NOPs. I have removed these and moved
44 * the branches.
45 *
46 * These changes result in a 35% speed increase when programming an
47 * external flash.
48 *
49 * More improvement could be gained if the registers do no need
50 * to be preserved but in that case the routines should be aware
51 * OpenOCD is used as a flash programmer or as a debug tool.
52 *
53 * Nico Coesel
54 */
55
56 #ifdef HAVE_CONFIG_H
57 #include "config.h"
58 #endif
59
60 #include <helper/align.h>
61 #include <helper/time_support.h>
62 #include <jtag/adapter.h>
63
64 #include "mips32.h"
65 #include "mips32_pracc.h"
66
67 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info)
68 {
69 int64_t then = timeval_ms();
70
71 /* wait for the PrAcc to become "1" */
72 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
73
74 while (1) {
75 ejtag_info->pa_ctrl = ejtag_info->ejtag_ctrl;
76 int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_ctrl);
77 if (retval != ERROR_OK)
78 return retval;
79
80 if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRACC)
81 break;
82
83 int64_t timeout = timeval_ms() - then;
84 if (timeout > 1000) {
85 LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
86 return ERROR_JTAG_DEVICE_ERROR;
87 }
88 }
89
90 return ERROR_OK;
91 }
92
93 /* Shift in control and address for a new processor access, save them in ejtag_info */
94 static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info)
95 {
96 int retval = wait_for_pracc_rw(ejtag_info);
97 if (retval != ERROR_OK)
98 return retval;
99
100 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
101
102 ejtag_info->pa_addr = 0;
103 return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr);
104 }
105
106 /* Finish processor access */
107 static void mips32_pracc_finish(struct mips_ejtag *ejtag_info)
108 {
109 uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
110 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
111 mips_ejtag_drscan_32_out(ejtag_info, ctrl);
112 }
113
114 static int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
115 {
116 uint32_t jt_code = MIPS32_J(ejtag_info->isa, MIPS32_PRACC_TEXT);
117 pracc_swap16_array(ejtag_info, &jt_code, 1);
118 /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */
119 for (int i = 0; i != 5; i++) {
120 /* Wait for pracc */
121 int retval = wait_for_pracc_rw(ejtag_info);
122 if (retval != ERROR_OK)
123 return retval;
124
125 /* Data or instruction out */
126 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
127 uint32_t data = (i == 3) ? jt_code : MIPS32_NOP;
128 mips_ejtag_drscan_32_out(ejtag_info, data);
129
130 /* finish pa */
131 mips32_pracc_finish(ejtag_info);
132 }
133
134 if (ejtag_info->mode != 0) /* async mode support only for MIPS ... */
135 return ERROR_OK;
136
137 for (int i = 0; i != 2; i++) {
138 int retval = mips32_pracc_read_ctrl_addr(ejtag_info);
139 if (retval != ERROR_OK)
140 return retval;
141
142 if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */
143 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
144 mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP);
145 mips32_pracc_finish(ejtag_info);
146 } else
147 break;
148 }
149
150 return ERROR_OK;
151 }
152
153 static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
154 uint32_t *param_out, bool check_last)
155 {
156 int code_count = 0;
157 int store_pending = 0; /* increases with every store instr at dmseg, decreases with every store pa */
158 uint32_t max_store_addr = 0; /* for store pa address testing */
159 bool restart = 0; /* restarting control */
160 int restart_count = 0;
161 uint32_t instr = 0;
162 bool final_check = 0; /* set to 1 if in final checks after function code shifted out */
163 bool pass = 0; /* to check the pass through pracc text after function code sent */
164 int retval;
165
166 while (1) {
167 if (restart) {
168 if (restart_count < 3) { /* max 3 restarts allowed */
169 retval = mips32_pracc_clean_text_jump(ejtag_info);
170 if (retval != ERROR_OK)
171 return retval;
172 } else
173 return ERROR_JTAG_DEVICE_ERROR;
174 restart_count++;
175 restart = 0;
176 code_count = 0;
177 LOG_DEBUG("restarting code");
178 }
179
180 retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */
181 if (retval != ERROR_OK)
182 return retval;
183
184 /* Check for read or write access */
185 if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */
186 /* Check for pending store from a previous store instruction at dmseg */
187 if (store_pending == 0) {
188 LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr);
189 if (code_count < 2) { /* allow for restart */
190 restart = 1;
191 continue;
192 } else
193 return ERROR_JTAG_DEVICE_ERROR;
194 } else {
195 /* check address */
196 if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT ||
197 ejtag_info->pa_addr > max_store_addr) {
198 LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr);
199 return ERROR_JTAG_DEVICE_ERROR;
200 }
201 }
202 /* read data */
203 uint32_t data = 0;
204 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
205 retval = mips_ejtag_drscan_32(ejtag_info, &data);
206 if (retval != ERROR_OK)
207 return retval;
208
209 /* store data at param out, address based offset */
210 param_out[(ejtag_info->pa_addr - MIPS32_PRACC_PARAM_OUT) / 4] = data;
211 store_pending--;
212
213 } else { /* read/fetch access */
214 if (!final_check) { /* executing function code */
215 /* check address */
216 if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
217 LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x",
218 ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
219
220 /* restart code execution only in some cases */
221 if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT &&
222 restart_count == 0) {
223 LOG_DEBUG("restarting, without clean jump");
224 restart_count++;
225 code_count = 0;
226 continue;
227 } else if (code_count < 2) {
228 restart = 1;
229 continue;
230 }
231 return ERROR_JTAG_DEVICE_ERROR;
232 }
233 /* check for store instruction at dmseg */
234 uint32_t store_addr = ctx->pracc_list[code_count].addr;
235 if (store_addr != 0) {
236 if (store_addr > max_store_addr)
237 max_store_addr = store_addr;
238 store_pending++;
239 }
240
241 instr = ctx->pracc_list[code_count++].instr;
242 if (code_count == ctx->code_count) /* last instruction, start final check */
243 final_check = 1;
244
245 } else { /* final check after function code shifted out */
246 /* check address */
247 if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) {
248 if (!pass) { /* first pass through pracc text */
249 if (store_pending == 0) /* done, normal exit */
250 return ERROR_OK;
251 pass = 1; /* pracc text passed */
252 code_count = 0; /* restart code count */
253 } else {
254 LOG_DEBUG("unexpected second pass through pracc text");
255 return ERROR_JTAG_DEVICE_ERROR;
256 }
257 } else {
258 if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
259 LOG_DEBUG("unexpected read address in final check: %"
260 PRIx32 ", expected: %x", ejtag_info->pa_addr,
261 MIPS32_PRACC_TEXT + code_count * 4);
262 return ERROR_JTAG_DEVICE_ERROR;
263 }
264 }
265 if (!pass) {
266 if ((code_count - ctx->code_count) > 1) { /* allow max 2 instr delay slot */
267 LOG_DEBUG("failed to jump back to pracc text");
268 return ERROR_JTAG_DEVICE_ERROR;
269 }
270 } else
271 if (code_count > 10) { /* enough, abandon */
272 LOG_DEBUG("execution abandoned, store pending: %d", store_pending);
273 return ERROR_JTAG_DEVICE_ERROR;
274 }
275 instr = MIPS32_NOP; /* shift out NOPs instructions */
276 code_count++;
277 }
278
279 /* Send instruction out */
280 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
281 mips_ejtag_drscan_32_out(ejtag_info, instr);
282 }
283 /* finish processor access, let the processor eat! */
284 mips32_pracc_finish(ejtag_info);
285
286 if (final_check && !check_last) /* last instr, don't check, execute and exit */
287 return jtag_execute_queue();
288
289 if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */
290 LOG_DEBUG("warning: store access pass pracc text");
291 return ERROR_OK;
292 }
293 }
294 }
295
296 inline void pracc_queue_init(struct pracc_queue_info *ctx)
297 {
298 ctx->retval = ERROR_OK;
299 ctx->code_count = 0;
300 ctx->store_count = 0;
301 ctx->max_code = 0;
302 ctx->pracc_list = NULL;
303 ctx->isa = ctx->ejtag_info->isa ? 1 : 0;
304 }
305
306 void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
307 {
308 if (ctx->retval != ERROR_OK) /* On previous out of memory, return */
309 return;
310 if (ctx->code_count == ctx->max_code) {
311 void *p = realloc(ctx->pracc_list, sizeof(struct pa_list) * (ctx->max_code + PRACC_BLOCK));
312 if (p) {
313 ctx->max_code += PRACC_BLOCK;
314 ctx->pracc_list = p;
315 } else {
316 ctx->retval = ERROR_FAIL; /* Out of memory */
317 return;
318 }
319 }
320 ctx->pracc_list[ctx->code_count].instr = instr;
321 ctx->pracc_list[ctx->code_count++].addr = addr;
322 if (addr)
323 ctx->store_count++;
324 }
325
326 static void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize)
327 {
328 if (LOWER16(data) == 0 && optimize)
329 pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load only upper value */
330 else if (UPPER16(data) == 0 && optimize)
331 pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, 0, LOWER16(data))); /* load only lower */
332 else {
333 pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load upper and lower */
334 pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, reg_num, LOWER16(data)));
335 }
336 }
337
338 inline void pracc_queue_free(struct pracc_queue_info *ctx)
339 {
340 free(ctx->pracc_list);
341 }
342
343 int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx,
344 uint32_t *buf, bool check_last)
345 {
346 if (ctx->retval != ERROR_OK) {
347 LOG_ERROR("Out of memory");
348 return ERROR_FAIL;
349 }
350
351 if (ejtag_info->isa && ejtag_info->endianness)
352 for (int i = 0; i != ctx->code_count; i++)
353 ctx->pracc_list[i].instr = SWAP16(ctx->pracc_list[i].instr);
354
355 if (ejtag_info->mode == 0)
356 return mips32_pracc_exec(ejtag_info, ctx, buf, check_last);
357
358 union scan_in {
359 uint8_t scan_96[12];
360 struct {
361 uint8_t ctrl[4];
362 uint8_t data[4];
363 uint8_t addr[4];
364 } scan_32;
365
366 } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count));
367 if (!scan_in) {
368 LOG_ERROR("Out of memory");
369 return ERROR_FAIL;
370 }
371
372 unsigned num_clocks =
373 ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000;
374
375 uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
376 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL);
377
378 int scan_count = 0;
379 for (int i = 0; i != ctx->code_count; i++) {
380 jtag_add_clocks(num_clocks);
381 mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, ctx->pracc_list[i].instr,
382 scan_in[scan_count++].scan_96);
383
384 /* Check store address from previous instruction, if not the first */
385 if (i > 0 && ctx->pracc_list[i - 1].addr) {
386 jtag_add_clocks(num_clocks);
387 mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, 0, scan_in[scan_count++].scan_96);
388 }
389 }
390
391 int retval = jtag_execute_queue(); /* execute queued scans */
392 if (retval != ERROR_OK)
393 goto exit;
394
395 uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */
396 scan_count = 0;
397 for (int i = 0; i != ctx->code_count; i++) { /* verify every pracc access */
398 /* check pracc bit */
399 ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
400 uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
401 if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
402 LOG_ERROR("Error: access not pending count: %d", scan_count);
403 retval = ERROR_FAIL;
404 goto exit;
405 }
406 if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
407 LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
408 retval = ERROR_FAIL;
409 goto exit;
410 }
411 if (addr != fetch_addr) {
412 LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
413 addr, fetch_addr, scan_count);
414 retval = ERROR_FAIL;
415 goto exit;
416 }
417 fetch_addr += 4;
418 scan_count++;
419
420 /* check if previous instruction is a store instruction at dmesg */
421 if (i > 0 && ctx->pracc_list[i - 1].addr) {
422 uint32_t store_addr = ctx->pracc_list[i - 1].addr;
423 ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
424 addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
425
426 if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
427 LOG_ERROR("Not a store/write access, count: %d", scan_count);
428 retval = ERROR_FAIL;
429 goto exit;
430 }
431 if (addr != store_addr) {
432 LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
433 addr, store_addr, scan_count);
434 retval = ERROR_FAIL;
435 goto exit;
436 }
437 int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
438 buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
439 scan_count++;
440 }
441 }
442 exit:
443 free(scan_in);
444 return retval;
445 }
446
447 static int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
448 {
449 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
450 pracc_queue_init(&ctx);
451
452 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
453 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper addr */
454 pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */
455 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
456 MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
457 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
458 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
459 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* move COP0 DeSave to $15 */
460
461 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1);
462 pracc_queue_free(&ctx);
463 return ctx.retval;
464 }
465
466 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
467 {
468 if (count == 1 && size == 4)
469 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
470
471 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
472 pracc_queue_init(&ctx);
473
474 uint32_t *data = NULL;
475 if (size != 4) {
476 data = malloc(256 * sizeof(uint32_t));
477 if (!data) {
478 LOG_ERROR("Out of memory");
479 goto exit;
480 }
481 }
482
483 uint32_t *buf32 = buf;
484 uint16_t *buf16 = buf;
485 uint8_t *buf8 = buf;
486
487 while (count) {
488 ctx.code_count = 0;
489 ctx.store_count = 0;
490
491 int this_round_count = (count > 256) ? 256 : count;
492 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
493
494 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
495 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, last_upper_base_addr)); /* upper memory addr to $9 */
496
497 for (int i = 0; i != this_round_count; i++) { /* Main code loop */
498 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
499 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $9 */
500 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, upper_base_addr));
501 last_upper_base_addr = upper_base_addr;
502 }
503
504 if (size == 4) /* load from memory to $8 */
505 pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 9));
506 else if (size == 2)
507 pracc_add(&ctx, 0, MIPS32_LHU(ctx.isa, 8, LOWER16(addr), 9));
508 else
509 pracc_add(&ctx, 0, MIPS32_LBU(ctx.isa, 8, LOWER16(addr), 9));
510
511 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, /* store $8 at param out */
512 MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + i * 4, 15));
513 addr += size;
514 }
515 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
516 pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */
517
518 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
519 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
520
521 if (size == 4) {
522 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1);
523 if (ctx.retval != ERROR_OK)
524 goto exit;
525 buf32 += this_round_count;
526 } else {
527 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data, 1);
528 if (ctx.retval != ERROR_OK)
529 goto exit;
530
531 uint32_t *data_p = data;
532 for (int i = 0; i != this_round_count; i++) {
533 if (size == 2)
534 *buf16++ = *data_p++;
535 else
536 *buf8++ = *data_p++;
537 }
538 }
539 count -= this_round_count;
540 }
541 exit:
542 pracc_queue_free(&ctx);
543 free(data);
544 return ctx.retval;
545 }
546
547 int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
548 {
549 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
550 pracc_queue_init(&ctx);
551
552 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
553 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */
554 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
555 MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
556 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
557 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
558 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
559 pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
560
561 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1);
562 pracc_queue_free(&ctx);
563 return ctx.retval;
564 }
565
566 int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
567 {
568 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
569 pracc_queue_init(&ctx);
570
571 pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */
572
573 pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */
574 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
575 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
576
577 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
578 pracc_queue_free(&ctx);
579 return ctx.retval;
580 }
581
582 /**
583 * \b mips32_pracc_sync_cache
584 *
585 * Synchronize Caches to Make Instruction Writes Effective
586 * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
587 * Document Number: MD00086, Revision 2.00, June 9, 2003)
588 *
589 * When the instruction stream is written, the SYNCI instruction should be used
590 * in conjunction with other instructions to make the newly-written instructions effective.
591 *
592 * Explanation :
593 * A program that loads another program into memory is actually writing the D- side cache.
594 * The instructions it has loaded can't be executed until they reach the I-cache.
595 *
596 * After the instructions have been written, the loader should arrange
597 * to write back any containing D-cache line and invalidate any locations
598 * already in the I-cache.
599 *
600 * If the cache coherency attribute (CCA) is set to zero, it's a write through cache, there is no need
601 * to write back.
602 *
603 * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
604 * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
605 * That is, it arranges a D-cache write-back (if CCA = 3) and an I-cache invalidate.
606 *
607 * The line size is obtained with the rdhwr SYNCI_Step in release 2 or from cp0 config 1 register in release 1.
608 */
609 static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
610 uint32_t start_addr, uint32_t end_addr, int cached, int rel)
611 {
612 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
613 pracc_queue_init(&ctx);
614
615 /** Find cache line size in bytes */
616 uint32_t clsiz;
617 if (rel) { /* Release 2 (rel = 1) */
618 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
619
620 pracc_add(&ctx, 0, MIPS32_RDHWR(ctx.isa, 8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
621
622 pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
623 MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
624
625 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
626
627 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
628 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
629
630 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1);
631 if (ctx.retval != ERROR_OK)
632 goto exit;
633
634 } else { /* Release 1 (rel = 0) */
635 uint32_t conf;
636 ctx.retval = mips32_cp0_read(ejtag_info, &conf, 16, 1);
637 if (ctx.retval != ERROR_OK)
638 goto exit;
639
640 uint32_t dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
641
642 /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... max dl=6 => 128 bytes cache line size */
643 clsiz = 0x2 << dl;
644 if (dl == 0)
645 clsiz = 0;
646 }
647
648 if (clsiz == 0)
649 goto exit; /* Nothing to do */
650
651 /* make sure clsiz is power of 2 */
652 if (!IS_PWR_OF_2(clsiz)) {
653 LOG_DEBUG("clsiz must be power of 2");
654 ctx.retval = ERROR_FAIL;
655 goto exit;
656 }
657
658 /* make sure start_addr and end_addr have the same offset inside de cache line */
659 start_addr |= clsiz - 1;
660 end_addr |= clsiz - 1;
661
662 ctx.code_count = 0;
663 ctx.store_count = 0;
664
665 int count = 0;
666 uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000));
667
668 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); /* load upper memory base addr to $15 */
669
670 while (start_addr <= end_addr) { /* main loop */
671 uint32_t upper_base_addr = UPPER16((start_addr + 0x8000));
672 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $15 */
673 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr));
674 last_upper_base_addr = upper_base_addr;
675 }
676 if (rel) /* synci instruction, offset($15) */
677 pracc_add(&ctx, 0, MIPS32_SYNCI(ctx.isa, LOWER16(start_addr), 15));
678
679 else {
680 if (cached == 3) /* cache Hit_Writeback_D, offset($15) */
681 pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_D_HIT_WRITEBACK,
682 LOWER16(start_addr), 15));
683 /* cache Hit_Invalidate_I, offset($15) */
684 pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_I_HIT_INVALIDATE,
685 LOWER16(start_addr), 15));
686 }
687 start_addr += clsiz;
688 count++;
689 if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */
690 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* to start */
691 pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */
692
693 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
694 if (ctx.retval != ERROR_OK)
695 goto exit;
696
697 ctx.code_count = 0; /* reset counters for another loop */
698 ctx.store_count = 0;
699 count = 0;
700 }
701 }
702 pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa));
703 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
704 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave*/
705
706 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
707 exit:
708 pracc_queue_free(&ctx);
709 return ctx.retval;
710 }
711
712 static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
713 uint32_t addr, int size, int count, const void *buf)
714 {
715 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
716 pracc_queue_init(&ctx);
717
718 const uint32_t *buf32 = buf;
719 const uint16_t *buf16 = buf;
720 const uint8_t *buf8 = buf;
721
722 while (count) {
723 ctx.code_count = 0;
724 ctx.store_count = 0;
725
726 int this_round_count = (count > 128) ? 128 : count;
727 uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
728 /* load $15 with memory base address */
729 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr));
730
731 for (int i = 0; i != this_round_count; i++) {
732 uint32_t upper_base_addr = UPPER16((addr + 0x8000));
733 if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15*/
734 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr));
735 last_upper_base_addr = upper_base_addr;
736 }
737
738 if (size == 4) {
739 pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */
740 pracc_add(&ctx, 0, MIPS32_SW(ctx.isa, 8, LOWER16(addr), 15)); /* store word to mem */
741 buf32++;
742
743 } else if (size == 2) {
744 pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf16)); /* load lower value */
745 pracc_add(&ctx, 0, MIPS32_SH(ctx.isa, 8, LOWER16(addr), 15)); /* store half word */
746 buf16++;
747
748 } else {
749 pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf8)); /* load lower value */
750 pracc_add(&ctx, 0, MIPS32_SB(ctx.isa, 8, LOWER16(addr), 15)); /* store byte */
751 buf8++;
752 }
753 addr += size;
754 }
755
756 pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */
757
758 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
759 pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */
760
761 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
762 if (ctx.retval != ERROR_OK)
763 goto exit;
764 count -= this_round_count;
765 }
766 exit:
767 pracc_queue_free(&ctx);
768 return ctx.retval;
769 }
770
771 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
772 {
773 int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf);
774 if (retval != ERROR_OK)
775 return retval;
776
777 /**
778 * If we are in the cacheable region and cache is activated,
779 * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write,
780 * so that changes do not continue to live only in D$ (if CCA = 3), but to be
781 * replicated in I$ also (maybe we wrote the instructions)
782 */
783 uint32_t conf = 0;
784 int cached = 0;
785
786 if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
787 return retval; /*Nothing to do*/
788
789 mips32_cp0_read(ejtag_info, &conf, 16, 0);
790
791 switch (KSEGX(addr)) {
792 case KUSEG:
793 cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
794 break;
795 case KSEG0:
796 cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
797 break;
798 case KSEG2:
799 case KSEG3:
800 cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
801 break;
802 default:
803 /* what ? */
804 break;
805 }
806
807 /**
808 * Check cacheability bits coherency algorithm
809 * is the region cacheable or uncached.
810 * If cacheable we have to synchronize the cache
811 */
812 if (cached == 3 || cached == 0) { /* Write back cache or write through cache */
813 uint32_t start_addr = addr;
814 uint32_t end_addr = addr + count * size;
815 uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
816 if (rel > 1) {
817 LOG_DEBUG("Unknown release in cache code");
818 return ERROR_FAIL;
819 }
820 retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel);
821 }
822
823 return retval;
824 }
825
826 int mips32_pracc_write_regs(struct mips32_common *mips32)
827 {
828 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
829 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
830 uint32_t *gprs = mips32->core_regs.gpr;
831 uint32_t *c0rs = mips32->core_regs.cp0;
832
833 pracc_queue_init(&ctx);
834
835 uint32_t cp0_write_code[] = {
836 MIPS32_MTC0(ctx.isa, 1, 12, 0), /* move $1 to status */
837 MIPS32_MTLO(ctx.isa, 1), /* move $1 to lo */
838 MIPS32_MTHI(ctx.isa, 1), /* move $1 to hi */
839 MIPS32_MTC0(ctx.isa, 1, 8, 0), /* move $1 to badvaddr */
840 MIPS32_MTC0(ctx.isa, 1, 13, 0), /* move $1 to cause*/
841 MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */
842 };
843
844 uint32_t cp0_write_data[] = {
845 /* lo */
846 gprs[32],
847 /* hi */
848 gprs[33],
849 /* status */
850 c0rs[0],
851 /* badvaddr */
852 c0rs[1],
853 /* cause */
854 c0rs[2],
855 /* depc (pc) */
856 c0rs[3],
857 };
858
859 for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) {
860 /* load CP0 value in $1 */
861 pracc_add_li32(&ctx, 1, cp0_write_data[i], 0);
862 /* write value from $1 to CP0 register */
863 pracc_add(&ctx, 0, cp0_write_code[i]);
864 }
865
866 /* load registers 2 to 31 with li32, optimize */
867 for (int i = 2; i < 32; i++)
868 pracc_add_li32(&ctx, i, gprs[i], 1);
869
870 /* load $15 in DeSave */
871 pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
872 /* load upper half word in $1 */
873 pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((gprs[1]))));
874 /* jump to start */
875 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
876 /* load lower half word in $1 */
877 pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((gprs[1]))));
878
879 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
880
881 ejtag_info->reg8 = gprs[8];
882 ejtag_info->reg9 = gprs[9];
883 pracc_queue_free(&ctx);
884 return ctx.retval;
885 }
886
887 /* Saves content in `$1` to `DeSave(cp0.31.0)` and loads `MIPS32_PRACC_BASE_ADDR` into `$1` */
888 static void mips32_pracc_store_regs_set_base_addr(struct pracc_queue_info *ctx)
889 {
890 /* move $1 to COP0 DeSave */
891 pracc_add(ctx, 0, MIPS32_MTC0(ctx->isa, 1, 31, 0));
892 /* $1 = MIP32_PRACC_BASE_ADDR */
893 pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, 1, PRACC_UPPER_BASE_ADDR));
894 }
895
896 /* This function assumes the address for saving is stored in `$1`.
897 * And that action is performed in `mips32_pracc_set_save_base_addr`.
898 */
899 static void mips32_pracc_store_regs_gpr(struct pracc_queue_info *ctx, unsigned int offset_gpr)
900 {
901 for (int i = 2; i != 32; i++)
902 pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset_gpr + (i * 4),
903 MIPS32_SW(ctx->isa, i, PRACC_OUT_OFFSET + offset_gpr + (i * 4), 1));
904 }
905
906 static void mips32_pracc_store_regs_lohi(struct pracc_queue_info *ctx)
907 {
908 uint32_t lohi_read_code[] = {
909 MIPS32_MFLO(ctx->isa, 8), /* move lo to $8 */
910 MIPS32_MFHI(ctx->isa, 8), /* move hi to $8 */
911 };
912
913 /* store lo & hi */
914 for (int i = 0; i < 2; i++) {
915 /* load COP0 needed registers to $8 */
916 pracc_add(ctx, 0, lohi_read_code[i]);
917 /* store $8 at PARAM OUT */
918 pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,
919 MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
920 }
921 }
922
923 /* Saves CP0 registers [status, badvaddr, cause, depc] */
924 static void mips32_pracc_store_regs_cp0_context(struct pracc_queue_info *ctx, unsigned int offset_cp0)
925 {
926 uint32_t cp0_read_code[] = {
927 MIPS32_MFC0(ctx->isa, 8, 12, 0), /* move status to $8 */
928 MIPS32_MFC0(ctx->isa, 8, 8, 0), /* move badvaddr to $8 */
929 MIPS32_MFC0(ctx->isa, 8, 13, 0), /* move cause to $8 */
930 MIPS32_MFC0(ctx->isa, 8, 24, 0), /* move depc (pc) to $8 */
931 };
932
933 /* store cp0 */
934 for (size_t i = 0; i < ARRAY_SIZE(cp0_read_code); i++) {
935 size_t offset = offset_cp0 + (i * 4);
936
937 /* load COP0 needed registers to $8 */
938 pracc_add(ctx, 0, cp0_read_code[i]);
939 /* store $8 at PARAM OUT */
940 pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset,
941 MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + offset, 1));
942 }
943 }
944
945 /* Loads original content of $1 into $8,
946 * then store it to the batch data access address.
947 * Finally it restores $1 from DeSave.
948 */
949 static void mips32_pracc_store_regs_restore(struct pracc_queue_info *ctx)
950 {
951 /* move DeSave to $8, reg1 value */
952 pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 8, 31, 0));
953 /* store reg1 value from $8 to param out */
954 pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + 4,
955 MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + 4, 1));
956
957 /* move COP0 DeSave to $1, restore reg1 */
958 pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 1, 31, 0));
959 }
960
961 /* This function performs following actions:
962 * Saves `$1` to `DeSave`,
963 * then load `PRACC_UPPER_BASE_ADDR` for saving the register data structure into `$1`,
964 * Saves `$2` ~ `$31` to `PRACC_UPPER_BASE_ADDR + offset_gpr`
965 * Saves HI and LO,
966 * Saves necessary cp0 registers.
967 */
968 static void mips32_pracc_store_regs(struct pracc_queue_info *ctx,
969 unsigned int offset_gpr, unsigned int offset_cp0)
970 {
971 mips32_pracc_store_regs_set_base_addr(ctx);
972 mips32_pracc_store_regs_gpr(ctx, offset_gpr);
973 mips32_pracc_store_regs_lohi(ctx);
974 mips32_pracc_store_regs_cp0_context(ctx, offset_cp0);
975 mips32_pracc_store_regs_restore(ctx);
976 }
977
978 int mips32_pracc_read_regs(struct mips32_common *mips32)
979 {
980 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
981 struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
982 struct mips32_core_regs *core_regs = &mips32->core_regs;
983 unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
984 unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
985
986 /*
987 * This procedure has to be in 2 distinctive steps, because we can
988 * only know whether FP is enabled after reading CP0.
989 *
990 * Step 1: Read everything except CP1 stuff
991 * Step 2: Read CP1 stuff if FP is implemented
992 */
993
994 pracc_queue_init(&ctx);
995
996 mips32_pracc_store_regs(&ctx, offset_gpr, offset_cp0);
997
998 /* jump to start */
999 pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
1000 /* load $15 in DeSave */
1001 pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
1002
1003 ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1);
1004
1005 pracc_queue_free(&ctx);
1006
1007 /* reg8 is saved but not restored, next called function should restore it */
1008 ejtag_info->reg8 = mips32->core_regs.gpr[8];
1009 ejtag_info->reg9 = mips32->core_regs.gpr[9];
1010
1011 /* we only care if FP is actually impl'd and if cp1 is enabled */
1012 /* since we already read cp0 in the prev step */
1013 /* now we know what's in cp0.status */
1014 /* TODO: Read FPRs */
1015
1016 return ctx.retval;
1017 }
1018
1019 /* fastdata upload/download requires an initialized working area
1020 * to load the download code; it should not be called otherwise
1021 * fetch order from the fastdata area
1022 * 1. start addr
1023 * 2. end addr
1024 * 3. data ...
1025 */
1026 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
1027 int write_t, uint32_t addr, int count, uint32_t *buf)
1028 {
1029 uint32_t isa = ejtag_info->isa ? 1 : 0;
1030 uint32_t handler_code[] = {
1031 /* r15 points to the start of this code */
1032 MIPS32_SW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
1033 MIPS32_SW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
1034 MIPS32_SW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
1035 MIPS32_SW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
1036 /* start of fastdata area in t0 */
1037 MIPS32_LUI(isa, 8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
1038 MIPS32_ORI(isa, 8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
1039 MIPS32_LW(isa, 9, 0, 8), /* start addr in t1 */
1040 MIPS32_LW(isa, 10, 0, 8), /* end addr to t2 */
1041 /* loop: */
1042 write_t ? MIPS32_LW(isa, 11, 0, 8) : MIPS32_LW(isa, 11, 0, 9), /* from xfer area : from memory */
1043 write_t ? MIPS32_SW(isa, 11, 0, 9) : MIPS32_SW(isa, 11, 0, 8), /* to memory : to xfer area */
1044
1045 MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)), /* bne $t2,t1,loop */
1046 MIPS32_ADDI(isa, 9, 9, 4), /* addi t1,t1,4 */
1047
1048 MIPS32_LW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
1049 MIPS32_LW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
1050 MIPS32_LW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
1051 MIPS32_LW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
1052
1053 MIPS32_LUI(isa, 15, UPPER16(MIPS32_PRACC_TEXT)),
1054 MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_PRACC_TEXT) | isa), /* isa bit for JR instr */
1055 MIPS32_JR(isa, 15), /* jr start */
1056 MIPS32_MFC0(isa, 15, 31, 0), /* move COP0 DeSave to $15 */
1057 };
1058
1059 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
1060 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1061
1062 pracc_swap16_array(ejtag_info, handler_code, ARRAY_SIZE(handler_code));
1063 /* write program into RAM */
1064 if (write_t != ejtag_info->fast_access_save) {
1065 mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
1066 /* save previous operation to speed to any consecutive read/writes */
1067 ejtag_info->fast_access_save = write_t;
1068 }
1069
1070 LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address);
1071
1072 uint32_t jmp_code[] = {
1073 MIPS32_LUI(isa, 15, UPPER16(source->address)), /* load addr of jump in $15 */
1074 MIPS32_ORI(isa, 15, 15, LOWER16(source->address) | isa), /* isa bit for JR instr */
1075 MIPS32_JR(isa, 15), /* jump to ram program */
1076 isa ? MIPS32_XORI(isa, 15, 15, 1) : MIPS32_NOP, /* drop isa bit, needed for LW/SW instructions */
1077 };
1078
1079 pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code));
1080
1081 /* execute jump code, with no address check */
1082 for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) {
1083 int retval = wait_for_pracc_rw(ejtag_info);
1084 if (retval != ERROR_OK)
1085 return retval;
1086
1087 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
1088 mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
1089
1090 /* Clear the access pending bit (let the processor eat!) */
1091 mips32_pracc_finish(ejtag_info);
1092 }
1093
1094 /* wait PrAcc pending bit for FASTDATA write, read address */
1095 int retval = mips32_pracc_read_ctrl_addr(ejtag_info);
1096 if (retval != ERROR_OK)
1097 return retval;
1098
1099 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1100 if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA)
1101 return ERROR_FAIL;
1102
1103 /* Send the load start address */
1104 uint32_t val = addr;
1105 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1106 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1107
1108 retval = wait_for_pracc_rw(ejtag_info);
1109 if (retval != ERROR_OK)
1110 return retval;
1111
1112 /* Send the load end address */
1113 val = addr + (count - 1) * 4;
1114 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
1115 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1116
1117 unsigned num_clocks = 0; /* like in legacy code */
1118 if (ejtag_info->mode != 0)
1119 num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000;
1120
1121 for (int i = 0; i < count; i++) {
1122 jtag_add_clocks(num_clocks);
1123 mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
1124 }
1125
1126 retval = jtag_execute_queue();
1127 if (retval != ERROR_OK) {
1128 LOG_ERROR("fastdata load failed");
1129 return retval;
1130 }
1131
1132 retval = mips32_pracc_read_ctrl_addr(ejtag_info);
1133 if (retval != ERROR_OK)
1134 return retval;
1135
1136 if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT)
1137 LOG_ERROR("mini program did not return to start");
1138
1139 return retval;
1140 }

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)