aboutsummaryrefslogtreecommitdiff
path: root/src/target/riscv/riscv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/riscv/riscv.c')
-rw-r--r--src/target/riscv/riscv.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index c26ba56..afcbf91 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -3229,6 +3229,10 @@ const char *gdb_regno_name(enum gdb_regno regno)
return "priv";
case GDB_REGNO_SATP:
return "satp";
+ case GDB_REGNO_VTYPE:
+ return "vtype";
+ case GDB_REGNO_VL:
+ return "vl";
case GDB_REGNO_V0:
return "v0";
case GDB_REGNO_V1:
@@ -3310,20 +3314,35 @@ static int register_get(struct reg *reg)
{
riscv_reg_info_t *reg_info = reg->arch_info;
struct target *target = reg_info->target;
- uint64_t value;
- int result = riscv_get_register(target, &value, reg->number);
- if (result != ERROR_OK)
- return result;
- buf_set_u64(reg->value, 0, reg->size, value);
+ RISCV_INFO(r);
+
+ if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) {
+ if (!r->get_register_buf) {
+ LOG_ERROR("Reading register %s not supported on this RISC-V target.",
+ gdb_regno_name(reg->number));
+ return ERROR_FAIL;
+ }
+
+ if (r->get_register_buf(target, reg->value, reg->number) != ERROR_OK)
+ return ERROR_FAIL;
+ } else {
+ uint64_t value;
+ int result = riscv_get_register(target, &value, reg->number);
+ if (result != ERROR_OK)
+ return result;
+ buf_set_u64(reg->value, 0, reg->size, value);
+ }
/* CSRs (and possibly other extension) registers may change value at any
* time. */
if (reg->number <= GDB_REGNO_XPR31 ||
(reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) ||
+ (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) ||
reg->number == GDB_REGNO_PC)
reg->valid = true;
- LOG_DEBUG("[%d]{%d} read 0x%" PRIx64 " from %s (valid=%d)",
- target->coreid, riscv_current_hartid(target), value, reg->name,
- reg->valid);
+ char *str = buf_to_str(reg->value, reg->size, 16);
+ LOG_DEBUG("[%d]{%d} read 0x%s from %s (valid=%d)", target->coreid,
+ riscv_current_hartid(target), str, reg->name, reg->valid);
+ free(str);
return ERROR_OK;
}
@@ -3331,22 +3350,37 @@ static int register_set(struct reg *reg, uint8_t *buf)
{
riscv_reg_info_t *reg_info = reg->arch_info;
struct target *target = reg_info->target;
+ RISCV_INFO(r);
- uint64_t value = buf_get_u64(buf, 0, reg->size);
+ char *str = buf_to_str(reg->value, reg->size, 16);
+ LOG_DEBUG("[%d]{%d} write 0x%s to %s (valid=%d)", target->coreid,
+ riscv_current_hartid(target), str, reg->name, reg->valid);
+ free(str);
- LOG_DEBUG("[%d]{%d} write 0x%" PRIx64 " to %s (valid=%d)",
- target->coreid, riscv_current_hartid(target), value, reg->name,
- reg->valid);
- struct reg *r = &target->reg_cache->reg_list[reg->number];
+ memcpy(reg->value, buf, DIV_ROUND_UP(reg->size, 8));
/* CSRs (and possibly other extension) registers may change value at any
* time. */
if (reg->number <= GDB_REGNO_XPR31 ||
(reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) ||
+ (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) ||
reg->number == GDB_REGNO_PC)
- r->valid = true;
- memcpy(r->value, buf, (r->size + 7) / 8);
+ reg->valid = true;
+
+ if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) {
+ if (!r->set_register_buf) {
+ LOG_ERROR("Reading register %s not supported on this RISC-V target.",
+ gdb_regno_name(reg->number));
+ return ERROR_FAIL;
+ }
+
+ if (r->set_register_buf(target, reg->number, reg->value) != ERROR_OK)
+ return ERROR_FAIL;
+ } else {
+ uint64_t value = buf_get_u64(buf, 0, reg->size);
+ if (riscv_set_register(target, reg->number, value) != ERROR_OK)
+ return ERROR_FAIL;
+ }
- riscv_set_register(target, reg->number, value);
return ERROR_OK;
}
@@ -3835,9 +3869,11 @@ int riscv_init_registers(struct target *target)
r->size = 8;
} else if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31) {
- r->caller_save = true;
+ /* TODO: These should be caller saved, but if I say it's true then
+ * gdb only tries to save 32 bits, which makes OpenOCD unhappy when
+ * it tries to write a 32-bit value to a larger register. */
+ r->caller_save = false;
r->exist = riscv_supports_extension(target, hartid, 'V');
- //r->reg_data_type = &type_arch_defined;
r->size = info->vlenb[hartid] * 8;
sprintf(reg_name, "v%d", number - GDB_REGNO_V0);
r->group = "vector";