+ /* store data at param out, address based offset */
+ param_out[(ejtag_info->pa_addr - MIPS32_PRACC_PARAM_OUT) / 4] = data;
+ store_pending--;
+
+ } else { /* read/fetch access */
+ if (!final_check) { /* executing function code */
+ /* check address */
+ if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
+ LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x",
+ ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
+
+ /* restart code execution only in some cases */
+ if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) {
+ LOG_DEBUG("restarting, without clean jump");
+ restart_count++;
+ code_count = 0;
+ continue;
+ } else if (code_count < 2) {
+ restart = 1;
+ continue;
+ }
+
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ /* check for store instruction at dmseg */
+ uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count];
+ if (store_addr != 0) {
+ if (store_addr > max_store_addr)
+ max_store_addr = store_addr;
+ store_pending++;
+ }
+
+ instr = ctx->pracc_list[code_count++];
+ if (code_count == ctx->code_count) /* last instruction, start final check */
+ final_check = 1;
+
+ } else { /* final check after function code shifted out */
+ /* check address */
+ if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) {
+ if (!pass) { /* first pass through pracc text */
+ if (store_pending == 0) /* done, normal exit */
+ return ERROR_OK;
+ pass = 1; /* pracc text passed */
+ code_count = 0; /* restart code count */
+ } else {
+ LOG_DEBUG("unexpected second pass through pracc text");
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ } else {
+ if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
+ LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x",
+ ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ }
+ if (!pass) {
+ if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */
+ LOG_DEBUG("failed to jump back to pracc text");
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ } else
+ if (code_count > 10) { /* enough, abandone */
+ LOG_DEBUG("execution abandoned, store pending: %d", store_pending);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+ instr = MIPS32_NOP; /* shift out NOPs instructions */
+ code_count++;
+ }
+
+ /* Send instruction out */
+ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
+ mips_ejtag_drscan_32_out(ejtag_info, instr);
+ }
+ /* finish processor access, let the processor eat! */
+ retval = mips32_pracc_finish(ejtag_info);
+ if (retval != ERROR_OK)
+ return retval;