Handle SRET - restore SIE from SPIE, privilege from SPP, return PC from SEPC. Err if illegal.
(regs: &mut Registers, csrs: &mut CsrFile)
| 169 | // Clear MPRV (not returning to M-mode). |
| 170 | csrs.mstatus &= !(1u64 << 17); |
| 171 | |
| 172 | Ok(csrs.sepc) |
| 173 | } |
| 174 | |
| 175 | // --- Unit tests for trap behavior --- |
| 176 | #[cfg(test)] |
| 177 | mod tests { |
| 178 | use super::*; |
| 179 | use crate::cpu::csr::CsrFile; |
| 180 | use crate::cpu::registers::{PrivilegeMode, Registers}; |
| 181 | |
| 182 | #[test] |
| 183 | fn test_mret_restores_privilege_and_pc() { |
| 184 | let mut regs = Registers::new(); |
| 185 | let mut csrs = CsrFile::new(); |
| 186 | |
| 187 | csrs.mstatus = 1u64 << 11; // MPP = 1 (Supervisor) |
| 188 | csrs.mepc = 0x1000; |
| 189 | |
| 190 | regs.priv_mode = PrivilegeMode::Machine; |
| 191 | let new_pc = handle_mret(&mut regs, &mut csrs); |
| 192 | |
| 193 | assert_eq!(new_pc, 0x1000); |
| 194 | assert_eq!(regs.priv_mode, PrivilegeMode::Supervisor); |
| 195 | assert_eq!((csrs.mstatus >> 11) & 0x3, 0); |
| 196 | } |
| 197 | |
| 198 | #[test] |
| 199 | fn test_sret_restores_privilege_and_pc() { |
| 200 | let mut regs = Registers::new(); |
| 201 | let mut csrs = CsrFile::new(); |
| 202 | |
| 203 | regs.priv_mode = PrivilegeMode::Supervisor; |
no outgoing calls