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

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)