aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2023-12-21 09:23:11 -0800
committerGitHub <noreply@github.com>2023-12-21 09:23:11 -0800
commit62758f20871f2de7df4a62aff7e987acb92b4d58 (patch)
tree3a8b4ba00c816048a7489688aa558dca41804b7e /src/target
parentfeff8e005482ce3a070131e62a14b3bc0b9fbdf9 (diff)
parent1f512eac32e614e893565741f93ea3739a522797 (diff)
downloadriscv-openocd-62758f20871f2de7df4a62aff7e987acb92b4d58.zip
riscv-openocd-62758f20871f2de7df4a62aff7e987acb92b4d58.tar.gz
riscv-openocd-62758f20871f2de7df4a62aff7e987acb92b4d58.tar.bz2
Merge pull request #976 from riscv/from_upstream
Merge up to d4575b647a3603200a9bb4a784d170f792ab88d0 from upstream
Diffstat (limited to 'src/target')
-rw-r--r--src/target/arc.c16
-rw-r--r--src/target/arm.h11
-rw-r--r--src/target/arm_dpm.c48
-rw-r--r--src/target/arm_dpm.h13
-rw-r--r--src/target/arm_opcodes.h22
-rw-r--r--src/target/armv4_5.c122
-rw-r--r--src/target/armv8_dpm.c11
-rw-r--r--src/target/breakpoints.c104
-rw-r--r--src/target/breakpoints.h1
-rw-r--r--src/target/cortex_a.c47
-rw-r--r--src/target/cortex_m.c5
-rw-r--r--src/target/cortex_m.h27
-rw-r--r--src/target/etm.c4
-rw-r--r--src/target/image.c38
-rw-r--r--src/target/mips32.c392
-rw-r--r--src/target/mips32.h386
-rw-r--r--src/target/mips32_pracc.c196
-rw-r--r--src/target/mips32_pracc.h6
-rw-r--r--src/target/mips64.c16
-rw-r--r--src/target/mips_ejtag.h11
-rw-r--r--src/target/mips_m4k.c22
-rw-r--r--src/target/mips_mips64.c8
-rw-r--r--src/target/target.c65
23 files changed, 1289 insertions, 282 deletions
diff --git a/src/target/arc.c b/src/target/arc.c
index 2ca6be1..0f7b110 100644
--- a/src/target/arc.c
+++ b/src/target/arc.c
@@ -1265,8 +1265,8 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
/* current = 1: continue on current PC, otherwise continue at <address> */
if (!current) {
target_buffer_set_u32(target, pc->value, address);
- pc->dirty = 1;
- pc->valid = 1;
+ pc->dirty = true;
+ pc->valid = true;
LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address);
}
@@ -1281,7 +1281,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
resume_pc, pc->dirty, pc->valid);
/* check if GDB tells to set our PC where to continue from */
- if ((pc->valid == 1) && (resume_pc == target_buffer_get_u32(target, pc->value))) {
+ if (pc->valid && resume_pc == target_buffer_get_u32(target, pc->value)) {
value = target_buffer_get_u32(target, pc->value);
LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, value);
CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value));
@@ -1573,9 +1573,6 @@ static int arc_set_breakpoint(struct target *target,
return ERROR_FAIL;
}
- /* core instruction cache is now invalid. */
- CHECK_RETVAL(arc_cache_invalidate(target));
-
return ERROR_OK;
}
@@ -1658,9 +1655,6 @@ static int arc_unset_breakpoint(struct target *target,
return ERROR_FAIL;
}
- /* core instruction cache is now invalid. */
- CHECK_RETVAL(arc_cache_invalidate(target));
-
return retval;
}
@@ -2013,8 +2007,8 @@ static int arc_step(struct target *target, int current, target_addr_t address,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
buf_set_u32(pc->value, 0, 32, address);
- pc->dirty = 1;
- pc->valid = 1;
+ pc->dirty = true;
+ pc->valid = true;
}
LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32,
diff --git a/src/target/arm.h b/src/target/arm.h
index 28e5330..d5053af 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -61,6 +61,7 @@ enum arm_arch {
/** Known ARM implementor IDs */
enum arm_implementor {
ARM_IMPLEMENTOR_ARM = 0x41,
+ ARM_IMPLEMENTOR_INFINEON = 0x49,
ARM_IMPLEMENTOR_REALTEK = 0x72,
};
@@ -230,12 +231,22 @@ struct arm {
uint32_t crn, uint32_t crm,
uint32_t *value);
+ /** Read coprocessor to two registers. */
+ int (*mrrc)(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm,
+ uint64_t *value);
+
/** Write coprocessor register. */
int (*mcr)(struct target *target, int cpnum,
uint32_t op1, uint32_t op2,
uint32_t crn, uint32_t crm,
uint32_t value);
+ /** Write coprocessor from two registers. */
+ int (*mcrr)(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm,
+ uint64_t value);
+
void *arch_info;
/** For targets conforming to ARM Debug Interface v5,
diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c
index ab9b50e..9f3a444 100644
--- a/src/target/arm_dpm.c
+++ b/src/target/arm_dpm.c
@@ -63,6 +63,29 @@ static int dpm_mrc(struct target *target, int cpnum,
return retval;
}
+static int dpm_mrrc(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm, uint64_t *value)
+{
+ struct arm *arm = target_to_arm(target);
+ struct arm_dpm *dpm = arm->dpm;
+ int retval;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("MRRC p%d, %d, r0, r1, c%d", cpnum,
+ (int)op, (int)crm);
+
+ /* read coprocessor register into R0, R1; return via DCC */
+ retval = dpm->instr_read_data_r0_r1(dpm,
+ ARMV5_T_MRRC(cpnum, op, 0, 1, crm),
+ value);
+
+ /* (void) */ dpm->finish(dpm);
+ return retval;
+}
+
static int dpm_mcr(struct target *target, int cpnum,
uint32_t op1, uint32_t op2, uint32_t crn, uint32_t crm,
uint32_t value)
@@ -88,6 +111,29 @@ static int dpm_mcr(struct target *target, int cpnum,
return retval;
}
+static int dpm_mcrr(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm, uint64_t value)
+{
+ struct arm *arm = target_to_arm(target);
+ struct arm_dpm *dpm = arm->dpm;
+ int retval;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("MCRR p%d, %d, r0, r1, c%d", cpnum,
+ (int)op, (int)crm);
+
+ /* read DCC into r0, r1; then write coprocessor register from R0, R1 */
+ retval = dpm->instr_write_data_r0_r1(dpm,
+ ARMV5_T_MCRR(cpnum, op, 0, 1, crm), value);
+
+ /* (void) */ dpm->finish(dpm);
+
+ return retval;
+}
+
/*----------------------------------------------------------------------*/
/*
@@ -1070,6 +1116,8 @@ int arm_dpm_setup(struct arm_dpm *dpm)
/* coprocessor access setup */
arm->mrc = dpm_mrc;
arm->mcr = dpm_mcr;
+ arm->mrrc = dpm_mrrc;
+ arm->mcrr = dpm_mcrr;
/* breakpoint setup -- optional until it works everywhere */
if (!target->type->add_breakpoint) {
diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h
index d35e9f6..2da4631 100644
--- a/src/target/arm_dpm.h
+++ b/src/target/arm_dpm.h
@@ -72,6 +72,12 @@ struct arm_dpm {
int (*instr_write_data_r0)(struct arm_dpm *dpm,
uint32_t opcode, uint32_t data);
+ /**
+ * Runs two instructions, writing data to R0 and R1 before execution.
+ */
+ int (*instr_write_data_r0_r1)(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t data);
+
/** Runs one instruction, writing data to R0 before execution. */
int (*instr_write_data_r0_64)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t data);
@@ -92,6 +98,13 @@ struct arm_dpm {
int (*instr_read_data_r0)(struct arm_dpm *dpm,
uint32_t opcode, uint32_t *data);
+ /**
+ * Runs two instructions, reading data from r0 and r1 after
+ * execution.
+ */
+ int (*instr_read_data_r0_r1)(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t *data);
+
int (*instr_read_data_r0_64)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t *data);
diff --git a/src/target/arm_opcodes.h b/src/target/arm_opcodes.h
index c182f41..c8ce51f 100644
--- a/src/target/arm_opcodes.h
+++ b/src/target/arm_opcodes.h
@@ -187,6 +187,17 @@
(0xee100010 | (crm) | ((op2) << 5) | ((cp) << 8) \
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
+/* Move to two ARM registers from coprocessor
+ * cp: Coprocessor number
+ * op: Coprocessor opcode
+ * rt: destination register 1
+ * rt2: destination register 2
+ * crm: coprocessor source register
+ */
+#define ARMV5_T_MRRC(cp, op, rt, rt2, crm) \
+ (0xec500000 | (crm) | ((op) << 4) | ((cp) << 8) \
+ | ((rt) << 12) | ((rt2) << 16))
+
/* Move to coprocessor from ARM register
* cp: Coprocessor number
* op1: Coprocessor opcode
@@ -199,6 +210,17 @@
(0xee000010 | (crm) | ((op2) << 5) | ((cp) << 8) \
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
+/* Move to coprocessor from two ARM registers
+ * cp: Coprocessor number
+ * op: Coprocessor opcode
+ * rt: destination register 1
+ * rt2: destination register 2
+ * crm: coprocessor source register
+ */
+#define ARMV5_T_MCRR(cp, op, rt, rt2, crm) \
+ (0xec400000 | (crm) | ((op) << 4) | ((cp) << 8) \
+ | ((rt) << 12) | ((rt2) << 16))
+
/* Breakpoint instruction (ARMv5)
* im: 16-bit immediate
*/
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index 8e3f224..7debb94 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -1093,6 +1093,94 @@ COMMAND_HANDLER(handle_armv4_5_mcrmrc)
return ERROR_OK;
}
+COMMAND_HANDLER(handle_armv4_5_mcrrmrrc)
+{
+ bool is_mcrr = false;
+ unsigned int arg_cnt = 3;
+
+ if (!strcmp(CMD_NAME, "mcrr")) {
+ is_mcrr = true;
+ arg_cnt = 4;
+ }
+
+ if (arg_cnt != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+ command_print(CMD, "no current target");
+ return ERROR_FAIL;
+ }
+ if (!target_was_examined(target)) {
+ command_print(CMD, "%s: not yet examined", target_name(target));
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
+ struct arm *arm = target_to_arm(target);
+ if (!is_arm(arm)) {
+ command_print(CMD, "%s: not an ARM", target_name(target));
+ return ERROR_FAIL;
+ }
+
+ if (target->state != TARGET_HALTED)
+ return ERROR_TARGET_NOT_HALTED;
+
+ int cpnum;
+ uint32_t op1;
+ uint32_t crm;
+ uint64_t value;
+
+ /* NOTE: parameter sequence matches ARM instruction set usage:
+ * MCRR pNUM, op1, rX1, rX2, CRm ; write CP from rX1 and rX2
+ * MREC pNUM, op1, rX1, rX2, CRm ; read CP into rX1 and rX2
+ * The "rXn" are necessarily omitted; they use Tcl mechanisms.
+ */
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
+ if (cpnum & ~0xf) {
+ command_print(CMD, "coprocessor %d out of range", cpnum);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
+ if (op1 & ~0xf) {
+ command_print(CMD, "op1 %d out of range", op1);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crm);
+ if (crm & ~0xf) {
+ command_print(CMD, "CRm %d out of range", crm);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ /*
+ * FIXME change the call syntax here ... simplest to just pass
+ * the MRC() or MCR() instruction to be executed. That will also
+ * let us support the "mrrc2" and "mcrr2" opcodes (toggling one bit)
+ * if that's ever needed.
+ */
+ if (is_mcrr) {
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], value);
+
+ /* NOTE: parameters reordered! */
+ /* ARMV5_T_MCRR(cpnum, op1, crm) */
+ int retval = arm->mcrr(target, cpnum, op1, crm, value);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ value = 0;
+ /* NOTE: parameters reordered! */
+ /* ARMV5_T_MRRC(cpnum, op1, crm) */
+ int retval = arm->mrrc(target, cpnum, op1, crm, &value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ command_print(CMD, "0x%" PRIx64, value);
+ }
+
+ return ERROR_OK;
+}
+
static const struct command_registration arm_exec_command_handlers[] = {
{
.name = "reg",
@@ -1116,6 +1204,20 @@ static const struct command_registration arm_exec_command_handlers[] = {
.usage = "cpnum op1 CRn CRm op2",
},
{
+ .name = "mcrr",
+ .mode = COMMAND_EXEC,
+ .handler = handle_armv4_5_mcrrmrrc,
+ .help = "write coprocessor 64-bit register",
+ .usage = "cpnum op1 CRm value",
+ },
+ {
+ .name = "mrrc",
+ .mode = COMMAND_EXEC,
+ .handler = handle_armv4_5_mcrrmrrc,
+ .help = "read coprocessor 64-bit register",
+ .usage = "cpnum op1 CRm",
+ },
+ {
.chain = arm_all_profiles_command_handlers,
},
COMMAND_REGISTRATION_DONE
@@ -1669,6 +1771,14 @@ static int arm_default_mrc(struct target *target, int cpnum,
return ERROR_FAIL;
}
+static int arm_default_mrrc(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm,
+ uint64_t *value)
+{
+ LOG_ERROR("%s doesn't implement MRRC", target_type_name(target));
+ return ERROR_FAIL;
+}
+
static int arm_default_mcr(struct target *target, int cpnum,
uint32_t op1, uint32_t op2,
uint32_t crn, uint32_t crm,
@@ -1678,6 +1788,14 @@ static int arm_default_mcr(struct target *target, int cpnum,
return ERROR_FAIL;
}
+static int arm_default_mcrr(struct target *target, int cpnum,
+ uint32_t op, uint32_t crm,
+ uint64_t value)
+{
+ LOG_ERROR("%s doesn't implement MCRR", target_type_name(target));
+ return ERROR_FAIL;
+}
+
int arm_init_arch_info(struct target *target, struct arm *arm)
{
target->arch_info = arm;
@@ -1697,8 +1815,12 @@ int arm_init_arch_info(struct target *target, struct arm *arm)
if (!arm->mrc)
arm->mrc = arm_default_mrc;
+ if (!arm->mrrc)
+ arm->mrrc = arm_default_mrrc;
if (!arm->mcr)
arm->mcr = arm_default_mcr;
+ if (!arm->mcrr)
+ arm->mcrr = arm_default_mcrr;
return ERROR_OK;
}
diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c
index 9ba6b54..552bcfa 100644
--- a/src/target/armv8_dpm.c
+++ b/src/target/armv8_dpm.c
@@ -725,7 +725,8 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
}
/**
- * Read basic registers of the current context: R0 to R15, and CPSR;
+ * Read basic registers of the current context: R0 to R15, and CPSR in AArch32
+ * state or R0 to R31, PC and CPSR in AArch64 state;
* sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
* In normal operation this is called on entry to halting debug state,
* possibly after some other operations supporting restore of debug state
@@ -772,9 +773,15 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
/* update core mode and state */
armv8_set_cpsr(arm, cpsr);
- for (unsigned int i = ARMV8_PC; i < cache->num_regs ; i++) {
+ /* read the remaining registers that would be required by GDB 'g' packet */
+ for (unsigned int i = ARMV8_R2; i <= ARMV8_PC ; i++) {
struct arm_reg *arm_reg;
+ /* in AArch32 skip AArch64 registers */
+ /* TODO: this should be detected below through arm_reg->mode */
+ if (arm->core_state != ARM_STATE_AARCH64 && i > ARMV8_R14 && i < ARMV8_PC)
+ continue;
+
r = armv8_reg_current(arm, i);
if (!r->exist || r->valid)
continue;
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index 7d2a9da..d069c6b 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -18,6 +18,11 @@
#include "rtos/rtos.h"
#include "smp.h"
+enum breakpoint_watchpoint {
+ BREAKPOINT,
+ WATCHPOINT,
+};
+
static const char * const breakpoint_type_strings[] = {
"hardware",
"software"
@@ -418,26 +423,90 @@ int breakpoint_remove(struct target *target, target_addr_t address)
return retval;
}
-int breakpoint_remove_all(struct target *target)
+static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
{
+ struct watchpoint *watchpoint = target->watchpoints;
+ struct watchpoint **watchpoint_p = &target->watchpoints;
+ int retval;
+
+ while (watchpoint) {
+ if (watchpoint == watchpoint_to_remove)
+ break;
+ watchpoint_p = &watchpoint->next;
+ watchpoint = watchpoint->next;
+ }
+
+ if (!watchpoint)
+ return ERROR_WATCHPOINT_NOT_FOUND;
+ retval = target_remove_watchpoint(target, watchpoint);
+ if (retval != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
+ watchpoint->number);
+ return retval;
+ }
+
+ LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
+ (*watchpoint_p) = watchpoint->next;
+ free(watchpoint);
+
+ return ERROR_OK;
+}
+
+static int watchpoint_remove_all_internal(struct target *target)
+{
+ struct watchpoint *watchpoint = target->watchpoints;
+ int retval = ERROR_OK;
+
+ while (watchpoint) {
+ struct watchpoint *tmp = watchpoint;
+ watchpoint = watchpoint->next;
+ int status = watchpoint_free(target, tmp);
+ if (status != ERROR_OK)
+ retval = status;
+ }
+
+ return retval;
+}
+
+static int breakpoint_watchpoint_remove_all(struct target *target, enum breakpoint_watchpoint bp_wp)
+{
+ assert(bp_wp == BREAKPOINT || bp_wp == WATCHPOINT);
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
- int status = breakpoint_remove_all_internal(curr);
+
+ int status = ERROR_OK;
+ if (bp_wp == BREAKPOINT)
+ status = breakpoint_remove_all_internal(curr);
+ else
+ status = watchpoint_remove_all_internal(curr);
if (status != ERROR_OK)
retval = status;
}
} else {
- retval = breakpoint_remove_all_internal(target);
+ if (bp_wp == BREAKPOINT)
+ retval = breakpoint_remove_all_internal(target);
+ else
+ retval = watchpoint_remove_all_internal(target);
}
return retval;
}
+int breakpoint_remove_all(struct target *target)
+{
+ return breakpoint_watchpoint_remove_all(target, BREAKPOINT);
+}
+
+int watchpoint_remove_all(struct target *target)
+{
+ return breakpoint_watchpoint_remove_all(target, WATCHPOINT);
+}
+
int breakpoint_clear_target(struct target *target)
{
int retval = ERROR_OK;
@@ -562,35 +631,6 @@ int watchpoint_add(struct target *target, target_addr_t address,
}
}
-static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
-{
- struct watchpoint *watchpoint = target->watchpoints;
- struct watchpoint **watchpoint_p = &target->watchpoints;
- int retval;
-
- while (watchpoint) {
- if (watchpoint == watchpoint_to_remove)
- break;
- watchpoint_p = &watchpoint->next;
- watchpoint = watchpoint->next;
- }
-
- if (!watchpoint)
- return ERROR_WATCHPOINT_NOT_FOUND;
- retval = target_remove_watchpoint(target, watchpoint);
- if (retval != ERROR_OK) {
- LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
- watchpoint->number);
- return retval;
- }
-
- LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
- (*watchpoint_p) = watchpoint->next;
- free(watchpoint);
-
- return ERROR_OK;
-}
-
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
{
struct watchpoint *watchpoint = target->watchpoints;
diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h
index 950283e..0ec65de 100644
--- a/src/target/breakpoints.h
+++ b/src/target/breakpoints.h
@@ -73,6 +73,7 @@ int watchpoint_add(struct target *target,
target_addr_t address, uint32_t length,
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
int watchpoint_remove(struct target *target, target_addr_t address);
+int watchpoint_remove_all(struct target *target);
/* report type and address of just hit watchpoint */
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index abfd6ac..ba3349d 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -471,6 +471,28 @@ static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
return retval;
}
+static int cortex_a_instr_write_data_r0_r1(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t data)
+{
+ struct cortex_a_common *a = dpm_to_a(dpm);
+ uint32_t dscr = DSCR_INSTR_COMP;
+ int retval;
+
+ retval = cortex_a_instr_write_data_rt_dcc(dpm, 0, data & 0xffffffffULL);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = cortex_a_instr_write_data_rt_dcc(dpm, 1, data >> 32);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* then the opcode, taking data from R0, R1 */
+ retval = cortex_a_exec_opcode(a->armv7a_common.arm.target,
+ opcode,
+ &dscr);
+ return retval;
+}
+
static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm)
{
struct target *target = dpm->arm->target;
@@ -539,6 +561,29 @@ static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
}
+static int cortex_a_instr_read_data_r0_r1(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t *data)
+{
+ uint32_t lo, hi;
+ int retval;
+
+ /* the opcode, writing data to RO, R1 */
+ retval = cortex_a_instr_read_data_r0(dpm, opcode, &lo);
+ if (retval != ERROR_OK)
+ return retval;
+
+ *data = lo;
+
+ /* write R1 to DCC */
+ retval = cortex_a_instr_read_data_rt_dcc(dpm, 1, &hi);
+ if (retval != ERROR_OK)
+ return retval;
+
+ *data |= (uint64_t)hi << 32;
+
+ return retval;
+}
+
static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
uint32_t addr, uint32_t control)
{
@@ -612,10 +657,12 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
dpm->instr_write_data_dcc = cortex_a_instr_write_data_dcc;
dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0;
+ dpm->instr_write_data_r0_r1 = cortex_a_instr_write_data_r0_r1;
dpm->instr_cpsr_sync = cortex_a_instr_cpsr_sync;
dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc;
dpm->instr_read_data_r0 = cortex_a_instr_read_data_r0;
+ dpm->instr_read_data_r0_r1 = cortex_a_instr_read_data_r0_r1;
dpm->bpwp_enable = cortex_a_bpwp_enable;
dpm->bpwp_disable = cortex_a_bpwp_disable;
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 854e8eb..3eafee0 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -112,6 +112,11 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
.flags = CORTEX_M_F_HAS_FPV5,
},
{
+ .impl_part = INFINEON_SLX2_PARTNO,
+ .name = "Infineon-SLx2",
+ .arch = ARM_ARCH_V8M,
+ },
+ {
.impl_part = REALTEK_M200_PARTNO,
.name = "Real-M200 (KM0)",
.arch = ARM_ARCH_V8M,
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index 065e4d4..0bc1399 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -45,19 +45,20 @@
*/
enum cortex_m_impl_part {
CORTEX_M_PARTNO_INVALID,
- STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
- CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
- CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
- CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
- CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
- CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
- CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
- CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
- CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
- CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
- CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
- REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
- REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
+ STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
+ CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
+ CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
+ CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
+ CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
+ CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
+ CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
+ CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
+ CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
+ CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
+ CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
+ INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0),
+ REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
+ REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
};
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
diff --git a/src/target/etm.c b/src/target/etm.c
index 6718875..d083017 100644
--- a/src/target/etm.c
+++ b/src/target/etm.c
@@ -552,8 +552,8 @@ static int etm_set_reg(struct reg *reg, uint32_t value)
}
buf_set_u32(reg->value, 0, reg->size, value);
- reg->valid = 1;
- reg->dirty = 0;
+ reg->valid = true;
+ reg->dirty = false;
return ERROR_OK;
}
diff --git a/src/target/image.c b/src/target/image.c
index ad2d856..9175c20 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -96,20 +96,22 @@ static int autodetect_image_type(struct image *image, const char *url)
static int identify_image_type(struct image *image, const char *type_string, const char *url)
{
if (type_string) {
- if (!strcmp(type_string, "bin"))
+ if (!strcmp(type_string, "bin")) {
image->type = IMAGE_BINARY;
- else if (!strcmp(type_string, "ihex"))
+ } else if (!strcmp(type_string, "ihex")) {
image->type = IMAGE_IHEX;
- else if (!strcmp(type_string, "elf"))
+ } else if (!strcmp(type_string, "elf")) {
image->type = IMAGE_ELF;
- else if (!strcmp(type_string, "mem"))
+ } else if (!strcmp(type_string, "mem")) {
image->type = IMAGE_MEMORY;
- else if (!strcmp(type_string, "s19"))
+ } else if (!strcmp(type_string, "s19")) {
image->type = IMAGE_SRECORD;
- else if (!strcmp(type_string, "build"))
+ } else if (!strcmp(type_string, "build")) {
image->type = IMAGE_BUILDER;
- else
+ } else {
+ LOG_ERROR("Unknown image type: %s, use one of: bin, ihex, elf, mem, s19, build", type_string);
return ERROR_IMAGE_TYPE_UNKNOWN;
+ }
} else
return autodetect_image_type(image, url);
@@ -966,12 +968,13 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
- return retval;
+ goto free_mem_on_error;
+
size_t filesize;
retval = fileio_size(image_binary->fileio, &filesize);
if (retval != ERROR_OK) {
fileio_close(image_binary->fileio);
- return retval;
+ goto free_mem_on_error;
}
image->num_sections = 1;
@@ -986,14 +989,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
- return retval;
+ goto free_mem_on_error;
retval = image_ihex_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering IHEX image, check server output for additional information");
fileio_close(image_ihex->fileio);
- return retval;
+ goto free_mem_on_error;
}
} else if (image->type == IMAGE_ELF) {
struct image_elf *image_elf;
@@ -1002,12 +1005,12 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
- return retval;
+ goto free_mem_on_error;
retval = image_elf_read_headers(image);
if (retval != ERROR_OK) {
fileio_close(image_elf->fileio);
- return retval;
+ goto free_mem_on_error;
}
} else if (image->type == IMAGE_MEMORY) {
struct target *target = get_target(url);
@@ -1037,14 +1040,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
- return retval;
+ goto free_mem_on_error;
retval = image_mot_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering S19 image, check server output for additional information");
fileio_close(image_mot->fileio);
- return retval;
+ goto free_mem_on_error;
}
} else if (image->type == IMAGE_BUILDER) {
image->num_sections = 0;
@@ -1065,6 +1068,11 @@ int image_open(struct image *image, const char *url, const char *type_string)
}
return retval;
+
+free_mem_on_error:
+ free(image->type_private);
+ image->type_private = NULL;
+ return retval;
};
int image_read_section(struct image *image,
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 4e6d251..5c346c4 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,13 @@ 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);
+ int retval = mips32_pracc_read_regs(mips32);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Could not read core registers from target");
+ return retval;
+ }
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (!mips32->core_cache->reg_list[i].valid)
@@ -265,7 +326,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 +333,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 +345,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 +382,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 +461,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;
@@ -751,15 +805,82 @@ int mips32_cpu_probe(struct target *target)
return ERROR_OK;
}
+/* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/
+void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
+{
+ uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT);
+ if (dsp_present) {
+ mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1;
+ LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp);
+ } else {
+ LOG_USER("DSP implemented: %s", "no");
+ }
+}
+
+/* read fpu implementation info from CP0 Config1 register {CU1, FP}*/
+int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
+{
+ int retval;
+ uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT;
+ char buf[60] = {0};
+ if (!fp_imp) {
+ LOG_USER("FPU implemented: %s", "no");
+ mips32->fp_imp = MIPS32_FP_IMP_NONE;
+ return ERROR_OK;
+ }
+ uint32_t status_value;
+ bool status_fr, status_cu1;
+
+ retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read cp0 status register");
+ return retval;
+ }
+
+ status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1;
+ status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1;
+ if (status_cu1) {
+ /* TODO: read fpu(cp1) config register for current operating mode.
+ * Now its set to 32 bits by default. */
+ snprintf(buf, sizeof(buf), "yes");
+ fp_imp = MIPS32_FP_IMP_32;
+ } else {
+ snprintf(buf, sizeof(buf), "yes, disabled");
+ fp_imp = MIPS32_FP_IMP_UNKNOWN;
+ }
+
+ mips32->fpu_in_64bit = status_fr;
+ mips32->fpu_enabled = status_cu1;
+
+ LOG_USER("FPU implemented: %s", buf);
+ mips32->fp_imp = fp_imp;
+
+ return ERROR_OK;
+}
+
+/* Checks if current target implements Common Device Memory Map and therefore Fast Debug Channel (MD00090) */
+void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr)
+{
+ if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) {
+ mips32->fdc = 1;
+ mips32->semihosting = 1;
+ } else {
+ mips32->fdc = 0;
+ mips32->semihosting = 0;
+ }
+}
+
/* 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;
+ char buf[60] = {0};
+ int retval;
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);
+ 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;
@@ -774,27 +895,56 @@ int mips32_read_config_regs(struct target *target)
LOG_DEBUG("read %"PRIu32" config registers", ejtag_info->config_regs);
+ mips32->isa_rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
+ snprintf(buf, sizeof(buf), ", release %s(AR=%d)",
+ mips32->isa_rel == MIPS32_RELEASE_1 ? "1"
+ : mips32->isa_rel == MIPS32_RELEASE_2 ? "2"
+ : mips32->isa_rel == MIPS32_RELEASE_6 ? "6"
+ : "unknown", mips32->isa_rel);
+
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
mips32->isa_imp = MIPS32_MIPS16;
- LOG_USER("MIPS32 with MIPS16 support implemented");
-
+ LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf);
} 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");
+ LOG_USER("ISA implemented: %s%s", "microMIPS32", buf);
} else if (isa_imp != 0) {
mips32->isa_imp = MIPS32_MMIPS32;
- LOG_USER("MIPS32 and MICRO MIPS32 implemented");
+ LOG_USER("ISA implemented: %s%s", "MIPS32, microMIPS32", buf);
}
+ } else if (mips32->isa_imp == MIPS32_ONLY) {
+ /* initial default value */
+ LOG_USER("ISA implemented: %s%s", "MIPS32", buf);
+ }
+
+ /* Retrieve DSP info */
+ mips32_read_config_dsp(mips32, ejtag_info);
+
+ /* Retrieve if Float Point CoProcessor Implemented */
+ retval = mips32_read_config_fpu(mips32, ejtag_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("fpu info is not available, error while reading cp0 status");
+ mips32->fp_imp = MIPS32_FP_IMP_NONE;
+ return retval;
}
- if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
- LOG_USER("MIPS32 only implemented");
+ uint32_t dcr;
+
+ retval = target_read_u32(target, EJTAG_DCR, &dcr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("failed to read EJTAG_DCR register");
+ return retval;
+ }
+
+ /* Determine if FDC and CDMM are implemented for this core */
+ mips32_read_config_fdc(mips32, ejtag_info, dcr);
return ERROR_OK;
}
+
int mips32_checksum_memory(struct target *target, target_addr_t address,
uint32_t count, uint32_t *checksum)
{
diff --git a/src/target/mips32.h b/src/target/mips32.h
index 3d03e98..d072eb9 100644
--- a/src/target/mips32.h
+++ b/src/target/mips32.h
@@ -46,9 +46,21 @@
#define MIPS32_CONFIG0_AR_SHIFT 10
#define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT)
+#define MIPS32_CONFIG1_FP_SHIFT 0
+#define MIPS32_CONFIG1_FP_MASK BIT(MIPS32_CONFIG1_FP_SHIFT)
+
#define MIPS32_CONFIG1_DL_SHIFT 10
#define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
+#define MIPS32_CONFIG3_CDMM_SHIFT 3
+#define MIPS32_CONFIG3_CDMM_MASK BIT(MIPS32_CONFIG3_CDMM_SHIFT)
+
+#define MIPS32_CONFIG3_DSPP_SHIFT 10
+#define MIPS32_CONFIG3_DSPP_MASK BIT(MIPS32_CONFIG3_DSPP_SHIFT)
+
+#define MIPS32_CONFIG3_DSPREV_SHIFT 11
+#define MIPS32_CONFIG3_DSPREV_MASK BIT(MIPS32_CONFIG3_DSPREV_SHIFT)
+
#define MIPS32_CONFIG3_ISA_SHIFT 14
#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT)
@@ -57,6 +69,141 @@
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
+#define MIPS32_NUM_DSPREGS 9
+
+/* 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 +214,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,
@@ -80,21 +251,67 @@ enum mips32_isa_imp {
MIPS32_MMIPS32 = 3,
};
+/* Release 2~5 does not have much change regarding to the ISA under User mode,
+* therefore no new Architecture Revision(AR) level is assigned to them.
+* Release 6 changed some instruction's encoding/mnemonic, removed instructions that
+* has lost its purposes/none are using, and added some new instructions as well.
+*/
+enum mips32_isa_rel {
+ MIPS32_RELEASE_1 = 0,
+ MIPS32_RELEASE_2 = 1,
+ MIPS32_RELEASE_6 = 2,
+ MIPS32_RELEASE_UNKNOWN,
+};
+
+enum mips32_fp_imp {
+ MIPS32_FP_IMP_NONE = 0,
+ MIPS32_FP_IMP_32 = 1,
+ MIPS32_FP_IMP_64 = 2,
+ MIPS32_FP_IMP_UNKNOWN = 3,
+};
+
+enum mips32_dsp_imp {
+ MIPS32_DSP_IMP_NONE = 0,
+ MIPS32_DSP_IMP_REV1 = 1,
+ MIPS32_DSP_IMP_REV2 = 2,
+};
+
struct mips32_comparator {
int used;
uint32_t bp_value;
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;
+ enum mips32_isa_rel isa_rel;
+ enum mips32_fp_imp fp_imp;
+ enum mips32_dsp_imp dsp_imp;
+
+ int fdc;
+ int semihosting;
+ uint32_t cp0_mask;
+
+ /* FPU enabled (cp0.status.cu1) */
+ bool fpu_enabled;
+ /* FPU mode (cp0.status.fr) */
+ bool fpu_in_64bit;
/* processor identification register */
uint32_t prid;
@@ -394,6 +611,173 @@ struct mips32_algorithm {
#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP)
+/*
+ * MIPS32 Config1 Register (CP0 Register 16, Select 1)
+ */
+#define MIPS32_CFG1_M 0x80000000 /* Config2 implemented */
+#define MIPS32_CFG1_MMUSMASK 0x7e000000 /* mmu size - 1 */
+#define MIPS32_CFG1_MMUSSHIFT 25
+#define MIPS32_CFG1_ISMASK 0x01c00000 /* icache lines 64<<n */
+#define MIPS32_CFG1_ISSHIFT 22
+#define MIPS32_CFG1_ILMASK 0x00380000 /* icache line size 2<<n */
+#define MIPS32_CFG1_ILSHIFT 19
+#define MIPS32_CFG1_IAMASK 0x00070000 /* icache ways - 1 */
+#define MIPS32_CFG1_IASHIFT 16
+#define MIPS32_CFG1_DSMASK 0x0000e000 /* dcache lines 64<<n */
+#define MIPS32_CFG1_DSSHIFT 13
+#define MIPS32_CFG1_DLMASK 0x00001c00 /* dcache line size 2<<n */
+#define MIPS32_CFG1_DLSHIFT 10
+#define MIPS32_CFG1_DAMASK 0x00000380 /* dcache ways - 1 */
+#define MIPS32_CFG1_DASHIFT 7
+#define MIPS32_CFG1_C2 0x00000040 /* Coprocessor 2 present */
+#define MIPS32_CFG1_MD 0x00000020 /* MDMX implemented */
+#define MIPS32_CFG1_PC 0x00000010 /* performance counters implemented */
+#define MIPS32_CFG1_WR 0x00000008 /* watch registers implemented */
+#define MIPS32_CFG1_CA 0x00000004 /* compression (mips16) implemented */
+#define MIPS32_CFG1_EP 0x00000002 /* ejtag implemented */
+#define MIPS32_CFG1_FP 0x00000001 /* fpu implemented */
+
+/*
+ * MIPS32 Coprocessor 0 register numbers
+ */
+#define MIPS32_C0_INDEX 0
+#define MIPS32_C0_INX 0
+#define MIPS32_C0_RANDOM 1
+#define MIPS32_C0_RAND 1
+#define MIPS32_C0_ENTRYLO0 2
+#define MIPS32_C0_TLBLO0 2
+#define MIPS32_C0_ENTRYLO1 3
+#define MIPS32_C0_TLBLO1 3
+#define MIPS32_C0_CONTEXT 4
+#define MIPS32_C0_CTXT 4
+#define MIPS32_C0_PAGEMASK 5
+#define MIPS32_C0_PAGEGRAIN (5, 1)
+#define MIPS32_C0_WIRED 6
+#define MIPS32_C0_HWRENA 7
+#define MIPS32_C0_BADVADDR 8
+#define MIPS32_C0_VADDR 8
+#define MIPS32_C0_COUNT 9
+#define MIPS32_C0_ENTRYHI 10
+#define MIPS32_C0_TLBHI 10
+#define MIPS32_C0_GUESTCTL1 10
+#define MIPS32_C0_COMPARE 11
+#define MIPS32_C0_STATUS 12
+#define MIPS32_C0_SR 12
+#define MIPS32_C0_INTCTL (12, 1)
+#define MIPS32_C0_SRSCTL (12, 2)
+#define MIPS32_C0_SRSMAP (12, 3)
+#define MIPS32_C0_CAUSE 13
+#define MIPS32_C0_CR 13
+#define MIPS32_C0_EPC 14
+#define MIPS32_C0_PRID 15
+#define MIPS32_C0_EBASE (15, 1)
+#define MIPS32_C0_CONFIG 16
+#define MIPS32_C0_CONFIG0 (16, 0)
+#define MIPS32_C0_CONFIG1 (16, 1)
+#define MIPS32_C0_CONFIG2 (16, 2)
+#define MIPS32_C0_CONFIG3 (16, 3)
+#define MIPS32_C0_LLADDR 17
+#define MIPS32_C0_WATCHLO 18
+#define MIPS32_C0_WATCHHI 19
+#define MIPS32_C0_DEBUG 23
+#define MIPS32_C0_DEPC 24
+#define MIPS32_C0_PERFCNT 25
+#define MIPS32_C0_ERRCTL 26
+#define MIPS32_C0_CACHEERR 27
+#define MIPS32_C0_TAGLO 28
+#define MIPS32_C0_ITAGLO 28
+#define MIPS32_C0_DTAGLO (28, 2)
+#define MIPS32_C0_TAGLO2 (28, 4)
+#define MIPS32_C0_DATALO (28, 1)
+#define MIPS32_C0_IDATALO (28, 1)
+#define MIPS32_C0_DDATALO (28, 3)
+#define MIPS32_C0_DATALO2 (28, 5)
+#define MIPS32_C0_TAGHI 29
+#define MIPS32_C0_ITAGHI 29
+#define MIPS32_C0_DATAHI (29, 1)
+#define MIPS32_C0_ERRPC 30
+#define MIPS32_C0_DESAVE 31
+
+/*
+ * MIPS32 MMU types
+ */
+#define MIPS32_MMU_TLB 1
+#define MIPS32_MMU_BAT 2
+#define MIPS32_MMU_FIXED 3
+#define MIPS32_MMU_DUAL_VTLB_FTLB 4
+
+enum mips32_cpu_vendor {
+ MIPS32_CPU_VENDOR_MTI,
+ MIPS32_CPU_VENDOR_ALCHEMY,
+ MIPS32_CPU_VENDOR_BROADCOM,
+ MIPS32_CPU_VENDOR_ALTERA,
+ MIPS32_CPU_VENDOR_LEXRA,
+};
+
+enum mips32_isa_supported {
+ MIPS16,
+ MIPS32,
+ MIPS64,
+ MICROMIPS_ONLY,
+ MIPS32_AT_RESET_AND_MICROMIPS,
+ MICROMIPS_AT_RESET_AND_MIPS32,
+};
+
+struct mips32_cpu_features {
+ /* Type of CPU (4Kc, 24Kf, etc.) */
+ uint32_t cpu_core;
+
+ /* Internal representation of cpu type */
+ uint32_t cpu_type;
+
+ /* Processor vendor */
+ enum mips32_cpu_vendor vendor;
+
+ /* Supported ISA and boot config */
+ enum mips32_isa_supported isa;
+
+ /* PRID */
+ uint32_t prid;
+
+ /* Processor implemented the MultiThreading ASE */
+ bool mtase;
+
+ /* Processor implemented the DSP ASE */
+ bool dspase;
+
+ /* Processor implemented the SmartMIPS ASE */
+ bool smase;
+
+ /* Processor implemented the MIPS16[e] ASE */
+ bool m16ase;
+
+ /* Processor implemented the microMIPS ASE */
+ bool micromipsase;
+
+ /* Processor implemented the Virtualization ASE */
+ uint32_t vzase;
+
+ uint32_t vz_guest_id_width;
+
+ /* ebase.cpuid number */
+ uint32_t cpuid;
+
+ uint32_t inst_cache_size;
+ uint32_t data_cache_size;
+ uint32_t mmu_type;
+ uint32_t tlb_entries;
+ uint32_t num_shadow_regs;
+
+ /* Processor implemented the MSA module */
+ bool msa;
+
+ /* Processor implemented mfhc0 and mthc0 instructions */
+ bool mvh;
+
+ bool guest_ctl1_present;
+ bool cdmm;
+};
+
extern const struct command_registration mips32_command_handlers[];
int mips32_arch_state(struct target *target);
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/mips64.c b/src/target/mips64.c
index 37f3685..48f4563 100644
--- a/src/target/mips64.c
+++ b/src/target/mips64.c
@@ -247,8 +247,8 @@ static int mips64_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_TARGET_NOT_HALTED;
buf_set_u64(reg->value, 0, 64, value);
- reg->dirty = 1;
- reg->valid = 1;
+ reg->dirty = true;
+ reg->valid = true;
return ERROR_OK;
}
@@ -265,8 +265,8 @@ static int mips64_read_core_reg(struct target *target, int num)
reg_value = mips64->core_regs[num];
buf_set_u64(mips64->core_cache->reg_list[num].value, 0, 64, reg_value);
- mips64->core_cache->reg_list[num].valid = 1;
- mips64->core_cache->reg_list[num].dirty = 0;
+ mips64->core_cache->reg_list[num].valid = true;
+ mips64->core_cache->reg_list[num].dirty = false;
return ERROR_OK;
}
@@ -284,8 +284,8 @@ static int mips64_write_core_reg(struct target *target, int num)
reg_value = buf_get_u64(mips64->core_cache->reg_list[num].value, 0, 64);
mips64->core_regs[num] = reg_value;
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
- mips64->core_cache->reg_list[num].valid = 1;
- mips64->core_cache->reg_list[num].dirty = 0;
+ mips64->core_cache->reg_list[num].valid = true;
+ mips64->core_cache->reg_list[num].dirty = false;
return ERROR_OK;
}
@@ -297,8 +297,8 @@ int mips64_invalidate_core_regs(struct target *target)
unsigned int i;
for (i = 0; i < mips64->core_cache->num_regs; i++) {
- mips64->core_cache->reg_list[i].valid = 0;
- mips64->core_cache->reg_list[i].dirty = 0;
+ mips64->core_cache->reg_list[i].valid = false;
+ mips64->core_cache->reg_list[i].dirty = false;
}
return ERROR_OK;
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);
}
diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c
index bf60953..9921e93 100644
--- a/src/target/mips_mips64.c
+++ b/src/target/mips_mips64.c
@@ -625,8 +625,8 @@ static int mips_mips64_resume(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
buf_set_u64(pc->value, 0, 64, address);
- pc->dirty = 1;
- pc->valid = 1;
+ pc->dirty = true;
+ pc->valid = true;
}
resume_pc = buf_get_u64(pc->value, 0, 64);
@@ -717,8 +717,8 @@ static int mips_mips64_step(struct target *target, int current,
* <address> */
if (!current) {
buf_set_u64(pc->value, 0, 64, address);
- pc->dirty = 1;
- pc->valid = 1;
+ pc->dirty = true;
+ pc->valid = true;
}
/* the front-end may request us not to handle breakpoints */
diff --git a/src/target/target.c b/src/target/target.c
index 167b1ea..cfd0641 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -3053,6 +3053,10 @@ COMMAND_HANDLER(handle_reg_command)
LOG_DEBUG("-");
struct target *target = get_current_target(CMD_CTX);
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
struct reg *reg = NULL;
/* list all available registers for the current target */
@@ -3117,7 +3121,7 @@ COMMAND_HANDLER(handle_reg_command)
if (!reg) {
command_print(CMD, "%i is out of bounds, the current target "
"has only %i registers (0 - %i)", num, count, count - 1);
- return ERROR_OK;
+ return ERROR_FAIL;
}
} else {
/* access a single register by its name */
@@ -3136,9 +3140,9 @@ COMMAND_HANDLER(handle_reg_command)
if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
&& (CMD_ARGV[1][0] <= '9')))) {
if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
- reg->valid = 0;
+ reg->valid = false;
- if (reg->valid == 0) {
+ if (!reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read register '%s'", reg->name);
@@ -3176,7 +3180,7 @@ COMMAND_HANDLER(handle_reg_command)
not_found:
command_print(CMD, "register %s not found in current target", CMD_ARGV[0]);
- return ERROR_OK;
+ return ERROR_FAIL;
}
COMMAND_HANDLER(handle_poll_command)
@@ -4071,13 +4075,14 @@ COMMAND_HANDLER(handle_wp_command)
struct watchpoint *watchpoint = target->watchpoints;
while (watchpoint) {
+ char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a'));
command_print(CMD, "address: " TARGET_ADDR_FMT
", len: 0x%8.8" PRIx32
- ", r/w/a: %i, value: 0x%8.8" PRIx64
+ ", r/w/a: %c, value: 0x%8.8" PRIx64
", mask: 0x%8.8" PRIx64,
watchpoint->address,
watchpoint->length,
- (int)watchpoint->rw,
+ wp_type,
watchpoint->value,
watchpoint->mask);
watchpoint = watchpoint->next;
@@ -4138,17 +4143,28 @@ COMMAND_HANDLER(handle_wp_command)
COMMAND_HANDLER(handle_rwp_command)
{
+ int retval;
+
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- target_addr_t addr;
- COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
-
struct target *target = get_current_target(CMD_CTX);
- int retval = watchpoint_remove(target, addr);
+ if (!strcmp(CMD_ARGV[0], "all")) {
+ retval = watchpoint_remove_all(target);
- if (retval != ERROR_OK)
- command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "Error encountered during removal of all watchpoints.");
+ command_print(CMD, "Some watchpoints may have remained set.");
+ }
+ } else {
+ target_addr_t addr;
+ COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
+
+ retval = watchpoint_remove(target, addr);
+
+ if (retval != ERROR_OK)
+ command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
+ }
return retval;
}
@@ -5135,7 +5151,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc,
return JIM_ERR;
}
- if (force) {
+ if (force || !reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {
@@ -5860,6 +5876,18 @@ COMMAND_HANDLER(handle_target_current_state)
return ERROR_OK;
}
+COMMAND_HANDLER(handle_target_debug_reason)
+{
+ if (CMD_ARGC != 0)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct target *target = get_current_target(CMD_CTX);
+
+ command_print(CMD, "%s", debug_reason_name(target));
+
+ return ERROR_OK;
+}
+
static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct jim_getopt_info goi;
@@ -6012,6 +6040,13 @@ static const struct command_registration target_instance_command_handlers[] = {
.usage = "",
},
{
+ .name = "debug_reason",
+ .mode = COMMAND_EXEC,
+ .handler = handle_target_debug_reason,
+ .help = "displays the debug reason of this target",
+ .usage = "",
+ },
+ {
.name = "arp_examine",
.mode = COMMAND_EXEC,
.handler = handle_target_examine,
@@ -6110,7 +6145,7 @@ static int target_create(struct jim_getopt_info *goi)
if (e != JIM_OK)
return e;
struct transport *tr = get_current_transport();
- if (tr->override_target) {
+ if (tr && tr->override_target) {
e = tr->override_target(&cp);
if (e != ERROR_OK) {
LOG_ERROR("The selected transport doesn't support this target");
@@ -7067,7 +7102,7 @@ static const struct command_registration target_exec_command_handlers[] = {
.handler = handle_rwp_command,
.mode = COMMAND_EXEC,
.help = "remove watchpoint",
- .usage = "address",
+ .usage = "'all' | address",
},
{
.name = "load_image",