From 039746112bcfb7e447fe09091501a3a454220b6a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 Nov 2021 15:10:20 +0100 Subject: [PATCH] fix exception behavior --- incl/iss/arch/riscv_hart_m_p.h | 17 ++++++++++++++--- incl/iss/arch/riscv_hart_mu_p.h | 21 ++++++++++++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index fa7324a..9133285 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -959,9 +959,16 @@ template uint64_t riscv_hart_m_p::e if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause // store ret addr in xepc register csr[mepc] = static_cast(addr) & get_pc_mask(); // store actual address instruction of exception + /* + * write mtval if new_priv=M_MODE, spec says: + * When a hardware breakpoint is triggered, or an instruction-fetch, load, + * or store address-misaligned, + * access, or page-fault exception occurs, mtval is written with the + * faulting effective address. + */ switch(cause){ case 0: - csr[mtval] = addr; + csr[mtval] = static_cast(addr); break; case 2: csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; @@ -970,10 +977,14 @@ template uint64_t riscv_hart_m_p::e //TODO: implement debug mode behavior // csr[dpc] = addr; // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) - csr[mtval] = addr; + csr[mtval] = 0; + break; + case 4: + case 6: + csr[mtval] = fault_data; break; default: - csr[mtval] = fault_data; + csr[mtval] = 0; } fault_data = 0; } else { diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index bb25f2e..5ade158 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -1220,7 +1220,26 @@ template uint64_t riscv_hart_mu_p:: * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - csr[utval | (new_priv << 8)] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data; + switch(cause){ + case 0: + csr[utval | (new_priv << 8)] = static_cast(addr); + break; + case 2: + csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + break; + case 3: + //TODO: implement debug mode behavior + // csr[dpc] = addr; + // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[utval | (new_priv << 8)] = 0; + break; + case 4: + case 6: + csr[utval | (new_priv << 8)] = fault_data; + break; + default: + csr[utval | (new_priv << 8)] = 0; + } fault_data = 0; } else { if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)