aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWalter Ji <walter.ji@oss.cipunited.com>2023-09-26 16:56:02 +0800
committerAntonio Borneo <borneo.antonio@gmail.com>2023-10-25 01:33:10 +0000
commit18c64af13500342da5dc304cb3f2024078815bd4 (patch)
treea5c69dbc6afa31790053b6848961f1f72abe80a3 /src
parentc7d1f0ddabb301e00738686671b939bb92a06ed9 (diff)
downloadriscv-openocd-18c64af13500342da5dc304cb3f2024078815bd4.zip
riscv-openocd-18c64af13500342da5dc304cb3f2024078815bd4.tar.gz
riscv-openocd-18c64af13500342da5dc304cb3f2024078815bd4.tar.bz2
target/mips32: rework mips core register related functions
Update mips core definitions. Reworked mips core register structure and read/write function. Add coprocessor0 register definitions for target configuration. Change-Id: I59c1f4cc4020db8a78e8d79f7421b87382fa1709 Signed-off-by: Walter Ji <walter.ji@oss.cipunited.com> Reviewed-on: https://review.openocd.org/c/openocd/+/7864 Reviewed-by: Oleksij Rempel <linux@rempel-privat.de> Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/target/mips32.c278
-rw-r--r--src/target/mips32.h168
-rw-r--r--src/target/mips32_pracc.c196
-rw-r--r--src/target/mips32_pracc.h6
-rw-r--r--src/target/mips_ejtag.h11
-rw-r--r--src/target/mips_m4k.c22
6 files changed, 508 insertions, 173 deletions
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 4e6d251..18160b2 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -27,7 +27,7 @@ static const char *mips_isa_strings[] = {
"MIPS32", "MIPS16", "", "MICRO MIPS32",
};
-#define MIPS32_GDB_DUMMY_FP_REG 1
+#define MIPS32_GDB_FP_REG 1
/*
* GDB registers
@@ -39,7 +39,7 @@ static const struct {
enum reg_type type;
const char *group;
const char *feature;
- int flag;
+ int size;
} mips32_regs[] = {
{ 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
@@ -73,88 +73,93 @@ static const struct {
{ 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
-
- { 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 70, "fcsr", REG_TYPE_INT, "float",
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 71, "fir", REG_TYPE_INT, "float",
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
+ { 32, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
+ { 33, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
+
+ { MIPS32_REGLIST_FP_INDEX + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+ { MIPS32_REGLIST_FP_INDEX + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
+ "org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
+
+ { MIPS32_REGLIST_FPC_INDEX + 0, "fcsr", REG_TYPE_INT, "float",
+ "org.gnu.gdb.mips.fpu", 0 },
+ { MIPS32_REGLIST_FPC_INDEX + 1, "fir", REG_TYPE_INT, "float",
+ "org.gnu.gdb.mips.fpu", 0 },
+
+ { MIPS32_REGLIST_C0_STATUS_INDEX, "status", REG_TYPE_INT, NULL,
+ "org.gnu.gdb.mips.cp0", 0 },
+ { MIPS32_REGLIST_C0_BADVADDR_INDEX, "badvaddr", REG_TYPE_INT, NULL,
+ "org.gnu.gdb.mips.cp0", 0 },
+ { MIPS32_REGLIST_C0_CAUSE_INDEX, "cause", REG_TYPE_INT, NULL,
+ "org.gnu.gdb.mips.cp0", 0 },
+ { MIPS32_REGLIST_C0_PC_INDEX, "pc", REG_TYPE_INT, NULL,
+ "org.gnu.gdb.mips.cpu", 0 },
+ { MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL,
+ "org.gnu.gdb.mips.cp0", 0 },
};
-
#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
-static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
-
static int mips32_get_core_reg(struct reg *reg)
{
int retval;
@@ -174,12 +179,21 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
{
struct mips32_core_reg *mips32_reg = reg->arch_info;
struct target *target = mips32_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
+ uint64_t value;
+
+ if (reg->size == 64)
+ value = buf_get_u64(buf, 0, 64);
+ else
+ value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
- buf_set_u32(reg->value, 0, 32, value);
+ if (reg->size == 64)
+ buf_set_u64(reg->value, 0, 64, value);
+ else
+ buf_set_u32(reg->value, 0, 32, value);
+
reg->dirty = true;
reg->valid = true;
@@ -188,7 +202,8 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
static int mips32_read_core_reg(struct target *target, unsigned int num)
{
- uint32_t reg_value;
+ unsigned int cnum;
+ uint64_t reg_value = 0;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@@ -196,17 +211,40 @@ static int mips32_read_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
- reg_value = mips32->core_regs[num];
- buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+ if (num >= MIPS32_REGLIST_C0_INDEX) {
+ /* CP0 */
+ cnum = num - MIPS32_REGLIST_C0_INDEX;
+ reg_value = mips32->core_regs.cp0[cnum];
+ buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+ } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
+ /* FPCR */
+ cnum = num - MIPS32_REGLIST_FPC_INDEX;
+ reg_value = mips32->core_regs.fpcr[cnum];
+ buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+ } else if (num >= MIPS32_REGLIST_FP_INDEX) {
+ /* FPR */
+ cnum = num - MIPS32_REGLIST_FP_INDEX;
+ reg_value = mips32->core_regs.fpr[cnum];
+ buf_set_u64(mips32->core_cache->reg_list[num].value, 0, 64, reg_value);
+ } else {
+ /* GPR */
+ cnum = num - MIPS32_REGLIST_GP_INDEX;
+ reg_value = mips32->core_regs.gpr[cnum];
+ buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
+ }
+
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
+ LOG_DEBUG("read core reg %i value 0x%" PRIx64 "", num, reg_value);
+
return ERROR_OK;
}
static int mips32_write_core_reg(struct target *target, unsigned int num)
{
- uint32_t reg_value;
+ unsigned int cnum;
+ uint64_t reg_value;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@@ -214,9 +252,29 @@ static int mips32_write_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
- reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
- mips32->core_regs[num] = reg_value;
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
+ 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);
+ mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
+ } else if (num >= MIPS32_REGLIST_FPC_INDEX) {
+ /* FPCR */
+ cnum = num - MIPS32_REGLIST_FPC_INDEX;
+ reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
+ mips32->core_regs.fpcr[cnum] = (uint32_t)reg_value;
+ } else if (num >= MIPS32_REGLIST_FP_INDEX) {
+ /* FPR */
+ cnum = num - MIPS32_REGLIST_FP_INDEX;
+ reg_value = buf_get_u64(mips32->core_cache->reg_list[num].value, 0, 64);
+ mips32->core_regs.fpr[cnum] = reg_value;
+ } else {
+ /* GPR */
+ cnum = num - MIPS32_REGLIST_GP_INDEX;
+ reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
+ mips32->core_regs.gpr[cnum] = (uint32_t)reg_value;
+ }
+
+ LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
@@ -246,10 +304,9 @@ int mips32_save_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
/* read core registers */
- mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
+ mips32_pracc_read_regs(mips32);
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (!mips32->core_cache->reg_list[i].valid)
@@ -265,7 +322,6 @@ int mips32_restore_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (mips32->core_cache->reg_list[i].dirty)
@@ -273,7 +329,7 @@ int mips32_restore_context(struct target *target)
}
/* write core regs */
- mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
+ mips32_pracc_write_regs(mips32);
return ERROR_OK;
}
@@ -285,7 +341,7 @@ int mips32_arch_state(struct target *target)
LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
mips_isa_strings[mips32->isa_mode],
debug_reason_name(target),
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
+ buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
return ERROR_OK;
}
@@ -322,25 +378,19 @@ struct reg_cache *mips32_build_reg_cache(struct target *target)
arch_info[i].mips32_common = mips32;
reg_list[i].name = mips32_regs[i].name;
- reg_list[i].size = 32;
-
- if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) {
- reg_list[i].value = mips32_gdb_dummy_fp_value;
- reg_list[i].valid = true;
- reg_list[i].arch_info = NULL;
- register_init_dummy(&reg_list[i]);
- } else {
- reg_list[i].value = calloc(1, 4);
- reg_list[i].valid = false;
- reg_list[i].type = &mips32_reg_type;
- reg_list[i].arch_info = &arch_info[i];
-
- reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
- if (reg_list[i].reg_data_type)
- reg_list[i].reg_data_type->type = mips32_regs[i].type;
- else
- LOG_ERROR("unable to allocate reg type list");
- }
+ reg_list[i].size = mips32_regs[i].size ? 64 : 32;
+
+ reg_list[i].value = mips32_regs[i].size ? calloc(1, 8) : calloc(1, 4);
+ reg_list[i].valid = false;
+ reg_list[i].type = &mips32_reg_type;
+ reg_list[i].arch_info = &arch_info[i];
+
+ reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+ if (reg_list[i].reg_data_type)
+ reg_list[i].reg_data_type->type = mips32_regs[i].type;
+ else
+ LOG_ERROR("unable to allocate reg type list");
+
reg_list[i].dirty = false;
@@ -407,7 +457,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
return ERROR_TARGET_TIMEOUT;
}
- pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
+ pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
if (exit_point && (pc != exit_point)) {
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
return ERROR_TARGET_TIMEOUT;
diff --git a/src/target/mips32.h b/src/target/mips32.h
index 3d03e98..7bf6384 100644
--- a/src/target/mips32.h
+++ b/src/target/mips32.h
@@ -57,6 +57,139 @@
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
+/* Bit Mask indicating CP0 register supported by this core */
+#define MIPS_CP0_MK4 0x0001
+#define MIPS_CP0_MAPTIV_UC 0x0002
+#define MIPS_CP0_MAPTIV_UP 0x0004
+#define MIPS_CP0_IAPTIV 0x0008
+
+/* CP0 Status register fields */
+#define MIPS32_CP0_STATUS_FR_SHIFT 26
+#define MIPS32_CP0_STATUS_CU1_SHIFT 29
+
+/* CP1 FIR register fields */
+#define MIPS32_CP1_FIR_F64_SHIFT 22
+
+static const struct {
+ unsigned int reg;
+ unsigned int sel;
+ const char *name;
+ const unsigned int core;
+} mips32_cp0_regs[] = {
+ {0, 0, "index", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {0, 1, "mvpcontrol", MIPS_CP0_IAPTIV},
+ {0, 2, "mvpconf0", MIPS_CP0_IAPTIV},
+ {0, 3, "mvpconf1", MIPS_CP0_IAPTIV},
+ {1, 0, "random", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {1, 1, "vpecontrol", MIPS_CP0_IAPTIV},
+ {1, 2, "vpeconf0", MIPS_CP0_IAPTIV},
+ {1, 3, "vpeconf1", MIPS_CP0_IAPTIV},
+ {1, 4, "yqmask", MIPS_CP0_IAPTIV},
+ {1, 5, "vpeschedule", MIPS_CP0_IAPTIV},
+ {1, 6, "vpeschefback", MIPS_CP0_IAPTIV},
+ {1, 7, "vpeopt", MIPS_CP0_IAPTIV},
+ {2, 0, "entrylo0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {2, 1, "tcstatus", MIPS_CP0_IAPTIV},
+ {2, 2, "tcbind", MIPS_CP0_IAPTIV},
+ {2, 3, "tcrestart", MIPS_CP0_IAPTIV},
+ {2, 4, "tchalt", MIPS_CP0_IAPTIV},
+ {2, 5, "tccontext", MIPS_CP0_IAPTIV},
+ {2, 6, "tcschedule", MIPS_CP0_IAPTIV},
+ {2, 7, "tcschefback", MIPS_CP0_IAPTIV},
+ {3, 0, "entrylo1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {3, 7, "tcopt", MIPS_CP0_IAPTIV},
+ {4, 0, "context", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {4, 2, "userlocal", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {5, 0, "pagemask", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {5, 1, "pagegrain", MIPS_CP0_MAPTIV_UP},
+ {5, 2, "segctl0", MIPS_CP0_IAPTIV},
+ {5, 3, "segctl1", MIPS_CP0_IAPTIV},
+ {5, 4, "segctl2", MIPS_CP0_IAPTIV},
+ {6, 0, "wired", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {6, 1, "srsconf0", MIPS_CP0_IAPTIV},
+ {6, 2, "srsconf1", MIPS_CP0_IAPTIV},
+ {6, 3, "srsconf2", MIPS_CP0_IAPTIV},
+ {6, 4, "srsconf3", MIPS_CP0_IAPTIV},
+ {6, 5, "srsconf4", MIPS_CP0_IAPTIV},
+ {7, 0, "hwrena", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {8, 0, "badvaddr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {8, 1, "badinstr", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+ {8, 2, "badinstrp", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+ {9, 0, "count", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {10, 0, "entryhi", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
+ {10, 4, "guestctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {10, 5, "guestctl2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {10, 6, "guestctl3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {11, 0, "compare", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {11, 4, "guestctl0ext", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {12, 0, "status", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {12, 1, "intctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {12, 2, "srsctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {12, 3, "srsmap", MIPS_CP0_IAPTIV},
+ {12, 3, "srsmap1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+ {12, 4, "view_ipl", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {12, 5, "srsmap2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+ {12, 6, "guestctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {12, 7, "gtoffset", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
+ {13, 0, "cause", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {13, 5, "nestedexc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {14, 0, "epc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {14, 2, "nestedepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {15, 0, "prid", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {15, 1, "ebase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {15, 2, "cdmmbase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {15, 3, "cmgcrbase", MIPS_CP0_IAPTIV},
+ {16, 0, "config", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 1, "config1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 2, "config2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 3, "config3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 4, "config4", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 5, "config5", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {16, 7, "config7", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {17, 0, "lladdr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {18, 0, "watchlo0", MIPS_CP0_IAPTIV},
+ {18, 1, "watchlo1", MIPS_CP0_IAPTIV},
+ {18, 2, "watchlo2", MIPS_CP0_IAPTIV},
+ {18, 3, "watchlo3", MIPS_CP0_IAPTIV},
+ {19, 0, "watchhi0", MIPS_CP0_IAPTIV},
+ {19, 1, "watchhi1", MIPS_CP0_IAPTIV},
+ {19, 2, "watchhi2", MIPS_CP0_IAPTIV},
+ {19, 3, "watchhi3", MIPS_CP0_IAPTIV},
+ {23, 0, "debug", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {23, 1, "tracecontrol", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {23, 2, "tracecontrol2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {23, 3, "usertracedata1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {23, 4, "tracebpc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {23, 4, "traceibpc", MIPS_CP0_IAPTIV},
+ {23, 5, "tracedbpc", MIPS_CP0_IAPTIV},
+ {24, 0, "depc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {24, 2, "tracecontrol3", MIPS_CP0_IAPTIV},
+ {24, 3, "usertracedata2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {25, 0, "perfctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {25, 1, "perfcnt0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {25, 2, "perfctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {25, 3, "perfcnt1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {26, 0, "errctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {27, 0, "cacheerr", MIPS_CP0_IAPTIV},
+ {28, 0, "itaglo", MIPS_CP0_IAPTIV},
+ {28, 0, "taglo", MIPS_CP0_IAPTIV},
+ {28, 1, "idatalo", MIPS_CP0_IAPTIV},
+ {28, 1, "datalo", MIPS_CP0_IAPTIV},
+ {28, 2, "dtaglo", MIPS_CP0_IAPTIV},
+ {28, 3, "ddatalo", MIPS_CP0_IAPTIV},
+ {28, 4, "l23taglo", MIPS_CP0_IAPTIV},
+ {28, 5, "l23datalo", MIPS_CP0_IAPTIV},
+ {29, 1, "idatahi", MIPS_CP0_IAPTIV},
+ {29, 2, "dtaghi", MIPS_CP0_IAPTIV},
+ {29, 5, "l23datahi", MIPS_CP0_IAPTIV},
+ {30, 0, "errorepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {31, 0, "desave", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
+ {31, 2, "kscratch1", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+ {31, 3, "kscratch2", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
+};
+
+#define MIPS32NUMCP0REGS ((int)ARRAY_SIZE(mips32_cp0_regs))
+
/* Insert extra NOPs after the DRET instruction on exit from debug. */
#define EJTAG_QUIRK_PAD_DRET BIT(0)
@@ -67,6 +200,30 @@ enum {
MIPS32NUMCOREREGS
};
+/* offsets into mips32 core register cache */
+
+#define MIPS32_REG_GP_COUNT 34
+#define MIPS32_REG_FP_COUNT 32
+#define MIPS32_REG_FPC_COUNT 2
+#define MIPS32_REG_C0_COUNT 5
+
+#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_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0)
+#define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1)
+#define MIPS32_REGLIST_C0_CAUSE_INDEX (MIPS32_REGLIST_C0_INDEX + 2)
+#define MIPS32_REGLIST_C0_PC_INDEX (MIPS32_REGLIST_C0_INDEX + 3)
+#define MIPS32_REGLIST_C0_GUESTCTL1_INDEX (MIPS32_REGLIST_C0_INDEX + 4)
+
+#define MIPS32_REG_C0_STATUS_INDEX 0
+#define MIPS32_REG_C0_BADVADDR_INDEX 1
+#define MIPS32_REG_C0_CAUSE_INDEX 2
+#define MIPS32_REG_C0_PC_INDEX 3
+#define MIPS32_REG_C0_GUESTCTL1_INDEX 4
+
enum mips32_isa_mode {
MIPS32_ISA_MIPS32 = 0,
MIPS32_ISA_MIPS16E = 1,
@@ -86,13 +243,22 @@ struct mips32_comparator {
uint32_t reg_address;
};
+struct mips32_core_regs {
+ uint32_t gpr[MIPS32_REG_GP_COUNT];
+ uint64_t fpr[MIPS32_REG_FP_COUNT];
+ uint32_t fpcr[MIPS32_REG_FPC_COUNT];
+ uint32_t cp0[MIPS32_REG_C0_COUNT];
+};
+
struct mips32_common {
unsigned int common_magic;
void *arch_info;
struct reg_cache *core_cache;
struct mips_ejtag ejtag_info;
- uint32_t core_regs[MIPS32NUMCOREREGS];
+
+ struct mips32_core_regs core_regs;
+
enum mips32_isa_mode isa_mode;
enum mips32_isa_imp isa_imp;
diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
index c4704b5..9f0d87c 100644
--- a/src/target/mips32_pracc.c
+++ b/src/target/mips32_pracc.c
@@ -823,9 +823,13 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
return retval;
}
-int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
+int mips32_pracc_write_regs(struct mips32_common *mips32)
{
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
+ uint32_t *gprs = mips32->core_regs.gpr;
+ uint32_t *c0rs = mips32->core_regs.cp0;
+
pracc_queue_init(&ctx);
uint32_t cp0_write_code[] = {
@@ -837,66 +841,178 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */
};
+ uint32_t cp0_write_data[] = {
+ /* lo */
+ gprs[32],
+ /* hi */
+ gprs[33],
+ /* status */
+ c0rs[0],
+ /* badvaddr */
+ c0rs[1],
+ /* cause */
+ c0rs[2],
+ /* depc (pc) */
+ c0rs[3],
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) {
+ /* load CP0 value in $1 */
+ pracc_add_li32(&ctx, 1, cp0_write_data[i], 0);
+ /* write value from $1 to CP0 register */
+ pracc_add(&ctx, 0, cp0_write_code[i]);
+ }
+
/* load registers 2 to 31 with li32, optimize */
for (int i = 2; i < 32; i++)
- pracc_add_li32(&ctx, i, regs[i], 1);
+ pracc_add_li32(&ctx, i, gprs[i], 1);
- for (int i = 0; i != 6; i++) {
- pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */
- pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
- }
- pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
- pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1])))); /* load upper half word in $1 */
- pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
+ /* load $15 in DeSave */
+ pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
+ /* load upper half word in $1 */
+ pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((gprs[1]))));
+ /* jump to start */
+ pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
+ /* load lower half word in $1 */
+ pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((gprs[1]))));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
- ejtag_info->reg8 = regs[8];
- ejtag_info->reg9 = regs[9];
+ ejtag_info->reg8 = gprs[8];
+ ejtag_info->reg9 = gprs[9];
pracc_queue_free(&ctx);
return ctx.retval;
}
-int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
+/* Saves content in `$1` to `DeSave(cp0.31.0)` and loads `MIPS32_PRACC_BASE_ADDR` into `$1` */
+static void mips32_pracc_store_regs_set_base_addr(struct pracc_queue_info *ctx)
{
- struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
- pracc_queue_init(&ctx);
+ /* move $1 to COP0 DeSave */
+ pracc_add(ctx, 0, MIPS32_MTC0(ctx->isa, 1, 31, 0));
+ /* $1 = MIP32_PRACC_BASE_ADDR */
+ pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, 1, PRACC_UPPER_BASE_ADDR));
+}
- uint32_t cp0_read_code[] = {
- MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */
- MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */
- MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */
- MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */
- MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */
- MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */
+/* This function assumes the address for saving is stored in `$1`.
+ * And that action is performed in `mips32_pracc_set_save_base_addr`.
+ */
+static void mips32_pracc_store_regs_gpr(struct pracc_queue_info *ctx, unsigned int offset_gpr)
+{
+ for (int i = 2; i != 32; i++)
+ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset_gpr + (i * 4),
+ MIPS32_SW(ctx->isa, i, PRACC_OUT_OFFSET + offset_gpr + (i * 4), 1));
+}
+
+static void mips32_pracc_store_regs_lohi(struct pracc_queue_info *ctx)
+{
+ uint32_t lohi_read_code[] = {
+ MIPS32_MFLO(ctx->isa, 8), /* move lo to $8 */
+ MIPS32_MFHI(ctx->isa, 8), /* move hi to $8 */
};
- pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0)); /* move $1 to COP0 DeSave */
- pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
+ /* store lo & hi */
+ for (int i = 0; i < 2; i++) {
+ /* load COP0 needed registers to $8 */
+ pracc_add(ctx, 0, lohi_read_code[i]);
+ /* store $8 at PARAM OUT */
+ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,
+ MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
+ }
+}
- for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
- MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1));
+/* Saves CP0 registers [status, badvaddr, cause, depc] */
+static void mips32_pracc_store_regs_cp0_context(struct pracc_queue_info *ctx, unsigned int offset_cp0)
+{
+ uint32_t cp0_read_code[] = {
+ MIPS32_MFC0(ctx->isa, 8, 12, 0), /* move status to $8 */
+ MIPS32_MFC0(ctx->isa, 8, 8, 0), /* move badvaddr to $8 */
+ MIPS32_MFC0(ctx->isa, 8, 13, 0), /* move cause to $8 */
+ MIPS32_MFC0(ctx->isa, 8, 24, 0), /* move depc (pc) to $8 */
+ };
- for (int i = 0; i != 6; i++) {
- pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
- MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
+ /* store cp0 */
+ for (size_t i = 0; i < ARRAY_SIZE(cp0_read_code); i++) {
+ size_t offset = offset_cp0 + (i * 4);
+
+ /* load COP0 needed registers to $8 */
+ pracc_add(ctx, 0, cp0_read_code[i]);
+ /* store $8 at PARAM OUT */
+ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset,
+ MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + offset, 1));
}
- pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0)); /* move DeSave to $8, reg1 value */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
- MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1));
+}
- pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
- pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
+/* Loads original content of $1 into $8,
+ * then store it to the batch data access address.
+ * Finally it restores $1 from DeSave.
+ */
+static void mips32_pracc_store_regs_restore(struct pracc_queue_info *ctx)
+{
+ /* move DeSave to $8, reg1 value */
+ pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 8, 31, 0));
+ /* store reg1 value from $8 to param out */
+ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + 4,
+ MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + 4, 1));
+
+ /* move COP0 DeSave to $1, restore reg1 */
+ pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 1, 31, 0));
+}
+
+/* This function performs following actions:
+ * Saves `$1` to `DeSave`,
+ * then load `PRACC_UPPER_BASE_ADDR` for saving the register data structure into `$1`,
+ * Saves `$2` ~ `$31` to `PRACC_UPPER_BASE_ADDR + offset_gpr`
+ * Saves HI and LO,
+ * Saves necessary cp0 registers.
+*/
+static void mips32_pracc_store_regs(struct pracc_queue_info *ctx,
+ unsigned int offset_gpr, unsigned int offset_cp0)
+{
+ mips32_pracc_store_regs_set_base_addr(ctx);
+ mips32_pracc_store_regs_gpr(ctx, offset_gpr);
+ mips32_pracc_store_regs_lohi(ctx);
+ mips32_pracc_store_regs_cp0_context(ctx, offset_cp0);
+ mips32_pracc_store_regs_restore(ctx);
+}
+
+int mips32_pracc_read_regs(struct mips32_common *mips32)
+{
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+ struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
+ struct mips32_core_regs *core_regs = &mips32->core_regs;
+ unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
+ unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
+
+ /*
+ * This procedure has to be in 2 distinctive steps, because we can
+ * only know whether FP is enabled after reading CP0.
+ *
+ * Step 1: Read everything except CP1 stuff
+ * Step 2: Read CP1 stuff if FP is implemented
+ */
+
+ pracc_queue_init(&ctx);
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1);
+ mips32_pracc_store_regs(&ctx, offset_gpr, offset_cp0);
+
+ /* 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);
- ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
- ejtag_info->reg9 = regs[9];
pracc_queue_free(&ctx);
+
+ /* reg8 is saved but not restored, next called function should restore it */
+ ejtag_info->reg8 = mips32->core_regs.gpr[8];
+ ejtag_info->reg9 = mips32->core_regs.gpr[9];
+
+ /* we only care if FP is actually impl'd and if cp1 is enabled */
+ /* since we already read cp0 in the prev step */
+ /* now we know what's in cp0.status */
+ /* TODO: Read FPRs */
+
return ctx.retval;
}
diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h
index 1b00768..587a446 100644
--- a/src/target/mips32_pracc.h
+++ b/src/target/mips32_pracc.h
@@ -36,6 +36,8 @@
#define PRACC_BLOCK 128 /* 1 Kbyte */
+struct mips32_common;
+
struct pa_list {
uint32_t instr;
uint32_t addr;
@@ -64,8 +66,8 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info,
int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
int write_t, uint32_t addr, int count, uint32_t *buf);
-int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
-int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
+int mips32_pracc_read_regs(struct mips32_common *mips32);
+int mips32_pracc_write_regs(struct mips32_common *mips32);
/**
* \b mips32_cp0_read
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
index eb80742..852444a 100644
--- a/src/target/mips_ejtag.h
+++ b/src/target/mips_ejtag.h
@@ -123,11 +123,12 @@
/* Debug Control Register DCR */
#define EJTAG_DCR 0xFF300000
-#define EJTAG_DCR_ENM (1 << 29)
-#define EJTAG_DCR_DB (1 << 17)
-#define EJTAG_DCR_IB (1 << 16)
-#define EJTAG_DCR_INTE (1 << 4)
-#define EJTAG_DCR_MP (1 << 2)
+#define EJTAG_DCR_ENM BIT(29)
+#define EJTAG_DCR_FDC BIT(18)
+#define EJTAG_DCR_DB BIT(17)
+#define EJTAG_DCR_IB BIT(16)
+#define EJTAG_DCR_INTE BIT(4)
+#define EJTAG_DCR_MP BIT(2)
/* breakpoint support */
/* EJTAG_V20_* was tested on Broadcom BCM7401
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
index 46d241c..0a06bb1 100644
--- a/src/target/mips_m4k.c
+++ b/src/target/mips_m4k.c
@@ -108,11 +108,11 @@ static int mips_m4k_debug_entry(struct target *target)
mips32->isa_mode = MIPS32_ISA_MIPS32;
/* other than mips32 only and isa bit set ? */
- if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1))
+ if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1))
mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32;
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
+ buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32),
target_state_name(target));
return ERROR_OK;
@@ -443,18 +443,18 @@ static int mips_m4k_internal_restore(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
- mips32->core_cache->reg_list[MIPS32_PC].valid = true;
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode);
if (!current)
resume_pc = address;
else
- resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
+ resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
mips32_restore_context(target);
@@ -537,15 +537,15 @@ static int mips_m4k_step(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
- mips32->core_cache->reg_list[MIPS32_PC].valid = true;
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
/* the front-end may request us not to handle breakpoints */
if (handle_breakpoints) {
breakpoint = breakpoint_find(target,
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
+ buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
if (breakpoint)
mips_m4k_unset_breakpoint(target, breakpoint);
}