diff options
author | Tim Newsome <tim@sifive.com> | 2019-07-16 13:29:45 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-16 13:29:45 -0700 |
commit | 3f200ac315c53d8caae1e454c19b655e6b35048b (patch) | |
tree | 4b65fa7d0d1cefe9e41416e6864c04ca1607ae4a /riscv/debug_module.cc | |
parent | b1bde2b904cd681c902d7c42c34bc55b4f4922ac (diff) | |
download | riscv-isa-sim-3f200ac315c53d8caae1e454c19b655e6b35048b.zip riscv-isa-sim-3f200ac315c53d8caae1e454c19b655e6b35048b.tar.gz riscv-isa-sim-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.cc | 34 |
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)) { |