/*
* 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;
"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)
static const struct {
const char *name;
} mips32_dsp_regs[MIPS32NUMDSPREGS] = {
- { "hi0"},
{ "hi1"},
- { "hi2"},
- { "hi3"},
- { "lo0"},
{ "lo1"},
+ { "hi2"},
{ "lo2"},
+ { "hi3"},
{ "lo3"},
{ "control"},
};
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];
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);
/* 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");
}
};
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 */
};
};
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*/
};
*
* @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;
*
* @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;
}
*
* @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]);
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;
}
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)
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];
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:
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);
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);
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);
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;
}