aboutsummaryrefslogtreecommitdiff
path: root/src/target/riscv/riscv_reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/riscv/riscv_reg.c')
-rw-r--r--src/target/riscv/riscv_reg.c112
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;