diff options
Diffstat (limited to 'src/target/riscv/riscv_reg.c')
-rw-r--r-- | src/target/riscv/riscv_reg.c | 112 |
1 files changed, 63 insertions, 49 deletions
diff --git a/src/target/riscv/riscv_reg.c b/src/target/riscv/riscv_reg.c index 6cf67dd..e35cd7f 100644 --- a/src/target/riscv/riscv_reg.c +++ b/src/target/riscv/riscv_reg.c @@ -56,7 +56,6 @@ static const char * const default_reg_names[GDB_REGNO_COUNT] = { [GDB_REGNO_T5] = "t5", [GDB_REGNO_T6] = "t6", [GDB_REGNO_PC] = "pc", - [GDB_REGNO_CSR0] = "csr0", [GDB_REGNO_PRIV] = "priv", [GDB_REGNO_FT0] = "ft0", [GDB_REGNO_FT1] = "ft1", @@ -196,7 +195,8 @@ const char *riscv_reg_gdb_regno_name(const struct target *target, enum gdb_regno } if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) { init_custom_csr_names(target); - info->reg_names[regno] = init_reg_name_with_prefix("csr", regno - GDB_REGNO_CSR0); + if (!info->reg_names[regno]) + info->reg_names[regno] = init_reg_name_with_prefix("csr", regno - GDB_REGNO_CSR0); return info->reg_names[regno]; } assert(!"Encountered uninitialized entry in reg_names table"); @@ -346,22 +346,11 @@ static bool vlenb_exists(const struct target *target) return riscv_vlenb(target) != 0; } -static bool mtopi_exists(const struct target *target) +static bool reg_exists(const struct target *target, uint32_t regno) { - RISCV_INFO(info) - /* TODO: The naming is quite unfortunate here. `mtopi_readable` refers - * to how the fact that `mtopi` exists was deduced during examine. - */ - return info->mtopi_readable; -} - -static bool mtopei_exists(const struct target *target) -{ - RISCV_INFO(info) - /* TODO: The naming is quite unfortunate here. `mtopei_readable` refers - * to how the fact that `mtopei` exists was deduced during examine. - */ - return info->mtopei_readable; + const struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); + assert(riscv_reg_impl_is_initialized(reg)); + return reg->exist; } static bool is_known_standard_csr(unsigned int csr_num) @@ -376,8 +365,19 @@ static bool is_known_standard_csr(unsigned int csr_num) return is_csr_in_buf[csr_num]; } -static bool gdb_regno_exist(const struct target *target, uint32_t regno) +bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno) { + switch (regno) { + case GDB_REGNO_VLENB: + case GDB_REGNO_MTOPI: + case GDB_REGNO_MTOPEI: + assert(false + && "Existence of other registers is determined " + "depending on existence of these ones, so " + "whether these register exist or not should be " + "set explicitly."); + }; + if (regno <= GDB_REGNO_XPR15 || regno == GDB_REGNO_PC || regno == GDB_REGNO_PRIV) @@ -403,7 +403,6 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_VL: case CSR_VCSR: case CSR_VTYPE: - case CSR_VLENB: return vlenb_exists(target); case CSR_SCOUNTEREN: case CSR_SSTATUS: @@ -498,25 +497,25 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_MVIP: case CSR_MIEH: case CSR_MIPH: - return mtopi_exists(target); + return reg_exists(target, GDB_REGNO_MTOPI); case CSR_MIDELEGH: case CSR_MVIENH: case CSR_MVIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'S'); /* Interrupts S-Mode CSRs. */ case CSR_SISELECT: case CSR_SIREG: case CSR_STOPI: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_supports_extension(target, 'S'); case CSR_STOPEI: - return mtopei_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPEI) && riscv_supports_extension(target, 'S'); case CSR_SIEH: case CSR_SIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'S'); /* Interrupts Hypervisor and VS CSRs. */ @@ -527,10 +526,10 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_VSISELECT: case CSR_VSIREG: case CSR_VSTOPI: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_supports_extension(target, 'H'); case CSR_VSTOPEI: - return mtopei_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPEI) && riscv_supports_extension(target, 'H'); case CSR_HIDELEGH: case CSR_HVIENH: @@ -539,7 +538,7 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_HVIPRIO2H: case CSR_VSIEH: case CSR_VSIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'H'); } @@ -599,14 +598,15 @@ static int resize_reg(const struct target *target, uint32_t regno, bool exist, return ERROR_OK; } -static int set_reg_exist(const struct target *target, uint32_t regno, bool exist) +int riscv_reg_impl_set_exist(const struct target *target, uint32_t regno, bool exist) { const struct reg *reg = riscv_reg_impl_cache_entry(target, regno); assert(riscv_reg_impl_is_initialized(reg)); return resize_reg(target, regno, exist, reg->size); } -int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct reg_arch_type *reg_type) +int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno, + bool exist, const struct reg_arch_type *reg_type) { struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); if (riscv_reg_impl_is_initialized(reg)) @@ -634,8 +634,7 @@ int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct reg_arch_info->target = target; reg_arch_info->custom_number = gdb_regno_custom_number(target, regno); } - return resize_reg(target, regno, gdb_regno_exist(target, regno), - gdb_regno_size(target, regno)); + return resize_reg(target, regno, exist, gdb_regno_size(target, regno)); } static int init_custom_register_names(struct list_head *expose_custom, @@ -725,7 +724,7 @@ int riscv_reg_impl_expose_csrs(const struct target *target) csr_number); continue; } - if (set_reg_exist(target, regno, /*exist*/ true) != ERROR_OK) + if (riscv_reg_impl_set_exist(target, regno, /*exist*/ true) != ERROR_OK) return ERROR_FAIL; LOG_TARGET_DEBUG(target, "Exposing additional CSR %d (name=%s)", csr_number, reg->name); @@ -746,7 +745,7 @@ void riscv_reg_impl_hide_csrs(const struct target *target) struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); const unsigned int csr_number = regno - GDB_REGNO_CSR0; if (!reg->exist) { - LOG_TARGET_WARNING(target, + LOG_TARGET_DEBUG(target, "Not hiding CSR %d: register does not exist.", csr_number); continue; @@ -834,15 +833,8 @@ static int riscv_set_or_write_register(struct target *target, return riscv_set_or_write_register(target, GDB_REGNO_DCSR, dcsr, write_through); } - if (!target->reg_cache) { - assert(!target_was_examined(target)); - LOG_TARGET_DEBUG(target, - "No cache, writing to target: %s <- 0x%" PRIx64, - riscv_reg_gdb_regno_name(target, regid), value); - return riscv013_set_register(target, regid, value); - } - struct reg *reg = riscv_reg_impl_cache_entry(target, regid); + assert(riscv_reg_impl_is_initialized(reg)); if (!reg->exist) { LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name); @@ -885,6 +877,34 @@ static int riscv_set_or_write_register(struct target *target, return ERROR_OK; } +bool riscv_reg_cache_any_dirty(const struct target *target, int log_level) +{ + bool any_dirty = false; + + if (!target->reg_cache) + return any_dirty; + + for (unsigned int number = 0; number < target->reg_cache->num_regs; ++number) { + const struct reg * const reg = riscv_reg_impl_cache_entry(target, number); + assert(riscv_reg_impl_is_initialized(reg)); + if (reg->dirty) { + log_printf_lf(log_level, __FILE__, __LINE__, __func__, + "[%s] Register %s is dirty!", target_name(target), reg->name); + any_dirty = true; + } + } + return any_dirty; +} + +void riscv_reg_cache_invalidate_all(struct target *target) +{ + if (!target->reg_cache) + return; + + LOG_TARGET_DEBUG(target, "Invalidating register cache."); + register_cache_invalidate(target->reg_cache); +} + /** * This function is used to change the value of a register. The new value may * be cached, and may not be written until the hart is resumed. @@ -935,21 +955,15 @@ int riscv_reg_get(struct target *target, riscv_reg_t *value, RISCV_INFO(r); assert(r); if (r->dtm_version == DTM_DTMCS_VERSION_0_11) - return riscv013_get_register(target, value, regid); + return riscv011_get_register(target, value, regid); keep_alive(); if (regid == GDB_REGNO_PC) return riscv_reg_get(target, value, GDB_REGNO_DPC); - if (!target->reg_cache) { - assert(!target_was_examined(target)); - LOG_TARGET_DEBUG(target, "No cache, reading %s from target", - riscv_reg_gdb_regno_name(target, regid)); - return riscv013_get_register(target, value, regid); - } - struct reg *reg = riscv_reg_impl_cache_entry(target, regid); + assert(riscv_reg_impl_is_initialized(reg)); if (!reg->exist) { LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name); return ERROR_FAIL; |