This is an automated email from Gerrit. Kent Brinkley (jkbrinkley.img...@gmail.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/2409
-- gerrit commit 98ab34c8e1b02159c257b9100e578b847b3e26ce Author: Kent Brinkley <jkbrinkley.img...@gmail.com> Date: Wed Nov 26 14:24:47 2014 -0700 New command to display/modify DSP registers Implemented new command to display/modify DSP registers for any MIPS core that has Rev 2 DSP module extension implemented. Change-Id: I9e586a91897655c837d6a1041fc1bd3817c652c7 Signed-off-by: Kent Brinkley <jkbrinkley.img...@gmail.com> Fixed formatting issues Fixed formatting issues Change-Id: Icda7b98abc6f045636c184955714daa13e3b48c1 Signed-off-by: Kent Brinkley <jkbrinkley.img...@gmail.com> diff --git a/src/target/mips32.c b/src/target/mips32.c index ff9e357..a2d30b8 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -84,6 +84,18 @@ static const struct { { 37, "pc" }, }; +static const struct { + unsigned reg; + const char *name; +} mips32_dsp_regs[MIPS32NUMDSPREGS] = { + { 0, "hi1"}, + { 1, "hi2"}, + { 2, "hi3"}, + { 3, "lo1"}, + { 4, "lo2"}, + { 5, "lo3"}, + { 6, "control"}, +}; /* number of mips dummy fp regs fp0 - fp31 + fsr and fir * we also add 18 unknown registers to handle gdb requests */ @@ -905,6 +917,89 @@ COMMAND_HANDLER(mips32_handle_cp0_command) return mips32_cp0_command(cmd); } +COMMAND_HANDLER(mips32_handle_dsp_command) +{ + int retval; + 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_CTX, mips32); + if (retval != ERROR_OK) + return retval; + + if (target->state != TARGET_HALTED) { + command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); + return ERROR_OK; + } + + /* Check if DSP access supported or not */ + if ((mips32->mmips != MIPS32_ONLY) && (mips32->dsp_implemented == DSP_NOT_IMP)) { + + /* Issue Error Message */ + command_print(CMD_CTX, "DSP not implemented by this processor"); + return ERROR_OK; + } + + if (mips32->dsp_rev != DSP_REV2) { + command_print(CMD_CTX, "only DSP Rev 2 supported by this processor"); + return ERROR_OK; + } + + /* two or more argument, access a single register/select (write if third argument is given) */ + if (CMD_ARGC < 2) { + uint32_t value; + + if (CMD_ARGC == 0) { + value = 0; + for (int i = 0; i < MIPS32NUMDSPREGS; i++) { + retval = mips32_pracc_read_dsp_regs(ejtag_info, &value, mips32_dsp_regs[i].reg); + if (retval != ERROR_OK) { + command_print(CMD_CTX, "couldn't access reg %s", mips32_dsp_regs[i].name); + return retval; + } + command_print(CMD_CTX, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value); + } + } else { + value = 0; + for (int i = 0; i < MIPS32NUMDSPREGS; i++) { + /* find register name */ + if (strcmp(mips32_dsp_regs[i].name, CMD_ARGV[0]) == 0) { + retval = mips32_pracc_read_dsp_regs(ejtag_info, &value, mips32_dsp_regs[i].reg); + command_print(CMD_CTX, "0x%8.8x", value); + return retval; + } + } + + LOG_ERROR("BUG: register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else { + if (CMD_ARGC == 2) { + uint32_t value; + char tmp = *CMD_ARGV[0]; + + if (isdigit(tmp) == false) { + for (int i = 0; i < MIPS32NUMCP0REGS; i++) { + /* find register name */ + if (strcmp(mips32_dsp_regs[i].name, CMD_ARGV[0]) == 0) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + retval = mips32_pracc_write_dsp_regs (ejtag_info, value, mips32_dsp_regs[i].reg); + return retval; + } + } + + LOG_ERROR("BUG: register '%s' not found", CMD_ARGV[0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else if (CMD_ARGC == 3) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + } + + return ERROR_OK; +} + COMMAND_HANDLER(mips32_handle_scan_delay_command) { return mips32_scan_delay_command(cmd); @@ -925,6 +1020,14 @@ static const struct command_registration mips32_exec_command_handlers[] = { .help = "display/set scan delay in nano seconds", .usage = "[value]", }, + { + .name = "dsp", + .handler = mips32_handle_dsp_command, + .mode = COMMAND_EXEC, + .help = "display or set DSP register; " + "with no arguments, displays all registers and their values", + .usage = "[(register_number|register_name) [value]]", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/mips32.h b/src/target/mips32.h index 45ef644..de7b423 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -312,6 +312,31 @@ struct mips32_algorithm { #define MIPS16_SDBBP 0xE801 #define MICRO_MIPS32_SDBBP 0x000046C0 #define MICRO_MIPS_SDBBP 0x46C0 +#define MIPS32_DSP_ENABLE 0x1000000 + +#define MICRO_MIPS_OP_MFHI 0x007C +#define MICRO_MIPS_OP_MFLO 0x107C + +#define MICRO_MIPS_OP_MTHI 0x207C +#define MICRO_MIPS_OP_MTLO 0x307C + +#define MICRO_DSP_I_INST(rs, ac, opcode) \ + ((0 << 21) | ((rs) << 16) | ((ac) << 14) | (opcode)) + +#define MICRO_DSP_MFLO(reg, ac) MICRO_DSP_I_INST(reg, ac, MICRO_MIPS_OP_MFLO) +#define MICRO_DSP_MFHI(reg, ac) MICRO_DSP_I_INST(reg, ac, MICRO_MIPS_OP_MFHI) +#define MICRO_DSP_MTLO(reg, ac) MICRO_DSP_I_INST(reg, ac, MICRO_MIPS_OP_MTLO) +#define MICRO_DSP_MTHI(reg, ac) MICRO_DSP_I_INST(reg, ac, MICRO_MIPS_OP_MTHI) + + +#define MICRO_MIPS_OP_RDDSP 0x067C +#define MICRO_MIPS_OP_WRDSP 0x167C + +#define MICRO_DSP_R_INST(rt, mask, opcode) \ + ((0 << 26) | ((rt) << 21) | ((mask) << 14) | (opcode)) + +#define MICRO_DSP_RDDSP(rt, mask) MICRO_DSP_R_INST(rt, mask, MICRO_MIPS_OP_RDDSP) +#define MICRO_DSP_WRDSP(rt, mask) MICRO_DSP_R_INST(rt, mask, MICRO_MIPS_OP_WRDSP) extern const struct command_registration mips32_command_handlers[]; diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index aaaff75..f9985dd 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -985,6 +985,131 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) ejtag_info->reg10 = regs[10]; exit: pracc_queue_free(&ctx); + + return ctx.retval; +} + +int mips32_pracc_read_dsp_regs(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t regs) +{ + struct pracc_queue_info ctx = {.max_code = 48}; + static uint32_t dsp_read_code[] = { + 0x00204010, /* MFHI (t0,1) */ + 0x00404010, /* MFHI (t0,2) */ + 0x00604010, /* MFHI (t0,3) */ + 0x00204012, /* MFLO (t0,1) */ + 0x00404012, /* MFLO (t0,2) */ + 0x00604012, /* MFLO (t0,3) */ + 0x7fff44b8, /* MICRO_DSP_RDDSP (t0,0x1F), */ + }; + + /* check status register to determine if dsp register access is enabled */ + + /* Get status register so it can be restored later */ + + /* Init context queue */ + pracc_queue_init(&ctx); + if (ctx.retval != ERROR_OK) + goto exit; + + pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* move $15 to COP0 DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + + /* Save Status Register */ + pracc_add(&ctx, 0, MIPS32_MFC0(9, 12, 0)); /* move status to $9 (t1) */ + + /* Read it again in order to modify it */ + pracc_add(&ctx, 0, MIPS32_MFC0(8, 12, 0)); /* move status to $0 (t0) */ + + /* Enable access to DSP registers by setting MX bit in status register */ + pracc_add(&ctx, 0, MIPS32_LUI(10, UPPER16(MIPS32_DSP_ENABLE))); /* $15 = MIPS32_PRACC_STACK */ + pracc_add(&ctx, 0, MIPS32_ORI(10, 10, LOWER16(MIPS32_DSP_ENABLE))); + pracc_add(&ctx, 0, MIPS32_OR(8, 8, 10)); + pracc_add(&ctx, 0, MIPS32_MTC0(8, 12, 0)); /* Enable DSP - update status registers */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + + pracc_add(&ctx, 0, dsp_read_code[regs]); /* move AC or Control to $8 (t0) */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + pracc_add(&ctx, 0, MIPS32_MTC0(9, 12, 0)); /* Restore status registers to previous setting */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $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_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 of $9 */ + pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 of $9 */ + + pracc_add(&ctx, 0, MIPS32_LUI(10, UPPER16(ejtag_info->reg10))); /* restore upper 16 of $10 */ + pracc_add(&ctx, 0, MIPS32_ORI(10, 10, LOWER16(ejtag_info->reg10))); /* restore lower 16 of $10 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + + ctx.retval = mips32_pracc_exec(ejtag_info, &ctx, val); +exit: + pracc_queue_free(&ctx); + return ctx.retval; +} + +int mips32_pracc_write_dsp_regs(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t regs) +{ + struct pracc_queue_info ctx = {.max_code = 48}; + static uint32_t dsp_write_code[] = { + 0x01000811, /* MTHI (t0,1) */ + 0x01001011, /* MTHI (t0,2) */ + 0x01001811, /* MTHI (t0,3) */ + 0x01000813, /* MTLO (t0,1) */ + 0x01001013, /* MTLO (t0,2) */ + 0x01001813, /* MTLO (t0,3) */ + 0x7d1ffcf8, /* WRDSP (t0,0x1F) */ + }; + + /* Init context queue */ + pracc_queue_init(&ctx); + if (ctx.retval != ERROR_OK) + goto exit; + + pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* move $15 to COP0 DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + + /* Save Status Register */ + pracc_add(&ctx, 0, MIPS32_MFC0(9, 12, 0)); /* move status to $9 (t1) */ + + /* Read it again in order to modify it */ + pracc_add(&ctx, 0, MIPS32_MFC0(8, 12, 0)); /* move status to $0 (t0) */ + + /* Enable access to DSP registers by setting MX bit in status register */ + pracc_add(&ctx, 0, MIPS32_LUI(10, UPPER16(MIPS32_DSP_ENABLE))); /* $15 = MIPS32_PRACC_STACK */ + pracc_add(&ctx, 0, MIPS32_ORI(10, 10, LOWER16(MIPS32_DSP_ENABLE))); + pracc_add(&ctx, 0, MIPS32_OR(8, 8, 10)); + pracc_add(&ctx, 0, MIPS32_MTC0(8, 12, 0)); /* Enable DSP - update status registers */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + + pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(val))); /* Load val to $8 (t0) */ + pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(val))); + + pracc_add(&ctx, 0, dsp_write_code[regs]); /* move AC or Control to $8 (t0) */ + + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + pracc_add(&ctx, 0, MIPS32_MTC0(9, 12, 0)); /* Restore status registers to previous setting */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $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_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 of $9 */ + pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 of $9 */ + + pracc_add(&ctx, 0, MIPS32_LUI(10, UPPER16(ejtag_info->reg10))); /* restore upper 16 of $10 */ + pracc_add(&ctx, 0, MIPS32_ORI(10, 10, LOWER16(ejtag_info->reg10))); /* restore lower 16 of $10 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop */ + + ctx.retval = mips32_pracc_exec(ejtag_info, &ctx, NULL); +exit: + pracc_queue_free(&ctx); return ctx.retval; } diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index eab5f73..a7bc277 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -99,6 +99,37 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, * @return ERROR_OK on Sucess, ERROR_FAIL otherwise */ int mips32_cp0_write(struct mips_ejtag *ejtag_info, - uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); + uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); +/** + * \b mips32_dsp_read + * + * Simulates mfc0 ASM instruction (Move From C0), + * i.e. implements copro C0 Register read. + * + * @param[in] ejtag_info + * @param[in] val Storage to hold read value + * @param[in] cp0_reg Number of copro C0 register we want to read + * @param[in] cp0_sel Select for the given C0 register + * + * @return ERROR_OK on Sucess, ERROR_FAIL otherwise + */ +int mips32_pracc_read_dsp_regs(struct mips_ejtag *ejtag_info, + uint32_t *val, uint32_t regs); + +/** + * \b mips32_dsp_write + * + * Simulates mtc0 ASM instruction (Move To C0), + * i.e. implements copro C0 Register write. + * + * @param[in] ejtag_info + * @param[in] val Value to be written + * @param[in] cp0_reg Number of copro C0 register we want to write to + * @param[in] cp0_sel Select for the given C0 register + * + * @return ERROR_OK on Sucess, ERROR_FAIL otherwise + */ +int mips32_pracc_write_dsp_regs(struct mips_ejtag *ejtag_info, + uint32_t val, uint32_t regs); #endif diff --git a/src/target/mips_common.c b/src/target/mips_common.c index 3fc5ba8..59e99dd 100644 --- a/src/target/mips_common.c +++ b/src/target/mips_common.c @@ -672,7 +672,6 @@ int mips_common_set_breakpoint(struct target *target, breakpoint->set = bp_num + 1; comparator_list[bp_num].used = 1; - comparator_list[bp_num].bp_value = breakpoint->address; /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved. * Warning: there is no IB ASID registers in 2.0. -- ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel