aboutsummaryrefslogtreecommitdiff
path: root/riscv/debug_module.cc
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2019-07-16 13:29:45 -0700
committerGitHub <noreply@github.com>2019-07-16 13:29:45 -0700
commit3f200ac315c53d8caae1e454c19b655e6b35048b (patch)
tree4b65fa7d0d1cefe9e41416e6864c04ca1607ae4a /riscv/debug_module.cc
parentb1bde2b904cd681c902d7c42c34bc55b4f4922ac (diff)
downloadspike-3f200ac315c53d8caae1e454c19b655e6b35048b.zip
spike-3f200ac315c53d8caae1e454c19b655e6b35048b.tar.gz
spike-3f200ac315c53d8caae1e454c19b655e6b35048b.tar.bz2
Writing non-existent CSRs, access FPRs with mstatus.FS=0 (#311)
* Don't corrupt s0 when abstract CSR write fails. * Support abstract FPR access then mstatus.FS=0 Discussion on the spec list leans towards this being a requirement. Certainly users want their debugger to be able to access all registers regardless of target state.
Diffstat (limited to 'riscv/debug_module.cc')
-rw-r--r--riscv/debug_module.cc34
1 files changed, 32 insertions, 2 deletions
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
index c4fb45c..f5d33f2 100644
--- a/riscv/debug_module.cc
+++ b/riscv/debug_module.cc
@@ -557,6 +557,12 @@ void debug_module_t::run_test_idle()
}
}
+static bool is_fpu_reg(unsigned regno)
+{
+ return (regno >= 0x1020 && regno <= 0x103f) || regno == CSR_FFLAGS ||
+ regno == CSR_FRM || regno == CSR_FCSR;
+}
+
bool debug_module_t::perform_abstract_command()
{
if (abstractcs.cmderr != CMDERR_NONE)
@@ -580,8 +586,22 @@ bool debug_module_t::perform_abstract_command()
unsigned i = 0;
if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
- if (regno < 0x1000 && config.support_abstract_csr_access) {
+ if (is_fpu_reg(regno)) {
+ // Save S0
write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH));
+ // Save mstatus
+ write32(debug_abstract, i++, csrr(S0, CSR_MSTATUS));
+ write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH + 1));
+ // Set mstatus.fs
+ assert((MSTATUS_FS & 0xfff) == 0);
+ write32(debug_abstract, i++, lui(S0, MSTATUS_FS >> 12));
+ write32(debug_abstract, i++, csrrs(ZERO, S0, CSR_MSTATUS));
+ }
+
+ if (regno < 0x1000 && config.support_abstract_csr_access) {
+ if (!is_fpu_reg(regno)) {
+ write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH));
+ }
if (write) {
switch (size) {
@@ -611,7 +631,9 @@ bool debug_module_t::perform_abstract_command()
return true;
}
}
- write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
+ if (!is_fpu_reg(regno)) {
+ write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
+ }
} else if (regno >= 0x1000 && regno < 0x1020) {
unsigned regnum = regno - 0x1000;
@@ -682,6 +704,14 @@ bool debug_module_t::perform_abstract_command()
abstractcs.cmderr = CMDERR_NOTSUP;
return true;
}
+
+ if (is_fpu_reg(regno)) {
+ // restore mstatus
+ write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH + 1));
+ write32(debug_abstract, i++, csrw(S0, CSR_MSTATUS));
+ // restore s0
+ write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
+ }
}
if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {