target/mips32: rework mips core register related functions 64/7864/11
authorWalter Ji <walter.ji@oss.cipunited.com>
Tue, 26 Sep 2023 08:56:02 +0000 (16:56 +0800)
committerAntonio Borneo <borneo.antonio@gmail.com>
Wed, 25 Oct 2023 01:33:10 +0000 (01:33 +0000)
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>
src/target/mips32.c
src/target/mips32.h
src/target/mips32_pracc.c
src/target/mips32_pracc.h
src/target/mips_ejtag.h
src/target/mips_m4k.c

index 4e6d25118e9cc64e0d40367a31ab8bba711252de..18160b23739dcce43c11b3841af8245fdb0f8050 100644 (file)
@@ -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;
index 3d03e98c58275f02ae7c46a9a94904aa5716a418..7bf6384582d5eed5c1fc38158350d83ba3d45742 100644 (file)
 
 #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;
 
index c4704b5a5d90f68e424df1d046da23a7cc5746c3..9f0d87cd9833b6454fa25655067a8fdde1115424 100644 (file)
@@ -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;
 }
 
index 1b00768676bc2485ac0c99c727cbdf65b395e70f..587a446918d0f65eed425ccf96ebefc24e639807 100644 (file)
@@ -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
index eb80742d65701a899febf520b5187ba00c22c5fb..852444a5195ebde69f4de27a2a3ff3b8c279a761 100644 (file)
 
 /* 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
index 46d241cb3085492a274c05a989a6741c663ec6eb..0a06bb1604777778271a394e06d85307328d1d3c 100644 (file)
@@ -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);
        }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)