diff --git a/src/target/mips32.c b/src/target/mips32.c index c5b7fbce8..93fb4e646 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -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(®_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(®_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(®_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); diff --git a/src/target/mips32.h b/src/target/mips32.h index d79451fb7..928598f4c 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -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, diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index ade1b4c70..226863ff5 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -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; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 8b32d115a..7ab30fe0e 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -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
*/ 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 */ 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; diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h index cf8266125..ea09ae527 100644 --- a/src/target/mips_m4k.h +++ b/src/target/mips_m4k.h @@ -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 */