+ int retval = jtag_execute_queue(); /* execute queued scans */
+ if (retval != ERROR_OK)
+ goto exit;
+
+ uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */
+ scan_count = 0;
+ for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */
+ uint32_t store_addr = 0;
+ if (i & 1u) { /* Read store addres from previous instruction, if not the first */
+ store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1];
+ if (i < 2 || 0 == store_addr)
+ continue;
+ }
+
+ ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
+ if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
+ LOG_ERROR("Error: access not pending count: %d", scan_count);
+ retval = ERROR_FAIL;
+ goto exit;
+ }
+
+ uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
+
+ if (store_addr != 0) {
+ if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
+ LOG_ERROR("Not a store/write access, count: %d", scan_count);
+ retval = ERROR_FAIL;
+ goto exit;
+ }
+ if (addr != store_addr) {
+ LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
+ addr, store_addr, scan_count);
+ retval = ERROR_FAIL;
+ goto exit;
+ }
+ int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
+ buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
+
+ } else {
+ if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
+ LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
+ retval = ERROR_FAIL;
+ goto exit;
+ }
+ if (addr != fetch_addr) {
+ LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
+ addr, fetch_addr, scan_count);
+ retval = ERROR_FAIL;
+ goto exit;
+ }
+ fetch_addr += 4;
+ }
+ scan_count++;
+ }
+exit:
+ free(scan_in);
+ return retval;
+}
+
+int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
+{
+ struct pracc_queue_info ctx = {.max_code = 8};
+ pracc_queue_init(&ctx);
+ if (ctx.retval != ERROR_OK)
+ goto exit;
+
+ pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
+ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */
+ pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */
+ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
+ MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
+ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */
+ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */
+ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
+ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
+
+ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
+exit:
+ pracc_queue_free(&ctx);
+ return ctx.retval;