aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2019-07-08 12:26:01 -0700
committerGitHub <noreply@github.com>2019-07-08 12:26:01 -0700
commit8f2d2c27e8b816f62785cfc4f445e380d5e8fc32 (patch)
treeafc5e83e660c8512a391775ec003ee5201f6bfdb
parent91faf1a573d6931cc2f563751421330944243b68 (diff)
downloadriscv-openocd-8f2d2c27e8b816f62785cfc4f445e380d5e8fc32.zip
riscv-openocd-8f2d2c27e8b816f62785cfc4f445e380d5e8fc32.tar.gz
riscv-openocd-8f2d2c27e8b816f62785cfc4f445e380d5e8fc32.tar.bz2
RV32E support (#387)
* In theory support RV32E. Change-Id: Icfe2a40976ae3161f2324e5bb586915aa4c4c7ee * In theory support RV32E. At least very basic tests pass. Change-Id: Ia42e28a3fa020b3e52c92109392c46d009330355 * Fix cut and paste bug. Change-Id: Ibfea68b39d706f59a8c3aa8153bb4db9803958c6 * Add hacks to make RV32E work with gdb. gdb currently requires all 32 GPRs to be present, even on RV32E targets. Once gdb is fixed these hacks can be removed. Change-Id: Idcde648de2ca1a3f5b31315aab35fac86580af2c
-rw-r--r--src/target/riscv/gdb_regs.h1
-rw-r--r--src/target/riscv/riscv.c42
2 files changed, 31 insertions, 12 deletions
diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h
index a587952..2379417 100644
--- a/src/target/riscv/gdb_regs.h
+++ b/src/target/riscv/gdb_regs.h
@@ -21,6 +21,7 @@ enum gdb_regno {
GDB_REGNO_A3,
GDB_REGNO_A4,
GDB_REGNO_A5,
+ GDB_REGNO_XPR15 = GDB_REGNO_A5,
GDB_REGNO_A6,
GDB_REGNO_A7,
GDB_REGNO_S2,
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index f864b14..f1c57e6 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -1356,7 +1356,9 @@ static int riscv_get_gdb_reg_list_internal(struct target *target,
assert(!target->reg_cache->reg_list[i].valid ||
target->reg_cache->reg_list[i].size > 0);
(*reg_list)[i] = &target->reg_cache->reg_list[i];
- if (read && !target->reg_cache->reg_list[i].valid) {
+ if (read &&
+ target->reg_cache->reg_list[i].exist &&
+ !target->reg_cache->reg_list[i].valid) {
if (target->reg_cache->reg_list[i].type->get(
&target->reg_cache->reg_list[i]) != ERROR_OK)
return ERROR_FAIL;
@@ -2595,6 +2597,12 @@ int riscv_set_register_on_hart(struct target *target, int hartid,
RISCV_INFO(r);
LOG_DEBUG("{%d} %s <- %" PRIx64, hartid, gdb_regno_name(regid), value);
assert(r->set_register);
+
+ /* TODO: Hack to deal with gdb that thinks these registers still exist. */
+ if (regid > GDB_REGNO_XPR15 && regid <= GDB_REGNO_XPR31 && value == 0 &&
+ riscv_supports_extension(target, hartid, 'E'))
+ return ERROR_OK;
+
return r->set_register(target, hartid, regid, value);
}
@@ -2617,6 +2625,13 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
return ERROR_OK;
}
+ /* TODO: Hack to deal with gdb that thinks these registers still exist. */
+ if (regid > GDB_REGNO_XPR15 && regid <= GDB_REGNO_XPR31 &&
+ riscv_supports_extension(target, hartid, 'E')) {
+ *value = 0;
+ return ERROR_OK;
+ }
+
int result = r->get_register(target, value, hartid, regid);
LOG_DEBUG("{%d} %s: %" PRIx64, hartid, gdb_regno_name(regid), *value);
@@ -2952,6 +2967,8 @@ int riscv_init_registers(struct target *target)
riscv_reg_info_t *shared_reg_info = calloc(1, sizeof(riscv_reg_info_t));
shared_reg_info->target = target;
+ int hartid = riscv_current_hartid(target);
+
/* When gdb requests register N, gdb_get_register_packet() assumes that this
* is register at index N in reg_list. So if there are certain registers
* that don't exist, we need to leave holes in the list (or renumber, but
@@ -2970,6 +2987,11 @@ int riscv_init_registers(struct target *target)
* target is in theory allowed to change XLEN on us. But I expect a lot
* of other things to break in that case as well. */
if (number <= GDB_REGNO_XPR31) {
+ r->exist = number <= GDB_REGNO_XPR15 ||
+ !riscv_supports_extension(target, hartid, 'E');
+ /* TODO: For now we fake that all GPRs exist because otherwise gdb
+ * doesn't work. */
+ r->exist = true;
r->caller_save = true;
switch (number) {
case GDB_REGNO_ZERO:
@@ -3078,12 +3100,10 @@ int riscv_init_registers(struct target *target)
r->feature = &feature_cpu;
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
r->caller_save = true;
- if (riscv_supports_extension(target, riscv_current_hartid(target),
- 'D')) {
+ if (riscv_supports_extension(target, hartid, 'D')) {
r->reg_data_type = &type_ieee_double;
r->size = 64;
- } else if (riscv_supports_extension(target,
- riscv_current_hartid(target), 'F')) {
+ } else if (riscv_supports_extension(target, hartid, 'F')) {
r->reg_data_type = &type_ieee_single;
r->size = 32;
} else {
@@ -3214,8 +3234,7 @@ int riscv_init_registers(struct target *target)
case CSR_FFLAGS:
case CSR_FRM:
case CSR_FCSR:
- r->exist = riscv_supports_extension(target,
- riscv_current_hartid(target), 'F');
+ r->exist = riscv_supports_extension(target, hartid, 'F');
r->group = "float";
r->feature = &feature_fpu;
break;
@@ -3229,16 +3248,15 @@ int riscv_init_registers(struct target *target)
case CSR_SCAUSE:
case CSR_STVAL:
case CSR_SATP:
- r->exist = riscv_supports_extension(target,
- riscv_current_hartid(target), 'S');
+ r->exist = riscv_supports_extension(target, hartid, 'S');
break;
case CSR_MEDELEG:
case CSR_MIDELEG:
/* "In systems with only M-mode, or with both M-mode and
* U-mode but without U-mode trap support, the medeleg and
* mideleg registers should not exist." */
- r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') ||
- riscv_supports_extension(target, riscv_current_hartid(target), 'N');
+ r->exist = riscv_supports_extension(target, hartid, 'S') ||
+ riscv_supports_extension(target, hartid, 'N');
break;
case CSR_CYCLEH:
@@ -3324,7 +3342,7 @@ int riscv_init_registers(struct target *target)
r->feature = &feature_virtual;
r->size = 8;
- } else {
+ } else if (number >= GDB_REGNO_COUNT) {
/* Custom registers. */
assert(expose_custom);