]> git.sur5r.net Git - openocd/commitdiff
mips32: add micromips isa handling
authorSalvador Arroyo <sarroyofdez@yahoo.es>
Sun, 7 May 2017 16:39:17 +0000 (18:39 +0200)
committerFreddie Chopin <freddie.chopin@gmail.com>
Mon, 8 May 2017 17:04:56 +0000 (18:04 +0100)
Read and save configuration registers, up to 4.
Config3 holds the micromips implementation info.
Added isa implementation info to mips32_common.
Added isa filter to avoid common mistakes, but only
if one isa mode is implemented.
When resuming the isa requested is set if more than
one isa mode is implemented.

Change-Id: I1d6526c5525bffac8d75e031b842b2edc6310e28
Signed-off-by: Salvador Arroyo <sarroyofdez@yahoo.es>
Reviewed-on: http://openocd.zylin.com/4123
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
src/target/mips32.c
src/target/mips32.h
src/target/mips_ejtag.h
src/target/mips_m4k.c
src/target/mips_m4k.h

index c5b7fbce8e4d3a1e1101f2a4414abff17905b199..93fb4e646b2d25e2aa452e8f1240b426b48d71a4 100644 (file)
@@ -34,7 +34,7 @@
 #include "register.h"
 
 static const char *mips_isa_strings[] = {
-       "MIPS32", "MIPS16"
+       "MIPS32", "MIPS16", "", "MICRO MIPS32",
 };
 
 #define MIPS32_GDB_DUMMY_FP_REG 1
@@ -375,6 +375,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s
        target->arch_info = mips32;
        mips32->common_magic = MIPS32_COMMON_MAGIC;
        mips32->fast_data_area = NULL;
+       mips32->isa_imp = MIPS32_ONLY;  /* default */
 
        /* has breakpoint/watchpoint unit been scanned */
        mips32->bp_scanned = 0;
@@ -388,7 +389,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s
        mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE;
        mips32->ejtag_info.mode = 0;                    /* Initial default value */
        mips32->ejtag_info.isa = 0;     /* isa on debug mips32, updated by poll function */
-
+       mips32->ejtag_info.config_regs = 0;     /* no config register read */
        return ERROR_OK;
 }
 
@@ -698,6 +699,50 @@ int mips32_enable_interrupts(struct target *target, int enable)
        return ERROR_OK;
 }
 
