aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/target/mips32.c67
-rw-r--r--src/target/mips32.h14
-rw-r--r--src/target/mips_ejtag.h3
-rw-r--r--src/target/mips_m4k.c15
-rw-r--r--src/target/mips_m4k.h11
5 files changed, 91 insertions, 19 deletions
diff --git a/src/target/mips32.c b/src/target/mips32.c
index c5b7fbce..93fb4e64 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(&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);
diff --git a/src/target/mips32.h b/src/target/mips32.h
index d79451fb..928598f4 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 ade1b4c7..226863ff 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 8b32d115..7ab30fe0 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 <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;
diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h
index cf826612..ea09ae52 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 */