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

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)