target/riscv: fix register cache flushing
Since writing a register can make some GPRs dirty (e.g. S0, S1), registers should be flushed in reverse order, so GPRs are flushed last. Change-Id: Ice352a4df4ae064619c0f9905db634a7b57e4711 Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
This commit is contained in:
parent
431deec8c9
commit
919a98a05b
|
@ -1495,6 +1495,15 @@ static int old_or_new_riscv_poll(struct target *target)
|
||||||
return riscv_openocd_poll(target);
|
return riscv_openocd_poll(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct reg *get_reg_cache_entry(struct target *target,
|
||||||
|
unsigned int number)
|
||||||
|
{
|
||||||
|
assert(target->reg_cache);
|
||||||
|
assert(target->reg_cache->reg_list);
|
||||||
|
assert(number < target->reg_cache->num_regs);
|
||||||
|
return &target->reg_cache->reg_list[number];
|
||||||
|
}
|
||||||
|
|
||||||
int riscv_flush_registers(struct target *target)
|
int riscv_flush_registers(struct target *target)
|
||||||
{
|
{
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
|
@ -1502,21 +1511,25 @@ int riscv_flush_registers(struct target *target)
|
||||||
if (!target->reg_cache)
|
if (!target->reg_cache)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
||||||
LOG_DEBUG("[%s]", target_name(target));
|
LOG_TARGET_DEBUG(target, "");
|
||||||
|
|
||||||
for (uint32_t number = 0; number < target->reg_cache->num_regs; number++) {
|
/* Writing non-GPR registers may require progbuf execution, and some GPRs
|
||||||
struct reg *reg = &target->reg_cache->reg_list[number];
|
* may become dirty in the process (e.g. S0, S1). For that reason, flush
|
||||||
|
* registers in reverse order, so that GPRs are flushed last.
|
||||||
|
*/
|
||||||
|
for (unsigned int number = target->reg_cache->num_regs; number-- > 0; ) {
|
||||||
|
struct reg *reg = get_reg_cache_entry(target, number);
|
||||||
if (reg->valid && reg->dirty) {
|
if (reg->valid && reg->dirty) {
|
||||||
uint64_t value = buf_get_u64(reg->value, 0, reg->size);
|
riscv_reg_t value = buf_get_u64(reg->value, 0, reg->size);
|
||||||
LOG_DEBUG("[%s] %s is dirty; write back 0x%" PRIx64,
|
|
||||||
target_name(target), reg->name, value);
|
LOG_TARGET_DEBUG(target, "%s is dirty; write back 0x%" PRIx64,
|
||||||
int result = r->set_register(target, number, value);
|
reg->name, value);
|
||||||
if (result != ERROR_OK)
|
if (r->set_register(target, number, value) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
reg->dirty = false;
|
reg->dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG_TARGET_DEBUG(target, "Flush of register cache completed");
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue