diff --git a/src/register/mod.rs b/src/register/mod.rs index 82fb0a1..df471c9 100644 --- a/src/register/mod.rs +++ b/src/register/mod.rs @@ -13,11 +13,17 @@ #[macro_use] mod macros; -// TODO: User Trap Setup - - -// TODO: User Trap Handling +// User Trap Setup +pub mod ustatus; +pub mod uie; +pub mod utvec; +// User Trap Handling +pub mod uscratch; +pub mod uepc; +pub mod ucause; +pub mod utval; +pub mod uip; // User Floating-Point CSRs // TODO: frm, fflags diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 9693918..6c34c83 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -2,6 +2,7 @@ // TODO: Virtualization, Memory Privilege and Extension Context Fields use bit_field::BitField; +use core::mem::size_of; /// mstatus register #[derive(Clone, Copy, Debug)] @@ -80,7 +81,7 @@ impl Mstatus { self.bits.get_bit(5) } - /// User Previous Interrupt Enable + /// Machine Previous Interrupt Enable #[inline] pub fn mpie(&self) -> bool { self.bits.get_bit(7) @@ -134,6 +135,13 @@ impl Mstatus { _ => unreachable!(), } } + + /// Whether either the FS field or XS field + /// signals the presence of some dirty state + #[inline] + pub fn sd(&self) -> bool { + self.bits.get_bit(size_of::() * 8 - 1) + } } diff --git a/src/register/scause.rs b/src/register/scause.rs index 0172f07..a9ffe92 100644 --- a/src/register/scause.rs +++ b/src/register/scause.rs @@ -59,7 +59,6 @@ impl Interrupt { } } - impl Exception { pub fn from(nr: usize) -> Self { match nr { diff --git a/src/register/sstatus.rs b/src/register/sstatus.rs index 550aaf2..68908fc 100644 --- a/src/register/sstatus.rs +++ b/src/register/sstatus.rs @@ -2,6 +2,7 @@ use bit_field::BitField; use core::mem::size_of; +pub use super::mstatus::FS; /// Supervisor Status Register #[derive(Clone, Copy, Debug)] @@ -16,15 +17,6 @@ pub enum SPP { User = 0, } -/// Floating-point unit Status -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum FS { - Off = 0, - Initial = 1, - Clean = 2, - Dirty = 3, -} - impl Sstatus { /// User Interrupt Enable #[inline] diff --git a/src/register/stvec.rs b/src/register/stvec.rs index aab918b..2bbbefa 100644 --- a/src/register/stvec.rs +++ b/src/register/stvec.rs @@ -1,18 +1,13 @@ //! stvec register +pub use crate::register::mtvec::TrapMode; + /// stvec register #[derive(Clone, Copy, Debug)] pub struct Stvec { bits: usize, } -/// Trap mode -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum TrapMode { - Direct = 0, - Vectored = 1, -} - impl Stvec { /// Returns the contents of the register as raw bits pub fn bits(&self) -> usize { diff --git a/src/register/ucause.rs b/src/register/ucause.rs new file mode 100644 index 0000000..06dd8a3 --- /dev/null +++ b/src/register/ucause.rs @@ -0,0 +1,17 @@ +//! ucause register + +/// ucause register +#[derive(Clone, Copy, Debug)] +pub struct Ucause { + bits: usize, +} + +impl Ucause { + /// Returns the contents of the register as raw bits + #[inline] + pub fn bits(&self) -> usize { + self.bits + } +} + +read_csr_as!(Ucause, 0x042, __read_ucause); diff --git a/src/register/uepc.rs b/src/register/uepc.rs new file mode 100644 index 0000000..1c9fa0e --- /dev/null +++ b/src/register/uepc.rs @@ -0,0 +1,4 @@ +//! uepc register + +read_csr_as_usize!(0x041, __read_uepc); +write_csr_as_usize!(0x041, __write_uepc); diff --git a/src/register/uie.rs b/src/register/uie.rs new file mode 100644 index 0000000..4a5e9e0 --- /dev/null +++ b/src/register/uie.rs @@ -0,0 +1,49 @@ +//! uie register + +use bit_field::BitField; + +/// uie register +#[derive(Clone, Copy, Debug)] +pub struct Uie { + bits: usize, +} + +impl Uie { + /// Returns the contents of the register as raw bits + #[inline] + pub fn bits(&self) -> usize { + self.bits + } + + /// User Software Interrupt Enable + #[inline] + pub fn usoft(&self) -> bool { + self.bits.get_bit(0) + } + + /// User Timer Interrupt Enable + #[inline] + pub fn utimer(&self) -> bool { + self.bits.get_bit(4) + } + + /// User External Interrupt Enable + #[inline] + pub fn uext(&self) -> bool { + self.bits.get_bit(8) + } +} + +read_csr_as!(Uie, 0x004, __read_uie); +set!(0x004, __set_uie); +clear!(0x004, __clear_uie); + +set_clear_csr!( + /// User Software Interrupt Enable + , set_usoft, clear_usoft, 1 << 0); +set_clear_csr!( + /// User Timer Interrupt Enable + , set_utimer, clear_utimer, 1 << 4); +set_clear_csr!( + /// User External Interrupt Enable + , set_uext, clear_uext, 1 << 8); diff --git a/src/register/uip.rs b/src/register/uip.rs new file mode 100644 index 0000000..ec92ad8 --- /dev/null +++ b/src/register/uip.rs @@ -0,0 +1,37 @@ +//! uip register + +use bit_field::BitField; + +/// uip register +#[derive(Clone, Copy, Debug)] +pub struct Uip { + bits: usize, +} + +impl Uip { + /// Returns the contents of the register as raw bits + #[inline] + pub fn bits(&self) -> usize { + self.bits + } + + /// User Software Interrupt Pending + #[inline] + pub fn usoft(&self) -> bool { + self.bits.get_bit(0) + } + + /// User Timer Interrupt Pending + #[inline] + pub fn utimer(&self) -> bool { + self.bits.get_bit(4) + } + + /// User External Interrupt Pending + #[inline] + pub fn uext(&self) -> bool { + self.bits.get_bit(8) + } +} + +read_csr_as!(Uip, 0x044, __read_uip); diff --git a/src/register/uscratch.rs b/src/register/uscratch.rs new file mode 100644 index 0000000..2bc2253 --- /dev/null +++ b/src/register/uscratch.rs @@ -0,0 +1,4 @@ +//! uscratch register + +read_csr_as_usize!(0x040, __read_uscratch); +write_csr_as_usize!(0x040, __write_uscratch); diff --git a/src/register/ustatus.rs b/src/register/ustatus.rs new file mode 100644 index 0000000..81890ba --- /dev/null +++ b/src/register/ustatus.rs @@ -0,0 +1,37 @@ +//! ustatus register +// TODO: Virtualization, Memory Privilege and Extension Context Fields + +use bit_field::BitField; + +/// ustatus register +#[derive(Clone, Copy, Debug)] +pub struct Ustatus { + bits: usize, +} + +impl Ustatus { + /// User Interrupt Enable + #[inline] + pub fn uie(&self) -> bool { + self.bits.get_bit(0) + } + + /// User Previous Interrupt Enable + #[inline] + pub fn upie(&self) -> bool { + self.bits.get_bit(4) + } +} + +read_csr_as!(Ustatus, 0x000, __read_ustatus); +write_csr!(0x000, __write_ustatus); +set!(0x000, __set_ustatus); +clear!(0x000, __clear_ustatus); + +set_clear_csr!( + /// User Interrupt Enable + , set_uie, clear_uie, 1 << 0); + +set_csr!( + /// User Previous Interrupt Enable + , set_upie, 1 << 4); diff --git a/src/register/utval.rs b/src/register/utval.rs new file mode 100644 index 0000000..b87dca6 --- /dev/null +++ b/src/register/utval.rs @@ -0,0 +1,3 @@ +//! utval register + +read_csr_as_usize!(0x043, __read_utval); diff --git a/src/register/utvec.rs b/src/register/utvec.rs new file mode 100644 index 0000000..31b6109 --- /dev/null +++ b/src/register/utvec.rs @@ -0,0 +1,40 @@ +//! stvec register + +pub use crate::register::mtvec::TrapMode; + +/// stvec register +#[derive(Clone, Copy, Debug)] +pub struct Utvec { + bits: usize, +} + +impl Utvec { + /// Returns the contents of the register as raw bits + pub fn bits(&self) -> usize { + self.bits + } + + /// Returns the trap-vector base-address + pub fn address(&self) -> usize { + self.bits - (self.bits & 0b11) + } + + /// Returns the trap-vector mode + pub fn trap_mode(&self) -> TrapMode { + let mode = self.bits & 0b11; + match mode { + 0 => TrapMode::Direct, + 1 => TrapMode::Vectored, + _ => unimplemented!() + } + } +} + +read_csr_as!(Utvec, 0x005, __read_utvec); +write_csr!(0x005, __write_utvec); + +/// Writes the CSR +#[inline] +pub unsafe fn write(addr: usize, mode: TrapMode) { + _write(addr + mode as usize); +}