aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Naydanov <109669442+en-sc@users.noreply.github.com>2024-08-16 17:04:24 +0300
committerGitHub <noreply@github.com>2024-08-16 17:04:24 +0300
commite4d6885eb5a627869d925d8f900bae4f881b46a7 (patch)
tree0bbd024ac06f1bd87d4484e3941976a217de0bab /src
parent9a23c9e67978f77d9166102cefc7b537b714b561 (diff)
parent5f45b5bd73566028ee36c146803232b3dce77c52 (diff)
downloadriscv-openocd-e4d6885eb5a627869d925d8f900bae4f881b46a7.zip
riscv-openocd-e4d6885eb5a627869d925d8f900bae4f881b46a7.tar.gz
riscv-openocd-e4d6885eb5a627869d925d8f900bae4f881b46a7.tar.bz2
Merge pull request #1101 from en-sc/en-sc/ref-reg-examine
target/riscv: reg cache entry is initialized before access
Diffstat (limited to 'src')
-rw-r--r--src/target/riscv/riscv-011_reg.c4
-rw-r--r--src/target/riscv/riscv-013.c99
-rw-r--r--src/target/riscv/riscv-013.h4
-rw-r--r--src/target/riscv/riscv-013_reg.c186
-rw-r--r--src/target/riscv/riscv-013_reg.h7
-rw-r--r--src/target/riscv/riscv_reg.c45
-rw-r--r--src/target/riscv/riscv_reg_impl.h16
7 files changed, 239 insertions, 122 deletions
diff --git a/src/target/riscv/riscv-011_reg.c b/src/target/riscv/riscv-011_reg.c
index 7f29064..44ea1a4 100644
--- a/src/target/riscv/riscv-011_reg.c
+++ b/src/target/riscv/riscv-011_reg.c
@@ -38,7 +38,9 @@ static const struct reg_arch_type *riscv011_gdb_regno_reg_type(uint32_t regno)
static int riscv011_init_reg(struct target *target, uint32_t regno)
{
- return riscv_reg_impl_init_one(target, regno, riscv011_gdb_regno_reg_type(regno));
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ riscv_reg_impl_gdb_regno_exist(target, regno),
+ riscv011_gdb_regno_reg_type(regno));
}
int riscv011_reg_init_all(struct target *target)
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index ae36a06..63b13b8 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -727,7 +727,7 @@ clear_cmderr:
return res;
}
-static int execute_abstract_command(struct target *target, uint32_t command,
+int riscv013_execute_abstract_command(struct target *target, uint32_t command,
uint32_t *cmderr)
{
assert(cmderr);
@@ -863,7 +863,7 @@ static int write_abstract_arg(struct target *target, unsigned index,
/**
* @par size in bits
*/
-static uint32_t access_register_command(struct target *target, uint32_t number,
+uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
unsigned size, uint32_t flags)
{
uint32_t command = set_field(0, DM_COMMAND_CMDTYPE, 0);
@@ -920,11 +920,11 @@ static int register_read_abstract_with_size(struct target *target,
if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31)
return ERROR_FAIL;
- uint32_t command = access_register_command(target, number, size,
+ uint32_t command = riscv013_access_register_command(target, number, size,
AC_ACCESS_REGISTER_TRANSFER);
uint32_t cmderr;
- int result = execute_abstract_command(target, command, &cmderr);
+ int result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result != ERROR_OK) {
if (cmderr == CMDERR_NOT_SUPPORTED) {
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
@@ -969,7 +969,7 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
return ERROR_FAIL;
const unsigned int size_bits = register_size(target, number);
- const uint32_t command = access_register_command(target, number, size_bits,
+ const uint32_t command = riscv013_access_register_command(target, number, size_bits,
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
LOG_DEBUG_REG(target, AC_ACCESS_REGISTER, command);
@@ -2112,70 +2112,9 @@ static int examine(struct target *target)
* program buffer. */
r->progbuf_size = info->progbufsize;
- result = register_read_abstract_with_size(target, NULL, GDB_REGNO_S0, 64);
- if (result == ERROR_OK)
- r->xlen = 64;
- else
- r->xlen = 32;
-
- /* Save s0 and s1. The register cache hasn't be initialized yet so we
- * need to take care of this manually. */
- uint64_t s0, s1;
- if (register_read_abstract(target, &s0, GDB_REGNO_S0) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read s0.");
- return ERROR_FAIL;
- }
- if (register_read_abstract(target, &s1, GDB_REGNO_S1) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read s1.");
- return ERROR_FAIL;
- }
-
- if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read MISA.");
- return ERROR_FAIL;
- }
-
- uint64_t value;
- if (register_read_direct(target, &value, GDB_REGNO_VLENB) != ERROR_OK) {
- if (riscv_supports_extension(target, 'V'))
- LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
- r->vlenb = 0;
- } else {
- r->vlenb = value;
- LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb);
- }
-
- if (register_read_direct(target, &value, GDB_REGNO_MTOPI) == ERROR_OK) {
- r->mtopi_readable = true;
-
- if (register_read_direct(target, &value, GDB_REGNO_MTOPEI) == ERROR_OK) {
- LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
- r->mtopei_readable = true;
- } else {
- r->mtopei_readable = false;
- LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
- }
- } else {
- r->mtopi_readable = false;
- }
-
- /* Display this as early as possible to help people who are using
- * really slow simulators. */
- LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa);
-
- /* Restore s0 and s1. */
- if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to write back s0.");
- return ERROR_FAIL;
- }
- if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to write back s1.");
- return ERROR_FAIL;
- }
-
- /* Now init registers based on what we discovered. */
- if (riscv013_reg_init_all(target) != ERROR_OK)
- return ERROR_FAIL;
+ result = riscv013_reg_examine_all(target);
+ if (result != ERROR_OK)
+ return result;
if (set_dcsr_ebreak(target, false) != ERROR_OK)
return ERROR_FAIL;
@@ -3651,7 +3590,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
/* Execute the command */
uint32_t cmderr;
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -3673,7 +3612,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, false);
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
@@ -3744,7 +3683,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
/* Execute the command */
uint32_t cmderr;
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -3766,7 +3705,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, true);
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
@@ -3812,11 +3751,11 @@ static int read_memory_progbuf_inner_startup(struct target *target,
/* AC_ACCESS_REGISTER_POSTEXEC is used to trigger first stage of the
* pipeline (memory -> s1) whenever this command is executed.
*/
- const uint32_t startup_command = access_register_command(target,
+ const uint32_t startup_command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
- if (execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -4299,11 +4238,11 @@ static int read_memory_progbuf_inner_one(struct target *target,
if (write_abstract_arg(target, 0, access.target_address, riscv_xlen(target))
!= ERROR_OK)
return ERROR_FAIL;
- uint32_t command = access_register_command(target, GDB_REGNO_S1,
+ uint32_t command = riscv013_access_register_command(target, GDB_REGNO_S1,
riscv_xlen(target), AC_ACCESS_REGISTER_WRITE |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
- if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
return read_word_from_s1(target, access, 0);
@@ -4642,14 +4581,14 @@ static int write_memory_progbuf_startup(struct target *target, target_addr_t *ad
/* Write and execute command that moves the value from data0 [, data1]
* into S1 and executes program buffer. */
- uint32_t command = access_register_command(target,
+ uint32_t command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_POSTEXEC |
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
uint32_t cmderr;
- if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
log_memory_access64(*address_p, value, size, /*is_read*/ false);
@@ -5320,7 +5259,7 @@ static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr)
run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0);
run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000);
- return execute_abstract_command(target, run_program, cmderr);
+ return riscv013_execute_abstract_command(target, run_program, cmderr);
}
static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d)
diff --git a/src/target/riscv/riscv-013.h b/src/target/riscv/riscv-013.h
index f39393c..ca2d4ae 100644
--- a/src/target/riscv/riscv-013.h
+++ b/src/target/riscv/riscv-013.h
@@ -19,5 +19,9 @@ int riscv013_set_register(struct target *target, enum gdb_regno rid,
riscv_reg_t value);
int riscv013_set_register_buf(struct target *target, enum gdb_regno regno,
const uint8_t *value);
+uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
+ unsigned int size, uint32_t flags);
+int riscv013_execute_abstract_command(struct target *target, uint32_t command,
+ uint32_t *cmderr);
#endif /* OPENOCD_TARGET_RISCV_RISCV_013_H */
diff --git a/src/target/riscv/riscv-013_reg.c b/src/target/riscv/riscv-013_reg.c
index a71a01c..ad1130d 100644
--- a/src/target/riscv/riscv-013_reg.c
+++ b/src/target/riscv/riscv-013_reg.c
@@ -9,6 +9,7 @@
#include "riscv_reg.h"
#include "riscv_reg_impl.h"
#include "riscv-013.h"
+#include "debug_defines.h"
#include <helper/time_support.h>
static int riscv013_reg_get(struct reg *reg)
@@ -85,33 +86,196 @@ static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
static const struct reg_arch_type *riscv013_gdb_regno_reg_type(uint32_t regno)
{
- static const struct reg_arch_type riscv011_reg_type = {
+ static const struct reg_arch_type riscv013_reg_type = {
.get = riscv013_reg_get,
.set = riscv013_reg_set
};
- return &riscv011_reg_type;
+ return &riscv013_reg_type;
}
-static int riscv013_init_reg(struct target *target, uint32_t regno)
+static int init_cache_entry(struct target *target, uint32_t regno)
{
- return riscv_reg_impl_init_one(target, regno, riscv013_gdb_regno_reg_type(regno));
+ struct reg * const reg = riscv_reg_impl_cache_entry(target, regno);
+ if (riscv_reg_impl_is_initialized(reg))
+ return ERROR_OK;
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ riscv_reg_impl_gdb_regno_exist(target, regno),
+ riscv013_gdb_regno_reg_type(regno));
+}
+
+/**
+ * Some registers are optional (e.g. "misa"). For such registers it is first
+ * assumed they exist (via "assume_reg_exist()"), then the read is attempted
+ * (via the usual "riscv_reg_get()") and if the read fails, the register is
+ * marked as non-existing (via "riscv_reg_impl_set_exist()").
+ */
+static int assume_reg_exist(struct target *target, uint32_t regno)
+{
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ /* exist */ true, riscv013_gdb_regno_reg_type(regno));
}
-int riscv013_reg_init_all(struct target *target)
+static int examine_xlen(struct target *target)
{
- if (riscv_reg_impl_init_cache(target) != ERROR_OK)
+ RISCV_INFO(r);
+ unsigned int cmderr;
+
+ const uint32_t command = riscv013_access_register_command(target,
+ GDB_REGNO_S0, /* size */ 64, AC_ACCESS_REGISTER_TRANSFER);
+ int res = riscv013_execute_abstract_command(target, command, &cmderr);
+ if (res == ERROR_OK) {
+ r->xlen = 64;
+ return ERROR_OK;
+ }
+ if (res == ERROR_TIMEOUT_REACHED)
return ERROR_FAIL;
+ r->xlen = 32;
+
+ return ERROR_OK;
+}
+
+static int examine_vlenb(struct target *target)
+{
+ RISCV_INFO(r);
+
+ /* Reading "vlenb" requires "mstatus.vs" to be set, so "mstatus" should
+ * be accessible.*/
+ int res = init_cache_entry(target, GDB_REGNO_MSTATUS);
+ if (res != ERROR_OK)
+ return res;
+
+ res = assume_reg_exist(target, GDB_REGNO_VLENB);
+ if (res != ERROR_OK)
+ return res;
+
+ riscv_reg_t vlenb_val;
+ if (riscv_reg_get(target, &vlenb_val, GDB_REGNO_VLENB) != ERROR_OK) {
+ if (riscv_supports_extension(target, 'V'))
+ LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
+ r->vlenb = 0;
+ return riscv_reg_impl_set_exist(target, GDB_REGNO_VLENB, false);
+ }
+ /* As defined by RISC-V V extension specification:
+ * https://github.com/riscv/riscv-v-spec/blob/2f68ef7256d6ec53e4d2bd7cb12862f406d64e34/v-spec.adoc?plain=1#L67-L72 */
+ const unsigned int vlen_max = 65536;
+ const unsigned int vlenb_max = vlen_max / 8;
+ if (vlenb_val > vlenb_max) {
+ LOG_TARGET_WARNING(target, "'vlenb == %" PRIu64
+ "' is greater than maximum allowed by specification (%u); vector register access won't work.",
+ vlenb_val, vlenb_max);
+ r->vlenb = 0;
+ return ERROR_OK;
+ }
+ assert(vlenb_max <= UINT_MAX);
+ r->vlenb = (unsigned int)vlenb_val;
+
+ LOG_TARGET_INFO(target, "Vector support with vlenb=%u", r->vlenb);
+ return ERROR_OK;
+}
+
+static int examine_misa(struct target *target)
+{
+ RISCV_INFO(r);
+
+ int res = init_cache_entry(target, GDB_REGNO_MISA);
+ if (res != ERROR_OK)
+ return res;
+
+ res = riscv_reg_get(target, &r->misa, GDB_REGNO_MISA);
+ if (res != ERROR_OK)
+ return res;
+
+ return ERROR_OK;
+}
+
+static int examine_mtopi(struct target *target)
+{
+ RISCV_INFO(r);
+
+ /* Assume the registers exist */
+ r->mtopi_readable = true;
+ r->mtopei_readable = true;
+
+ int res = assume_reg_exist(target, GDB_REGNO_MTOPI);
+ if (res != ERROR_OK)
+ return res;
+ res = assume_reg_exist(target, GDB_REGNO_MTOPEI);
+ if (res != ERROR_OK)
+ return res;
+
+ riscv_reg_t value;
+ if (riscv_reg_get(target, &value, GDB_REGNO_MTOPI) != ERROR_OK) {
+ r->mtopi_readable = false;
+ r->mtopei_readable = false;
+ } else if (riscv_reg_get(target, &value, GDB_REGNO_MTOPEI) != ERROR_OK) {
+ LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
+ r->mtopei_readable = false;
+ } else {
+ LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
+ }
+ res = riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPI, r->mtopi_readable);
+ if (res != ERROR_OK)
+ return res;
+
+ return riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPEI, r->mtopei_readable);
+}
+
+/**
+ * This function assumes target's DM to be initialized (target is able to
+ * access DMs registers, execute program buffer, etc.)
+ */
+int riscv013_reg_examine_all(struct target *target)
+{
+ RISCV_INFO(r);
+
+ int res = riscv_reg_impl_init_cache(target);
+ if (res != ERROR_OK)
+ return res;
init_shared_reg_info(target);
+ assert(target->state == TARGET_HALTED);
+
+ res = examine_xlen(target);
+ if (res != ERROR_OK)
+ return res;
+
+ /* Reading CSRs may clobber "s0", "s1", so it should be possible to
+ * save them in cache. */
+ res = init_cache_entry(target, GDB_REGNO_S0);
+ if (res != ERROR_OK)
+ return res;
+ res = init_cache_entry(target, GDB_REGNO_S1);
+ if (res != ERROR_OK)
+ return res;
+
+ res = examine_misa(target);
+ if (res != ERROR_OK)
+ return res;
+
+ /* Display this as early as possible to help people who are using
+ * really slow simulators. */
+ LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), r->misa);
+
+ res = examine_vlenb(target);
+ if (res != ERROR_OK)
+ return res;
+
riscv_reg_impl_init_vector_reg_type(target);
- for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno)
- if (riscv013_init_reg(target, regno) != ERROR_OK)
- return ERROR_FAIL;
+ res = examine_mtopi(target);
+ if (res != ERROR_OK)
+ return res;
- if (riscv_reg_impl_expose_csrs(target) != ERROR_OK)
- return ERROR_FAIL;
+ for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) {
+ res = init_cache_entry(target, regno);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ res = riscv_reg_impl_expose_csrs(target);
+ if (res != ERROR_OK)
+ return res;
riscv_reg_impl_hide_csrs(target);
diff --git a/src/target/riscv/riscv-013_reg.h b/src/target/riscv/riscv-013_reg.h
index e7a9447..e542a35 100644
--- a/src/target/riscv/riscv-013_reg.h
+++ b/src/target/riscv/riscv-013_reg.h
@@ -13,10 +13,11 @@
*/
/**
- * Init initialize register cache. After this function all registers can be
- * safely accessed via functions described here and in `riscv_reg.h`.
+ * This function assumes target is halted.
+ * After this function all registers can be safely accessed via functions
+ * described here and in `riscv_reg.h`.
*/
-int riscv013_reg_init_all(struct target *target);
+int riscv013_reg_examine_all(struct target *target);
/**
* This function is used to save the value of a register in cache. The register
diff --git a/src/target/riscv/riscv_reg.c b/src/target/riscv/riscv_reg.c
index 6cf67dd..eefd402 100644
--- a/src/target/riscv/riscv_reg.c
+++ b/src/target/riscv/riscv_reg.c
@@ -376,8 +376,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 +414,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:
@@ -599,14 +609,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 +645,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 +735,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);
@@ -834,15 +844,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);
@@ -935,21 +938,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;
diff --git a/src/target/riscv/riscv_reg_impl.h b/src/target/riscv/riscv_reg_impl.h
index 906a5b6..7a483ad 100644
--- a/src/target/riscv/riscv_reg_impl.h
+++ b/src/target/riscv/riscv_reg_impl.h
@@ -13,7 +13,7 @@
* This file describes the helpers to use during register cache initialization
* of a RISC-V target. Each cache entry proceedes through the following stages:
* - not allocated before `riscv_reg_impl_init_cache()`
- * - not initialized before the call to `riscv_reg_impl_init_one()` with appropriate regno.
+ * - not initialized before the call to `riscv_reg_impl_init_cache_entry()` with appropriate regno.
* - initialized until `riscv_reg_free_all()` is called.
*/
static inline bool riscv_reg_impl_is_initialized(const struct reg *reg)
@@ -37,8 +37,18 @@ static inline bool riscv_reg_impl_is_initialized(const struct reg *reg)
int riscv_reg_impl_init_cache(struct target *target);
/** Initialize register. */
-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);
+
+/**
+ * For most registers, returns whether they exist or not.
+ * For some registers the "exist" bit should be set explicitly.
+ */
+bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno);
+
+/** Mark register as existing or not. */
+int riscv_reg_impl_set_exist(const struct target *target,
+ uint32_t regno, bool exist);
/** Return the entry in the register cache of the target. */
struct reg *riscv_reg_impl_cache_entry(const struct target *target,