Merge pull request #236 from riscv/optimize

Small speed improvements.
riscv-compliance-dev
Tim Newsome 2018-05-07 15:15:14 -07:00 committed by GitHub
commit ddc64f45fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 69 additions and 25 deletions

View File

@ -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);