+/* read config to config3 cp0 registers and log isa implementation */
+int mips32_read_config_regs(struct target *target)
+{
+       struct mips32_common *mips32 = target_to_mips32(target);
+       struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+
+       if (ejtag_info->config_regs == 0)
+               for (int i = 0; i != 4; i++) {
+                       int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
+                               ejtag_info->config_regs = 0;
+                               return retval;
+                       }
+                       ejtag_info->config_regs = i + 1;
+                       if ((ejtag_info->config[i] & (1 << 31)) == 0)
+                               break;  /* no more config registers implemented */
+               }
+       else
+               return ERROR_OK;        /* already succesfully read */
+
+       LOG_DEBUG("read  %"PRId32" config registers", ejtag_info->config_regs);
+
+       if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
+               mips32->isa_imp = MIPS32_MIPS16;
+               LOG_USER("MIPS32 with MIPS16 support implemented");
+
+       } else if (ejtag_info->config_regs >= 4) {      /* config3 implemented */
+               unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
+               if (isa_imp == 1) {
+                       mips32->isa_imp = MMIPS32_ONLY;
+                       LOG_USER("MICRO MIPS32 only implemented");
+
+               } else if (isa_imp != 0) {
+                       mips32->isa_imp = MIPS32_MMIPS32;
+                       LOG_USER("MIPS32 and MICRO MIPS32 implemented");
+               }
+       }
+
+       if (mips32->isa_imp == MIPS32_ONLY)     /* initial default value */
+               LOG_USER("MIPS32 only implemented");
+
+       return ERROR_OK;
+}
 int mips32_checksum_memory(struct target *target, target_addr_t address,
                uint32_t count, uint32_t *checksum)
 {
@@ -756,7 +801,7 @@ int mips32_checksum_memory(struct target *target, target_addr_t address,
                return retval;
 
        mips32_info.common_magic = MIPS32_COMMON_MAGIC;
-       mips32_info.isa_mode = MIPS32_ISA_MIPS32;
+       mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;    /* run isa as in debug mode */
 
        init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
        buf_set_u32(reg_params[0].value, 0, 32, address);
@@ -766,11 +811,8 @@ int mips32_checksum_memory(struct target *target, target_addr_t address,
 
        int timeout = 20000 * (1 + (count / (1024 * 1024)));
 
-       /* same isa as in debug mode */
-       retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
-                       crc_algorithm->address | isa,
-                       (crc_algorithm->address + (sizeof(mips_crc_code) - 4)) | isa,
-                       timeout, &mips32_info);
+       retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
+                                     crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info);
 
        if (retval == ERROR_OK)
                *checksum = buf_get_u32(reg_params[0].value, 0, 32);
@@ -827,7 +869,7 @@ int mips32_blank_check_memory(struct target *target,
                return retval;
 
        mips32_info.common_magic = MIPS32_COMMON_MAGIC;
-       mips32_info.isa_mode = MIPS32_ISA_MIPS32;
+       mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
 
        init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
        buf_set_u32(reg_params[0].value, 0, 32, address);
@@ -838,11 +880,8 @@ int mips32_blank_check_memory(struct target *target,
        init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
        buf_set_u32(reg_params[2].value, 0, 32, erased_value);
 
-       /* same isa as in debug mode */
-       retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
-                       erase_check_algorithm->address | isa,
-                       (erase_check_algorithm->address + (sizeof(erase_check_code) - 4)) | isa,
-                       10000, &mips32_info);
+       retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address,
+                       erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
 
        if (retval == ERROR_OK)
                *blank = buf_get_u32(reg_params[2].value, 0, 32);
index d79451fb70ae6ae7dc96d4cad00f8c8f7349d642..928598f4c8a56277a14c4f4f70e9e4c4c0cb4d6f 100644 (file)
@@ -58,6 +58,9 @@
 #define MIPS32_CONFIG1_DL_SHIFT 10
 #define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
 
+#define MIPS32_CONFIG3_ISA_SHIFT       14
+#define MIPS32_CONFIG3_ISA_MASK                (3 << MIPS32_CONFIG3_ISA_SHIFT)
+
 #define MIPS32_ARCH_REL1 0x0
 #define MIPS32_ARCH_REL2 0x1
 
@@ -73,6 +76,14 @@ enum {
 enum mips32_isa_mode {
        MIPS32_ISA_MIPS32 = 0,
        MIPS32_ISA_MIPS16E = 1,
+       MIPS32_ISA_MMIPS32 = 3,
+};
+
+enum mips32_isa_imp {
+       MIPS32_ONLY = 0,
+       MMIPS32_ONLY = 1,
+       MIPS32_MIPS16 = 2,
+       MIPS32_MMIPS32 = 3,
 };
 
 struct mips32_comparator {
@@ -88,6 +99,7 @@ struct mips32_common {
        struct mips_ejtag ejtag_info;
        uint32_t core_regs[MIPS32NUMCOREREGS];
        enum mips32_isa_mode isa_mode;
+       enum mips32_isa_imp isa_imp;
 
        /* working area for fastdata access */
        struct working_area *fast_data_area;
@@ -406,6 +418,8 @@ int mips32_enable_interrupts(struct target *target, int enable);
 
 int mips32_examine(struct target *target);
 
+int mips32_read_config_regs(struct target *target);
+
 int mips32_register_commands(struct command_context *cmd_ctx);
 
 int mips32_get_gdb_reg_list(struct target *target,
index ade1b4c709efb13d4a302c9f43ecda0d14c7a380..226863ff56dcbfa64ddf5596da75936cded53b79 100644 (file)
@@ -183,6 +183,9 @@ struct mips_ejtag {
        uint32_t idcode;
        uint32_t ejtag_ctrl;
        int fast_access_save;
+       uint32_t config_regs;   /* number of config registers read */
+       uint32_t config[4];     /* cp0 config to config3 */
+
        uint32_t reg8;
        uint32_t reg9;
        unsigned scan_delay;
index 8b32d115a28069eb3808083576a1baeb03012cea..7ab30fe0ea983d7abc570e049b1b58fae8e5603b 100644 (file)
@@ -41,7 +41,7 @@ static int mips_m4k_set_breakpoint(struct target *target,
 static int mips_m4k_unset_breakpoint(struct target *target,
                struct breakpoint *breakpoint);
 static int mips_m4k_internal_restore(struct target *target, int current,
-               uint32_t address, int handle_breakpoints,
+               target_addr_t address, int handle_breakpoints,
                int debug_execution);
 static int mips_m4k_halt(struct target *target);
 static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
@@ -108,11 +108,14 @@ static int mips_m4k_debug_entry(struct target *target)
        /* attempt to find halt reason */
        mips_m4k_examine_debug_reason(target);
 
+       mips32_read_config_regs(target);
+
        /* default to mips32 isa, it will be changed below if required */
        mips32->isa_mode = MIPS32_ISA_MIPS32;
 
-       if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
-               mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1);
+       /* 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))
+               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),
@@ -431,7 +434,7 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
 }
 
 static int mips_m4k_internal_restore(struct target *target, int current,
-               uint32_t address, int handle_breakpoints, int debug_execution)
+               target_addr_t address, int handle_breakpoints, int debug_execution)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -451,12 +454,13 @@ 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 = 1;
                mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
        }
 
-       if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
+       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);
 
        if (!current)
@@ -544,6 +548,7 @@ 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 = 1;
                mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
index cf826612549960c6e646af90761aed1a6dcfcea9..ea09ae527ffc8d1892c0655e506c3987aa76902d 100644 (file)
@@ -41,6 +41,17 @@ target_to_m4k(struct target *target)
                        struct mips_m4k_common, mips32);
 }
 
+static inline void mips_m4k_isa_filter(enum mips32_isa_imp isa_imp, target_addr_t  *addr)
+{
+       if (isa_imp <= 1) {     /* if only one isa implemented */
+               target_addr_t address = (*addr & ~1) | isa_imp;
+
+               if (address != *addr) {
+                       LOG_USER("Warning: isa bit changed due to isa not implemented");
+                       *addr = address;
+               }
+       }
+}
 extern const struct command_registration mips_m4k_command_handlers[];
 
 #endif /* OPENOCD_TARGET_MIPS_M4K_H */