From 00ee9b09d9112a09e9780ace560bd8b353661658 Mon Sep 17 00:00:00 2001 From: Walter Ji Date: Thu, 22 Feb 2024 17:06:53 +0800 Subject: [PATCH] target/mips32: add dsp access support for gdb Change order of dsp register name array and removed hi0 and lo0 to comply with gdb definition of dsp in mips-dsp.xml, the regs name array is now mapping corresponding dsp accumulator names onto `mips32_regs` and `core_regs` instead of mapping to instr arrays in dsp functions. feature now requires a place to store cached dsp registers. Add dsp registers to reg_list for gdb to access them. Add dsp module enable detection to avoid DSP Disabled exception while reading dsp accumulators. Add dsp register reading procedure in `mips32_pracc_read_regs` and writing procedure in `mips32_pracc_write_regs`. Change-Id: Iacc335da030ab85989922c81aac7925b3dc17459 Signed-off-by: Walter Ji Reviewed-on: https://review.openocd.org/c/openocd/+/8476 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Oleksij Rempel --- src/target/mips32.c | 102 +++++++++++++++++++++++++++----------- src/target/mips32.h | 11 +++- src/target/mips32_pracc.c | 83 +++++++++++++++++++++++++++++-- 3 files changed, 163 insertions(+), 33 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 81faab72da..af52ffca05 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -31,7 +31,7 @@ static const char *mips_isa_strings[] = { /* * GDB registers - * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml + * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu,dsp}.xml */ static const struct { unsigned id; @@ -156,6 +156,22 @@ static const struct { "org.gnu.gdb.mips.cpu", 0 }, { MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, + + { MIPS32_REGLIST_DSP_INDEX + 0, "hi1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 1, "lo1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 2, "hi2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 3, "lo2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 4, "hi3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 5, "lo3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + + { MIPS32_REGLIST_DSP_DSPCTL_INDEX, "dspctl", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, }; #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) @@ -211,13 +227,11 @@ static const struct { static const struct { const char *name; } mips32_dsp_regs[MIPS32NUMDSPREGS] = { - { "hi0"}, { "hi1"}, - { "hi2"}, - { "hi3"}, - { "lo0"}, { "lo1"}, + { "hi2"}, { "lo2"}, + { "hi3"}, { "lo3"}, { "control"}, }; @@ -328,7 +342,12 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = mips32->core_regs.dsp[cnum]; + buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = mips32->core_regs.cp0[cnum]; @@ -371,7 +390,12 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); + mips32->core_regs.dsp[cnum] = (uint32_t)reg_value; + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); @@ -1026,10 +1050,20 @@ int mips32_cpu_probe(struct target *target) /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { - uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + uint32_t retval, status_value, dsp_present; + bool dsp_enabled; + + retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read cp0 status register"); + return; + } + + dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + dsp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; if (dsp_present) { mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1; - LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp); + LOG_USER("DSP implemented: rev %d, %s", mips32->dsp_imp, dsp_enabled ? "enabled" : "disabled"); } else { LOG_USER("DSP implemented: %s", "no"); } @@ -1747,13 +1781,11 @@ static int mips32_pracc_read_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t *va }; uint32_t dsp_read_code[] = { - MIPS32_MFHI(isa, t0), /* mfhi t0 ($ac0) - OPCODE - 0x00004010 */ MIPS32_DSP_MFHI(t0, 1), /* mfhi t0,$ac1 - OPCODE - 0x00204010 */ - MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ - MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ - MIPS32_MFLO(isa, t0), /* mflo t0 ($ac0) - OPCODE - 0x00004012 */ MIPS32_DSP_MFLO(t0, 1), /* mflo t0,$ac1 - OPCODE - 0x00204012 */ + MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ MIPS32_DSP_MFLO(t0, 2), /* mflo t0,$ac2 - OPCODE - 0x00404012 */ + MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ MIPS32_DSP_MFLO(t0, 3), /* mflo t0,$ac3 - OPCODE - 0x00604012 */ MIPS32_DSP_RDDSP(t0, 0x3F), /* rddsp t0, 0x3f (DSPCtl) - OPCODE - 0x7c3f44b8 */ }; @@ -1824,13 +1856,11 @@ static int mips32_pracc_write_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t va }; uint32_t dsp_write_code[] = { - MIPS32_MTHI(isa, t0), /* mthi t0 ($ac0) - OPCODE - 0x01000011 */ MIPS32_DSP_MTHI(t0, 1), /* mthi t0, $ac1 - OPCODE - 0x01000811 */ - MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ - MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ - MIPS32_MTLO(isa, t0), /* mtlo t0 ($ac0) - OPCODE - 0x01000013 */ MIPS32_DSP_MTLO(t0, 1), /* mtlo t0, $ac1 - OPCODE - 0x01000813 */ + MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ MIPS32_DSP_MTLO(t0, 2), /* mtlo t0, $ac2 - OPCODE - 0x01001013 */ + MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ MIPS32_DSP_MTLO(t0, 3), /* mtlo t0, $ac3 - OPCODE - 0x01001813 */ MIPS32_DSP_WRDSP(t0, 0x1F), /* wrdsp t0, 0x1f (DSPCtl) - OPCODE - 0x7d00fcf8*/ }; @@ -2107,15 +2137,18 @@ static int mips32_dsp_find_register_by_name(const char *reg_name) * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; for (int i = 0; i < MIPS32NUMDSPREGS; i++) { int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i); if (retval != ERROR_OK) { command_print(CMD, "couldn't access reg %s", mips32_dsp_regs[i].name); return retval; } + mips32->core_regs.dsp[i] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + i].dirty = 1; command_print(CMD, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value); } return ERROR_OK; @@ -2132,20 +2165,28 @@ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "ERROR: Could not access dsp register %s", CMD_ARGV[0]); - else - command_print(CMD, "0x%8.8x", value); + return retval; + } + + command_print(CMD, "0x%8.8x", value); + + if (mips32->core_regs.dsp[index] != value) { + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; + } return retval; } @@ -2162,9 +2203,10 @@ static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); @@ -2174,8 +2216,13 @@ static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_e COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); int retval = mips32_pracc_write_dsp_reg(ejtag_info, value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "Error: could not write to dsp register %s", CMD_ARGV[0]); + return retval; + } + + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; return retval; } @@ -2193,7 +2240,6 @@ COMMAND_HANDLER(mips32_handle_dsp_command) int retval, tmp; struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); - struct mips_ejtag *ejtag_info = &mips32->ejtag_info; retval = mips32_verify_pointer(CMD, mips32); if (retval != ERROR_OK) @@ -2217,10 +2263,10 @@ COMMAND_HANDLER(mips32_handle_dsp_command) switch (CMD_ARGC) { case 0: - retval = mips32_dsp_get_all_regs(CMD, ejtag_info); + retval = mips32_dsp_get_all_regs(CMD, mips32); break; case 1: - retval = mips32_dsp_get_register(CMD, ejtag_info); + retval = mips32_dsp_get_register(CMD, mips32); break; case 2: tmp = *CMD_ARGV[0]; @@ -2228,7 +2274,7 @@ COMMAND_HANDLER(mips32_handle_dsp_command) command_print(CMD, "Error: invalid dsp command format"); retval = ERROR_COMMAND_ARGUMENT_INVALID; } else { - retval = mips32_dsp_set_register(CMD, ejtag_info); + retval = mips32_dsp_set_register(CMD, mips32); } break; default: diff --git a/src/target/mips32.h b/src/target/mips32.h index a557f31172..3d919e7ddb 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -69,7 +69,7 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 -#define MIPS32NUMDSPREGS 9 +#define MIPS32NUMDSPREGS 7 /* Bit Mask indicating CP0 register supported by this core */ #define MIPS_CP0_MK4 0x0001 @@ -78,6 +78,7 @@ #define MIPS_CP0_IAPTIV 0x0008 /* CP0 Status register fields */ +#define MIPS32_CP0_STATUS_MX_SHIFT 24 #define MIPS32_CP0_STATUS_FR_SHIFT 26 #define MIPS32_CP0_STATUS_CU1_SHIFT 29 @@ -211,6 +212,7 @@ static const struct mips32_cp0 { enum { MIPS32_PC = 37, MIPS32_FIR = 71, + MIPS32_DSPCTL = 78, MIPS32NUMCOREREGS }; @@ -220,11 +222,13 @@ enum { #define MIPS32_REG_FP_COUNT 32 #define MIPS32_REG_FPC_COUNT 2 #define MIPS32_REG_C0_COUNT 5 +#define MIPS32_REG_DSP_COUNT 7 #define MIPS32_REGLIST_GP_INDEX 0 #define MIPS32_REGLIST_FP_INDEX (MIPS32_REGLIST_GP_INDEX + MIPS32_REG_GP_COUNT) #define MIPS32_REGLIST_FPC_INDEX (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT) #define MIPS32_REGLIST_C0_INDEX (MIPS32_REGLIST_FPC_INDEX + MIPS32_REG_FPC_COUNT) +#define MIPS32_REGLIST_DSP_INDEX (MIPS32_REGLIST_C0_INDEX + MIPS32_REG_C0_COUNT) #define MIPS32_REGLIST_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0) #define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1) @@ -238,6 +242,10 @@ enum { #define MIPS32_REG_C0_PC_INDEX 3 #define MIPS32_REG_C0_GUESTCTL1_INDEX 4 +#define MIPS32_REGLIST_DSP_DSPCTL_INDEX (MIPS32_REGLIST_DSP_INDEX + 6) + +#define MIPS32_REG_DSP_DSPCTL_INDEX 6 + enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, @@ -377,6 +385,7 @@ struct mips32_core_regs { uint64_t fpr[MIPS32_REG_FP_COUNT]; uint32_t fpcr[MIPS32_REG_FPC_COUNT]; uint32_t cp0[MIPS32_REG_C0_COUNT]; + uint32_t dsp[MIPS32_REG_DSP_COUNT]; }; struct mips32_common { diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index aaf3875fb7..018d8424e3 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -878,6 +878,7 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) uint32_t *c0rs = mips32->core_regs.cp0; bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + bool dsp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0); uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; pracc_queue_init(&ctx); @@ -943,6 +944,34 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); } + /* Store DSP Accumulators */ + if (mips32->dsp_imp && dsp_enabled) { + /* Struct of mips32_dsp_regs: {ac{hi, lo}1-3, dspctl} */ + uint32_t *dspr = mips32->core_regs.dsp; + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + + /* Starts from ac1, core_regs.dsp contains dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi and lo, and core_regs.dsp stores ac[1~3] */ + /* reads hi[ac] from core_regs array */ + pracc_add_li32(&ctx, 2, dspr[index * 2], 0); + /* reads lo[ac] from core_regs array */ + pracc_add_li32(&ctx, 3, dspr[(index * 2) + 1], 0); + + /* Write to accumulator 1~3 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MTHI(2, ac)); + pracc_add(&ctx, 0, MIPS32_DSP_MTLO(3, ac)); + } + + /* DSPCTL is the last element of register store */ + pracc_add_li32(&ctx, 2, dspr[6], 0); + pracc_add(&ctx, 0, MIPS32_DSP_WRDSP(2, 0x1F)); + + if (rel > MIPS32_RELEASE_1) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + } + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1064,14 +1093,16 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs; unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs; unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs; - bool fp_enabled; + unsigned int offset_dsp = ((uint8_t *)&core_regs->dsp[0]) - (uint8_t *)core_regs; + bool fp_enabled, dsp_enabled; /* - * This procedure has to be in 2 distinctive steps, because we can - * only know whether FP is enabled after reading CP0. + * This procedure has to be in 3 distinctive steps, because we can + * only know whether FP and DSP are enabled after reading CP0. * - * Step 1: Read everything except CP1 stuff + * Step 1: Read everything except CP1 and DSP stuff * Step 2: Read CP1 stuff if FP is implemented + * Step 3: Read DSP registers if dsp is implemented */ pracc_queue_init(&ctx); @@ -1149,6 +1180,50 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) pracc_queue_free(&ctx); } + + dsp_enabled = (mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; + if (mips32->dsp_imp && dsp_enabled) { + pracc_queue_init(&ctx); + + mips32_pracc_store_regs_set_base_addr(&ctx); + + /* Struct of mips32_dsp_regs[7]: {ac{hi, lo}1-3, dspctl} */ + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + /* Starts from ac1, core_regs.dsp have dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi&lo, and core_regs.dsp stores ac[1~3] */ + /* Reads offset of hi[ac] from core_regs array */ + size_t offset_hi = offset_dsp + ((index * 2) * sizeof(uint32_t)); + /* Reads offset of lo[ac] from core_regs array */ + size_t offset_lo = offset_dsp + (((index * 2) + 1) * sizeof(uint32_t)); + + /* DSP Ac registers starts from 1 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MFHI(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_hi, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_hi, 1)); + pracc_add(&ctx, 0, MIPS32_DSP_MFLO(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_lo, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_lo, 1)); + } + + /* DSPCTL is the last element of register store */ + pracc_add(&ctx, 0, MIPS32_DSP_RDDSP(8, 0x3F)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), + MIPS32_SW(ctx.isa, 8, + PRACC_OUT_OFFSET + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), 1)); + + mips32_pracc_store_regs_restore(&ctx); + + /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); + /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1); + + pracc_queue_free(&ctx); + } return ctx.retval; }