diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index d610b33de8..39a7a6ba38 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -5157,7 +5157,10 @@ static int riscv_set_or_write_register(struct target *target, enum gdb_regno regid, riscv_reg_t value, bool write_through) { RISCV_INFO(r); + assert(r); assert(r->set_register); + if (r->dtm_version == DTM_DTMCS_VERSION_0_11) + return r->set_register(target, regid, value); keep_alive(); @@ -5254,7 +5257,10 @@ int riscv_get_register(struct target *target, riscv_reg_t *value, enum gdb_regno regid) { RISCV_INFO(r); + assert(r); assert(r->get_register); + if (r->dtm_version == DTM_DTMCS_VERSION_0_11) + return r->get_register(target, value, regid); keep_alive(); @@ -5710,13 +5716,17 @@ const char *gdb_regno_name(const struct target *target, enum gdb_regno regno) return NULL; } +static struct target *get_target_from_reg(const struct reg *reg); + /** * This function is the handler of user's request to read a register. */ -static int register_get(struct reg *reg) +static int riscv013_reg_get(struct reg *reg) { - struct target *target = ((riscv_reg_info_t *)reg->arch_info)->target; + struct target *target = get_target_from_reg(reg); RISCV_INFO(r); + assert(r); + assert(r->dtm_version == DTM_DTMCS_VERSION_1_0); /* TODO: Hack to deal with gdb that thinks these registers still exist. */ if (reg->number > GDB_REGNO_XPR15 && reg->number <= GDB_REGNO_XPR31 && @@ -5754,10 +5764,12 @@ static int register_get(struct reg *reg) /** * This function is the handler of user's request to write a register. */ -static int register_set(struct reg *reg, uint8_t *buf) +static int riscv013_reg_set(struct reg *reg, uint8_t *buf) { - struct target *target = ((riscv_reg_info_t *)reg->arch_info)->target; + struct target *target = get_target_from_reg(reg); RISCV_INFO(r); + assert(r); + assert(r->dtm_version == DTM_DTMCS_VERSION_1_0); char *str = buf_to_hex_str(buf, reg->size); LOG_TARGET_DEBUG(target, "Write 0x%s to %s (valid=%d).", str, reg->name, @@ -5803,11 +5815,6 @@ static int register_set(struct reg *reg, uint8_t *buf) return ERROR_OK; } -static struct reg_arch_type riscv_reg_arch_type = { - .get = register_get, - .set = register_set -}; - static int init_custom_register_names(struct list_head *expose_custom, struct reg_name_table *custom_register_names) { @@ -5858,7 +5865,7 @@ static bool is_known_standard_csr(unsigned int csr_num) return is_csr_in_buf[csr_num]; } -bool reg_is_initialized(const struct reg *reg) +static bool reg_is_initialized(const struct reg *reg) { assert(reg); if (!reg->feature) { @@ -5873,6 +5880,56 @@ bool reg_is_initialized(const struct reg *reg) return true; } +static struct target *get_target_from_reg(const struct reg *reg) +{ + assert(reg_is_initialized(reg)); + return ((const riscv_reg_info_t *)reg->arch_info)->target; +} + +static int riscv011_reg_get(struct reg *reg) +{ + struct target * const target = get_target_from_reg(reg); + RISCV_INFO(info); + assert(info); + assert(info->dtm_version == DTM_DTMCS_VERSION_0_11); + riscv_reg_t value; + const int result = info->get_register(target, &value, reg->number); + if (result != ERROR_OK) + return result; + buf_set_u64(reg->value, 0, reg->size, value); + return ERROR_OK; +} + +static int riscv011_reg_set(struct reg *reg, uint8_t *buf) +{ + const riscv_reg_t value = buf_get_u64(buf, 0, reg->size); + struct target * const target = get_target_from_reg(reg); + RISCV_INFO(info); + assert(info); + assert(info->dtm_version == DTM_DTMCS_VERSION_0_11); + return info->set_register(target, reg->number, value); +} + +static struct reg_arch_type *gdb_regno_reg_type(const struct target *target, + uint32_t regno) +{ + RISCV_INFO(info); + assert(info); + if (info->dtm_version == DTM_DTMCS_VERSION_0_11) { + static struct reg_arch_type riscv011_reg_type = { + .get = riscv011_reg_get, + .set = riscv011_reg_set + }; + return &riscv011_reg_type; + } + + static struct reg_arch_type riscv013_reg_type = { + .get = riscv013_reg_get, + .set = riscv013_reg_set + }; + return &riscv013_reg_type; +} + static struct reg_feature *gdb_regno_feature(uint32_t regno) { if (regno <= GDB_REGNO_XPR31 || regno == GDB_REGNO_PC) { @@ -6246,7 +6303,7 @@ static int init_reg(struct target *target, uint32_t regno) if (reg_is_initialized(reg)) return ERROR_OK; reg->number = regno; - reg->type = &riscv_reg_arch_type; + reg->type = gdb_regno_reg_type(target, regno); reg->dirty = false; reg->valid = false; reg->hidden = false;