aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2018-05-07 15:15:14 -0700
committerGitHub <noreply@github.com>2018-05-07 15:15:14 -0700
commitddc64f45fb436844553356511a013cd2862cd48c (patch)
tree1765a939ecf56aae6966770ed30ef9e898b6a698
parent67b4e2c5223e79c934a2522b811a4708c9294d7a (diff)
parent909c9d4ab2e5ee5180ef81248608fa2109c3dba7 (diff)
downloadriscv-openocd-ddc64f45fb436844553356511a013cd2862cd48c.zip
riscv-openocd-ddc64f45fb436844553356511a013cd2862cd48c.tar.gz
riscv-openocd-ddc64f45fb436844553356511a013cd2862cd48c.tar.bz2
Merge pull request #236 from riscv/optimize
Small speed improvements.
-rw-r--r--src/target/riscv/riscv-013.c94
1 files changed, 69 insertions, 25 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index d9b52e4..f3fe76b 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -57,6 +57,7 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a,
static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a);
static int riscv013_dmi_write_u64_bits(struct target *target);
static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
+static int register_read(struct target *target, uint64_t *value, uint32_t number);
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number);
static int register_write_direct(struct target *target, unsigned number,
uint64_t value);
@@ -143,6 +144,8 @@ typedef struct {
bool was_reset;
/* Targets that are connected to this DM. */
struct list_head target_list;
+ /* The currently selected hartid on this DM. */
+ int current_hartid;
} dm013_info_t;
typedef struct {
@@ -242,6 +245,7 @@ static dm013_info_t *get_dm(struct target *target)
if (!dm) {
dm = calloc(1, sizeof(dm013_info_t));
dm->abs_chain_position = abs_chain_position;
+ dm->current_hartid = -1;
INIT_LIST_HEAD(&dm->target_list);
list_add(&dm->list, &dm_list);
}
@@ -678,17 +682,12 @@ static int execute_abstract_command(struct target *target, uint32_t command)
LOG_DEBUG("command=0x%x", command);
dmi_write(target, DMI_COMMAND, command);
- {
- uint32_t abstractcs = 0;
- wait_for_idle(target, &abstractcs);
- }
+ uint32_t abstractcs = 0;
+ wait_for_idle(target, &abstractcs);
- uint32_t cs;
- if (dmi_read(target, &cs, DMI_ABSTRACTCS) != ERROR_OK)
- return ERROR_FAIL;
- info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
+ info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
if (info->cmderr != 0) {
- LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
+ LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, abstractcs);
/* Clear the error. */
dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR,
info->cmderr));
@@ -859,7 +858,7 @@ static int examine_progbuf(struct target *target)
}
uint64_t s0;
- if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
struct riscv_program program;
@@ -1068,6 +1067,11 @@ static int register_write_direct(struct target *target, unsigned number,
int result = register_write_abstract(target, number, value,
register_size(target, number));
+ if (result == ERROR_OK && target->reg_cache) {
+ struct reg *reg = &target->reg_cache->reg_list[number];
+ buf_set_u64(reg->value, 0, reg->size, value);
+ reg->valid = true;
+ }
if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 ||
!riscv_is_halted(target))
return result;
@@ -1076,7 +1080,7 @@ static int register_write_direct(struct target *target, unsigned number,
riscv_program_init(&program, target);
uint64_t s0;
- if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
@@ -1116,6 +1120,11 @@ static int register_write_direct(struct target *target, unsigned number,
int exec_out = riscv_program_exec(&program, target);
/* Don't message on error. Probably the register doesn't exist. */
+ if (exec_out == ERROR_OK && target->reg_cache) {
+ struct reg *reg = &target->reg_cache->reg_list[number];
+ buf_set_u64(reg->value, 0, reg->size, value);
+ reg->valid = true;
+ }
/* Restore S0. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
@@ -1124,6 +1133,35 @@ static int register_write_direct(struct target *target, unsigned number,
return exec_out;
}
+/** Return the cached value, or read from the target if necessary. */
+static int register_read(struct target *target, uint64_t *value, uint32_t number)
+{
+ if (number == GDB_REGNO_ZERO) {
+ *value = 0;
+ return ERROR_OK;
+ }
+ if (target->reg_cache &&
+ (number <= GDB_REGNO_XPR31 ||
+ (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31))) {
+ /* Only check the cache for registers that we know won't spontaneously
+ * change. */
+ struct reg *reg = &target->reg_cache->reg_list[number];
+ if (reg && reg->valid) {
+ *value = buf_get_u64(reg->value, 0, reg->size);
+ return ERROR_OK;
+ }
+ }
+ int result = register_read_direct(target, value, number);
+ if (result != ERROR_OK)
+ return ERROR_FAIL;
+ if (target->reg_cache) {
+ struct reg *reg = &target->reg_cache->reg_list[number];
+ buf_set_u64(reg->value, 0, reg->size, *value);
+ reg->valid = true;
+ }
+ return ERROR_OK;
+}
+
/** Actually read registers from the target right now. */
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
{
@@ -1143,14 +1181,14 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
bool use_scratch = false;
uint64_t s0;
- if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
/* Write program to move data into s0. */
uint64_t mstatus;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
- if (register_read_direct(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
+ if (register_read(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
return ERROR_FAIL;
if ((mstatus & MSTATUS_FS) == 0)
if (register_write_direct(target, GDB_REGNO_MSTATUS,
@@ -1393,7 +1431,7 @@ static int examine(struct target *target)
else
r->xlen[i] = 32;
- if (register_read_direct(target, &r->misa[i], GDB_REGNO_MISA)) {
+ if (register_read(target, &r->misa[i], GDB_REGNO_MISA)) {
LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i);
return ERROR_FAIL;
}
@@ -1972,9 +2010,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
* s1 holds the next data value to write
*/
uint64_t s0, s1;
- if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
- if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
+ if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
if (execute_fence(target) != ERROR_OK)
@@ -2406,9 +2444,9 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
int result = ERROR_OK;
uint64_t s0, s1;
- if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
+ if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL;
- if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
+ if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL;
/* Write the program (store, increment) */
@@ -2632,14 +2670,14 @@ static int riscv013_get_register(struct target *target,
int result = ERROR_OK;
if (rid == GDB_REGNO_PC) {
- result = register_read_direct(target, value, GDB_REGNO_DPC);
+ result = register_read(target, value, GDB_REGNO_DPC);
LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value);
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
- result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ result = register_read(target, &dcsr, GDB_REGNO_DCSR);
*value = get_field(dcsr, CSR_DCSR_PRV);
} else {
- result = register_read_direct(target, value, rid);
+ result = register_read(target, value, rid);
if (result != ERROR_OK)
*value = -1;
}
@@ -2669,7 +2707,7 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64
}
} else if (rid == GDB_REGNO_PRIV) {
uint64_t dcsr;
- register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ register_read(target, &dcsr, GDB_REGNO_DCSR);
dcsr = set_field(dcsr, CSR_DCSR_PRV, value);
return register_write_direct(target, GDB_REGNO_DCSR, dcsr);
} else {
@@ -2683,11 +2721,17 @@ static int riscv013_select_current_hart(struct target *target)
{
RISCV_INFO(r);
+ dm013_info_t *dm = get_dm(target);
+ if (r->current_hartid == dm->current_hartid)
+ return ERROR_OK;
+
uint32_t dmcontrol;
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
return ERROR_FAIL;
dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
- return dmi_write(target, DMI_DMCONTROL, dmcontrol);
+ int result = dmi_write(target, DMI_DMCONTROL, dmcontrol);
+ dm->current_hartid = r->current_hartid;
+ return result;
}
static int riscv013_halt_current_hart(struct target *target)
@@ -2782,7 +2826,7 @@ static bool riscv013_is_halted(struct target *target)
static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
{
riscv_reg_t dcsr;
- int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ int result = register_read(target, &dcsr, GDB_REGNO_DCSR);
if (result != ERROR_OK)
return RISCV_HALT_UNKNOWN;
@@ -2881,7 +2925,7 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
/* We want to twiddle some bits in the debug CSR so debugging works. */
riscv_reg_t dcsr;
- int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
+ int result = register_read(target, &dcsr, GDB_REGNO_DCSR);
if (result != ERROR_OK)
return result;
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);