From ef9926d3577b901f027673521a950b5bb5b217a8 Mon Sep 17 00:00:00 2001 From: john <799433746@qq.com> Date: Sat, 3 Jul 2021 11:29:32 +0000 Subject: [PATCH 01/13] add support for mprv --- src/register/mstatus.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 4946ecd7..7c477335 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -142,6 +142,12 @@ impl Mstatus { } } + /// Modify Memory PRiVilege + #[inline] + pub fn mprv(&self) -> bool { + self.bits.get_bit(17) + } + /// Permit Supervisor User Memory access #[inline] pub fn sum(&self) -> bool { @@ -226,6 +232,9 @@ set_csr!( set_csr!( /// Machine Previous Interrupt Enable , set_mpie, 1 << 7); +set_clear_csr!( + /// Modify Memory PRiVilege + , set_mprv, clear_mprv, 1 << 17); set_clear_csr!( /// Permit Supervisor User Memory access , set_sum, clear_sum, 1 << 18); From 29b8d3fe20d54ad433c68a2ecfd4d0e2e5fe15aa Mon Sep 17 00:00:00 2001 From: john <799433746@qq.com> Date: Sat, 3 Jul 2021 12:09:23 +0000 Subject: [PATCH 02/13] add a bunch of setter for mstatus --- src/register/mstatus.rs | 148 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 7c477335..5e5aa34a 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -57,6 +57,154 @@ pub enum SPP { } impl Mstatus { + /// User Interrupt Enable + #[inline] + pub fn set_uie(&mut self, value: bool) { + self.bits.set_bit(0, value); + } + + /// Supervisor Interrupt Enable + #[inline] + pub fn set_sie(&mut self, value: bool) { + self.bits.set_bit(1, value); + } + + /// Machine Interrupt Enable + #[inline] + pub fn set_mie(&mut self, value: bool) { + self.bits.set_bit(3, value); + } + + /// User Previous Interrupt Enable + #[inline] + pub fn set_upie(&mut self, value: bool) { + self.bits.set_bit(4, value); + } + + /// Supervisor Previous Interrupt Enable + #[inline] + pub fn set_spie(&mut self, value: bool) { + self.bits.set_bit(5, value); + } + + /// Machine Previous Interrupt Enable + #[inline] + pub fn set_mpie(&mut self, value: bool) { + self.bits.set_bit(7, value); + } + + /// Supervisor Previous Privilege Mode + #[inline] + pub fn set_spp(&mut self, spp: SPP) { + match spp { + SPP::Supervisor => self.bits.set_bit(8, true), + SPP::User => self.bits.set_bit(8, false), + }; + } + + /// Machine Previous Privilege Mode + #[inline] + pub fn set_mpp(&mut self, mpp: MPP) { + match mpp { + MPP::User => self.bits.set_bits(11..13, 0b00), + MPP::Supervisor => self.bits.set_bits(11..13, 0b01), + MPP::Machine => self.bits.set_bits(11..13, 0b11), + }; + } + + /// Floating-point extension state + /// + /// Encodes the status of the floating-point unit, + /// including the CSR `fcsr` and floating-point data registers `f0–f31`. + #[inline] + pub fn set_fs(&mut self, fs: FS) { + match fs { + FS::Off => self.bits.set_bits(13..15, 0b00), + FS::Initial => self.bits.set_bits(13..15, 0b01), + FS::Clean => self.bits.set_bits(13..15, 0b10), + FS::Dirty => self.bits.set_bits(13..15, 0b11), + }; + } + + /// Additional extension state + /// + /// Encodes the status of additional user-mode extensions and associated state. + #[inline] + pub fn set_xs(&mut self, xs: XS) { + match xs { + XS::AllOff => self.bits.set_bits(15..17, 0b00), + XS::NoneDirtyOrClean => self.bits.set_bits(15..17, 0b01), + XS::NoneDirtySomeClean => self.bits.set_bits(15..17, 0b10), + XS::SomeDirty => self.bits.set_bits(15..17, 0b11), + }; + } + + /// Modify Memory PRiVilege + #[inline] + pub fn set_mprv(&mut self, value: bool) { + self.bits.set_bit(17, value); + } + + /// Permit Supervisor User Memory access + #[inline] + pub fn set_sum(&mut self, value: bool) { + self.bits.set_bit(18, value); + } + + /// Make eXecutable Readable + #[inline] + pub fn set_mxr(&mut self, value: bool) { + self.bits.set_bit(19, value); + } + + /// Trap Virtual Memory + /// + /// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma` + /// instruction when in S-mode will raise an illegal instruction exception. + /// + /// TVM is hard-wired to 0 when S-mode is not supported. + #[inline] + pub fn set_tvm(&mut self, value: bool) { + self.bits.set_bit(20, value); + } + + /// Timeout Wait + /// + /// Indicates that if WFI instruction should be intercepted. + /// + /// If this bit is set, when WFI is executed in S-mode, and it does not complete + /// within an implementation specific, bounded time limit, the WFI instruction will cause + /// an illegal instruction trap; or could always cause trap then the time limit is zero. + /// + /// TW is hard-wired to 0 when S-mode is not supported. + #[inline] + pub fn set_tw(&mut self, value: bool) { + self.bits.set_bit(21, value); + } + + /// Trap SRET + /// + /// Indicates that if SRET instruction should be trapped to raise illegal + /// instruction exception. + /// + /// If S-mode is not supported, TSR bit is hard-wired to 0. + #[inline] + pub fn set_tsr(&mut self, value: bool) { + self.bits.set_bit(22, value); + } + + /* + FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12 + is ratified, there should be read functions of these bits as well. + */ + + /// Whether either the FS field or XS field + /// signals the presence of some dirty state + #[inline] + pub fn set_sd(&mut self, value: bool) { + self.bits.set_bit(size_of::() * 8 - 1, value); + } + /// User Interrupt Enable #[inline] pub fn uie(&self) -> bool { From af3996c6df403952b6978a4daa32d69337cac055 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 00:13:12 +0800 Subject: [PATCH 03/13] add builder, remove setter --- src/lib.rs | 1 + src/register/mstatus.rs | 148 ---------------------------------------- 2 files changed, 1 insertion(+), 148 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4d78c926..834c7fd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ pub mod asm; pub mod delay; pub mod interrupt; pub mod register; +pub mod builder; #[macro_use] mod macros; diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 5e5aa34a..7c477335 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -57,154 +57,6 @@ pub enum SPP { } impl Mstatus { - /// User Interrupt Enable - #[inline] - pub fn set_uie(&mut self, value: bool) { - self.bits.set_bit(0, value); - } - - /// Supervisor Interrupt Enable - #[inline] - pub fn set_sie(&mut self, value: bool) { - self.bits.set_bit(1, value); - } - - /// Machine Interrupt Enable - #[inline] - pub fn set_mie(&mut self, value: bool) { - self.bits.set_bit(3, value); - } - - /// User Previous Interrupt Enable - #[inline] - pub fn set_upie(&mut self, value: bool) { - self.bits.set_bit(4, value); - } - - /// Supervisor Previous Interrupt Enable - #[inline] - pub fn set_spie(&mut self, value: bool) { - self.bits.set_bit(5, value); - } - - /// Machine Previous Interrupt Enable - #[inline] - pub fn set_mpie(&mut self, value: bool) { - self.bits.set_bit(7, value); - } - - /// Supervisor Previous Privilege Mode - #[inline] - pub fn set_spp(&mut self, spp: SPP) { - match spp { - SPP::Supervisor => self.bits.set_bit(8, true), - SPP::User => self.bits.set_bit(8, false), - }; - } - - /// Machine Previous Privilege Mode - #[inline] - pub fn set_mpp(&mut self, mpp: MPP) { - match mpp { - MPP::User => self.bits.set_bits(11..13, 0b00), - MPP::Supervisor => self.bits.set_bits(11..13, 0b01), - MPP::Machine => self.bits.set_bits(11..13, 0b11), - }; - } - - /// Floating-point extension state - /// - /// Encodes the status of the floating-point unit, - /// including the CSR `fcsr` and floating-point data registers `f0–f31`. - #[inline] - pub fn set_fs(&mut self, fs: FS) { - match fs { - FS::Off => self.bits.set_bits(13..15, 0b00), - FS::Initial => self.bits.set_bits(13..15, 0b01), - FS::Clean => self.bits.set_bits(13..15, 0b10), - FS::Dirty => self.bits.set_bits(13..15, 0b11), - }; - } - - /// Additional extension state - /// - /// Encodes the status of additional user-mode extensions and associated state. - #[inline] - pub fn set_xs(&mut self, xs: XS) { - match xs { - XS::AllOff => self.bits.set_bits(15..17, 0b00), - XS::NoneDirtyOrClean => self.bits.set_bits(15..17, 0b01), - XS::NoneDirtySomeClean => self.bits.set_bits(15..17, 0b10), - XS::SomeDirty => self.bits.set_bits(15..17, 0b11), - }; - } - - /// Modify Memory PRiVilege - #[inline] - pub fn set_mprv(&mut self, value: bool) { - self.bits.set_bit(17, value); - } - - /// Permit Supervisor User Memory access - #[inline] - pub fn set_sum(&mut self, value: bool) { - self.bits.set_bit(18, value); - } - - /// Make eXecutable Readable - #[inline] - pub fn set_mxr(&mut self, value: bool) { - self.bits.set_bit(19, value); - } - - /// Trap Virtual Memory - /// - /// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma` - /// instruction when in S-mode will raise an illegal instruction exception. - /// - /// TVM is hard-wired to 0 when S-mode is not supported. - #[inline] - pub fn set_tvm(&mut self, value: bool) { - self.bits.set_bit(20, value); - } - - /// Timeout Wait - /// - /// Indicates that if WFI instruction should be intercepted. - /// - /// If this bit is set, when WFI is executed in S-mode, and it does not complete - /// within an implementation specific, bounded time limit, the WFI instruction will cause - /// an illegal instruction trap; or could always cause trap then the time limit is zero. - /// - /// TW is hard-wired to 0 when S-mode is not supported. - #[inline] - pub fn set_tw(&mut self, value: bool) { - self.bits.set_bit(21, value); - } - - /// Trap SRET - /// - /// Indicates that if SRET instruction should be trapped to raise illegal - /// instruction exception. - /// - /// If S-mode is not supported, TSR bit is hard-wired to 0. - #[inline] - pub fn set_tsr(&mut self, value: bool) { - self.bits.set_bit(22, value); - } - - /* - FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12 - is ratified, there should be read functions of these bits as well. - */ - - /// Whether either the FS field or XS field - /// signals the presence of some dirty state - #[inline] - pub fn set_sd(&mut self, value: bool) { - self.bits.set_bit(size_of::() * 8 - 1, value); - } - /// User Interrupt Enable #[inline] pub fn uie(&self) -> bool { From d9a1cc2701859d081733c20b3de6574821a1e356 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 00:14:08 +0800 Subject: [PATCH 04/13] add builder, remove setter --- src/builder/macros.rs | 17 ++++ src/builder/mod.rs | 5 ++ src/builder/mstatus.rs | 175 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 src/builder/macros.rs create mode 100644 src/builder/mod.rs create mode 100644 src/builder/mstatus.rs diff --git a/src/builder/macros.rs b/src/builder/macros.rs new file mode 100644 index 00000000..be901a54 --- /dev/null +++ b/src/builder/macros.rs @@ -0,0 +1,17 @@ +macro_rules! impl_get_bit { + ($field: ident, $inner: ident, $getter: ident, $idx: literal) => { + #[inline] + pub fn $field(&self) -> bool { + self.$inner.$getter($idx) + } + }; +} + +macro_rules! impl_set_bit { + ($field_setter: ident, $inner: ident, $setter: ident, $idx: literal) => { + #[inline] + pub fn $field_setter(&mut self, value: bool) { + self.$inner.$setter($idx, value); + } + } +} diff --git a/src/builder/mod.rs b/src/builder/mod.rs new file mode 100644 index 00000000..fd73432e --- /dev/null +++ b/src/builder/mod.rs @@ -0,0 +1,5 @@ +#[macro_use] +mod macros; + +pub mod mstatus; + diff --git a/src/builder/mstatus.rs b/src/builder/mstatus.rs new file mode 100644 index 00000000..d06fc492 --- /dev/null +++ b/src/builder/mstatus.rs @@ -0,0 +1,175 @@ +//! mstatus register builder + +use bit_field::BitField; +use core::mem::size_of; +use core::arch::asm; +use crate::register::mstatus::*; + +/// mstatus register builder +pub struct MstatusBuilder { + bits: usize +} + +/// mstatus register value +#[derive(Clone, Copy, Debug)] +#[repr(transparent)] +pub struct MstatusValue { + bits: usize +} + +macro_rules! impl_mstatus_writable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_set_bit!(set_uie, $inner, set_bit, 0); + + impl_set_bit!(set_sie, $inner, set_bit, 1); + + impl_set_bit!(set_mie, $inner, set_bit, 3); + + impl_set_bit!(set_upie, $inner, set_bit, 4); + + impl_set_bit!(set_spie, $inner, set_bit, 5); + + impl_set_bit!(set_mpie, $inner, set_bit, 7); + + #[inline] + pub fn set_spp(&mut self, spp: SPP) { + match spp { + SPP::Supervisor => self.bits.set_bit(8, true), + SPP::User => self.bits.set_bit(8, false), + }; + } + #[inline] + pub fn set_mpp(&mut self, mpp: MPP) { + match mpp { + MPP::User => self.bits.set_bits(11..13, 0b00), + MPP::Supervisor => self.bits.set_bits(11..13, 0b01), + MPP::Machine => self.bits.set_bits(11..13, 0b11), + }; + } + + #[inline] + pub fn set_fs(&mut self, fs: FS) { + match fs { + FS::Off => self.bits.set_bits(13..15, 0b00), + FS::Initial => self.bits.set_bits(13..15, 0b01), + FS::Clean => self.bits.set_bits(13..15, 0b10), + FS::Dirty => self.bits.set_bits(13..15, 0b11), + }; + } + + #[inline] + pub fn set_xs(&mut self, xs: XS) { + match xs { + XS::AllOff => self.bits.set_bits(15..17, 0b00), + XS::NoneDirtyOrClean => self.bits.set_bits(15..17, 0b01), + XS::NoneDirtySomeClean => self.bits.set_bits(15..17, 0b10), + XS::SomeDirty => self.bits.set_bits(15..17, 0b11), + }; + } + + impl_set_bit!(set_mprv, $inner, set_bit, 17); + + impl_set_bit!(set_sum, $inner, set_bit, 18); + + impl_set_bit!(set_mxr, $inner, set_bit, 19); + + impl_set_bit!(set_tvm, $inner, set_bit, 20); + + impl_set_bit!(set_tw, $inner, set_bit, 21); + + impl_set_bit!(set_tsr, $inner, set_bit, 22); + + } + } +} + +macro_rules! impl_mstatus_readable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_get_bit!(uie, $inner, get_bit, 0); + + impl_get_bit!(sie, $inner, get_bit, 1); + + impl_get_bit!(mie, $inner, get_bit, 3); + + impl_get_bit!(upie, $inner, get_bit, 4); + + impl_get_bit!(spie, $inner, get_bit, 5); + + impl_get_bit!(mpie, $inner, get_bit, 7); + + #[inline] + pub fn spp(&self) -> SPP { + match self.$inner.get_bit(8) { + true => SPP::Supervisor, + false => SPP::User, + } + } + + #[inline] + pub fn mpp(&self) -> MPP { + match self.$inner.get_bits(11..13) { + 0b00 => MPP::User, + 0b01 => MPP::Supervisor, + 0b11 => MPP::Machine, + _ => unreachable!(), + } + } + + #[inline] + pub fn fs(&self) -> FS { + match self.$inner.get_bits(13..15) { + 0b00 => FS::Off, + 0b01 => FS::Initial, + 0b10 => FS::Clean, + 0b11 => FS::Dirty, + _ => unreachable!(), + } + } + + #[inline] + pub fn xs(&self) -> XS { + match self.$inner.get_bits(15..17) { + 0b00 => XS::AllOff, + 0b01 => XS::NoneDirtyOrClean, + 0b10 => XS::NoneDirtySomeClean, + 0b11 => XS::SomeDirty, + _ => unreachable!(), + } + } + + impl_get_bit!(mprv, $inner, get_bit, 17); + + impl_get_bit!(sum, $inner, get_bit, 18); + + impl_get_bit!(mxr, $inner, get_bit, 19); + + impl_get_bit!(tvm, $inner, get_bit, 20); + + impl_get_bit!(tw, $inner, get_bit, 21); + + impl_get_bit!(tsr, $inner, get_bit, 22); + + #[inline] + pub fn sd(&self) -> bool { + self.$inner.get_bit(size_of::() * 8 - 1) + } + } + } +} + +impl_mstatus_readable!(MstatusBuilder, bits); +impl_mstatus_writable!(MstatusBuilder, bits); + +impl MstatusBuilder { + pub fn build(&self) -> MstatusValue { + return MstatusValue { bits: self.bits } + } +} + +impl MstatusValue { + pub unsafe fn write_mstatus(&self) { + asm!("csrw mstatus, {0}", in(reg) self.bits) + } +} From 6f3fbdd87008d959677aee2ab93d736cb37587a1 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 00:22:48 +0800 Subject: [PATCH 05/13] to fix format issue --- src/builder/macros.rs | 2 +- src/builder/mod.rs | 1 - src/builder/mstatus.rs | 17 ++++++++--------- src/lib.rs | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/builder/macros.rs b/src/builder/macros.rs index be901a54..d1a2f65d 100644 --- a/src/builder/macros.rs +++ b/src/builder/macros.rs @@ -13,5 +13,5 @@ macro_rules! impl_set_bit { pub fn $field_setter(&mut self, value: bool) { self.$inner.$setter($idx, value); } - } + }; } diff --git a/src/builder/mod.rs b/src/builder/mod.rs index fd73432e..1e2e4bbf 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -2,4 +2,3 @@ mod macros; pub mod mstatus; - diff --git a/src/builder/mstatus.rs b/src/builder/mstatus.rs index d06fc492..4b6c2695 100644 --- a/src/builder/mstatus.rs +++ b/src/builder/mstatus.rs @@ -1,20 +1,20 @@ //! mstatus register builder +use crate::register::mstatus::*; use bit_field::BitField; -use core::mem::size_of; use core::arch::asm; -use crate::register::mstatus::*; +use core::mem::size_of; /// mstatus register builder pub struct MstatusBuilder { - bits: usize + bits: usize, } /// mstatus register value #[derive(Clone, Copy, Debug)] #[repr(transparent)] pub struct MstatusValue { - bits: usize + bits: usize, } macro_rules! impl_mstatus_writable { @@ -57,7 +57,7 @@ macro_rules! impl_mstatus_writable { FS::Dirty => self.bits.set_bits(13..15, 0b11), }; } - + #[inline] pub fn set_xs(&mut self, xs: XS) { match xs { @@ -79,9 +79,8 @@ macro_rules! impl_mstatus_writable { impl_set_bit!(set_tw, $inner, set_bit, 21); impl_set_bit!(set_tsr, $inner, set_bit, 22); - } - } + }; } macro_rules! impl_mstatus_readable { @@ -156,7 +155,7 @@ macro_rules! impl_mstatus_readable { self.$inner.get_bit(size_of::() * 8 - 1) } } - } + }; } impl_mstatus_readable!(MstatusBuilder, bits); @@ -164,7 +163,7 @@ impl_mstatus_writable!(MstatusBuilder, bits); impl MstatusBuilder { pub fn build(&self) -> MstatusValue { - return MstatusValue { bits: self.bits } + return MstatusValue { bits: self.bits }; } } diff --git a/src/lib.rs b/src/lib.rs index 834c7fd9..c171d5fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,10 +22,10 @@ extern crate bit_field; extern crate embedded_hal; pub mod asm; +pub mod builder; pub mod delay; pub mod interrupt; pub mod register; -pub mod builder; #[macro_use] mod macros; From 877fe45dde713dcd784fde7543cca1291351243d Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 00:29:37 +0800 Subject: [PATCH 06/13] to fix format issue --- src/builder/mstatus.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/builder/mstatus.rs b/src/builder/mstatus.rs index 4b6c2695..1667f30a 100644 --- a/src/builder/mstatus.rs +++ b/src/builder/mstatus.rs @@ -2,7 +2,6 @@ use crate::register::mstatus::*; use bit_field::BitField; -use core::arch::asm; use core::mem::size_of; /// mstatus register builder @@ -169,6 +168,7 @@ impl MstatusBuilder { impl MstatusValue { pub unsafe fn write_mstatus(&self) { - asm!("csrw mstatus, {0}", in(reg) self.bits) + #[cfg(all(riscv, feature = "inline-asm"))] + core::arch::asm!("csrw mstatus, {0}", in(reg) self.bits) } } From c60c46faf2306133788f44bac83547b900246f33 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 10:01:15 +0800 Subject: [PATCH 07/13] add builder for misa --- src/builder/mod.rs | 1 + src/builder/mstatus.rs | 27 +++++++++++++++++++++------ src/register/mstatus.rs | 7 +++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 1e2e4bbf..7641bf9d 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -1,4 +1,5 @@ #[macro_use] mod macros; +pub mod misa; pub mod mstatus; diff --git a/src/builder/mstatus.rs b/src/builder/mstatus.rs index 1667f30a..a7579ed7 100644 --- a/src/builder/mstatus.rs +++ b/src/builder/mstatus.rs @@ -6,14 +6,14 @@ use core::mem::size_of; /// mstatus register builder pub struct MstatusBuilder { - bits: usize, + pub(self) bits: usize, } /// mstatus register value #[derive(Clone, Copy, Debug)] #[repr(transparent)] pub struct MstatusValue { - bits: usize, + pub(self) bits: usize, } macro_rules! impl_mstatus_writable { @@ -161,14 +161,29 @@ impl_mstatus_readable!(MstatusBuilder, bits); impl_mstatus_writable!(MstatusBuilder, bits); impl MstatusBuilder { + pub fn bits(&self) -> usize { + self.bits + } + pub fn build(&self) -> MstatusValue { - return MstatusValue { bits: self.bits }; + MstatusValue { bits: self.bits } } } impl MstatusValue { - pub unsafe fn write_mstatus(&self) { - #[cfg(all(riscv, feature = "inline-asm"))] - core::arch::asm!("csrw mstatus, {0}", in(reg) self.bits) + pub fn bits(&self) -> usize { + self.bits + } +} + +impl From for MstatusBuilder { + fn from(value: MstatusValue) -> Self { + MstatusBuilder { bits: value.bits } + } +} + +impl From for MstatusValue { + fn from(value: MstatusBuilder) -> Self { + MstatusValue { bits: value.bits } } } diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 7c477335..6fe0a94e 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -8,6 +8,7 @@ // which would be the best way we implement this using Rust? use bit_field::BitField; +use builder::mstatus::MstatusValue; use core::mem::size_of; /// mstatus register @@ -275,3 +276,9 @@ pub unsafe fn set_fs(fs: FS) { value.set_bits(13..15, fs as usize); _write(value); } + +/// Write from value to register +#[inline] +pub unsafe fn write(value: MstatusValue) { + _write(value.bits()); +} From d05e6a75be0096b2c80d7fce1ae1d89d14dcb10e Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Fri, 4 Mar 2022 10:02:34 +0800 Subject: [PATCH 08/13] add builder for misa --- src/builder/misa.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/builder/misa.rs diff --git a/src/builder/misa.rs b/src/builder/misa.rs new file mode 100644 index 00000000..65530aef --- /dev/null +++ b/src/builder/misa.rs @@ -0,0 +1,75 @@ +//! misa builder + +use crate::register::misa::*; +use bit_field::BitField; + +/// mstatus register builder +pub struct MisaBuilder { + pub(self) bits: usize, +} + +/// mstatus register value +#[derive(Clone, Copy, Debug)] +pub struct MisaValue { + pub(self) bits: usize, +} + +impl MisaBuilder { + pub fn bits(&self) -> usize { + self.bits + } + + pub fn mxl(&self) -> MXL { + let value = match () { + #[cfg(target_pointer_width = "32")] + () => (self.bits() >> 30) as u8, + #[cfg(target_pointer_width = "64")] + () => (self.bits() >> 62) as u8, + }; + match value { + 1 => MXL::XLEN32, + 2 => MXL::XLEN64, + 3 => MXL::XLEN128, + _ => unreachable!(), + } + } + + pub fn set_mxl(&mut self, mxl: MXL) { + let value = match mxl { + MXL::XLEN32 => 1, + MXL::XLEN64 => 2, + MXL::XLEN128 => 3, + _ => unreachable!(), + }; + match () { + #[cfg(target_pointer_width = "32")] + () => self.bits.set_bits(30..32, value), + #[cfg(target_pointer_width = "64")] + () => self.bits.set_bits(62..64, value), + }; + } + + pub fn build(&self) -> MisaValue { + MisaValue { bits: self.bits } + } +} + +impl MisaValue { + pub fn bits(&self) -> usize { + self.bits + } +} + +impl From for MisaBuilder { + #[inline] + fn from(value: MisaValue) -> Self { + MisaBuilder { bits: value.bits() } + } +} + +impl From for MisaValue { + #[inline] + fn from(value: MisaBuilder) -> Self { + MisaValue { bits: value.bits() } + } +} From e66d716d76bf9236f2524a90d982c739d191a1a3 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Sat, 5 Mar 2022 11:43:31 +0800 Subject: [PATCH 09/13] add builder for & remove write in --- src/builder/misa.rs | 23 ++++++++--- src/builder/mod.rs | 1 + src/builder/mstatus.rs | 20 ++++++++-- src/builder/mtvec.rs | 84 +++++++++++++++++++++++++++++++++++++++++ src/register/mstatus.rs | 6 --- 5 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 src/builder/mtvec.rs diff --git a/src/builder/misa.rs b/src/builder/misa.rs index 65530aef..61e210bc 100644 --- a/src/builder/misa.rs +++ b/src/builder/misa.rs @@ -4,21 +4,34 @@ use crate::register::misa::*; use bit_field::BitField; /// mstatus register builder +#[derive(Clone, Copy, Debug)] pub struct MisaBuilder { - pub(self) bits: usize, + bits: usize, } /// mstatus register value #[derive(Clone, Copy, Debug)] pub struct MisaValue { - pub(self) bits: usize, + bits: usize, } impl MisaBuilder { + #[inline] + pub fn new() -> Self { + Self { bits: 0usize } + } + + #[inline] pub fn bits(&self) -> usize { self.bits } + #[inline] + pub fn build(&self) -> MisaValue { + MisaValue { bits: self.bits } + } + + #[inline] pub fn mxl(&self) -> MXL { let value = match () { #[cfg(target_pointer_width = "32")] @@ -34,6 +47,7 @@ impl MisaBuilder { } } + #[inline] pub fn set_mxl(&mut self, mxl: MXL) { let value = match mxl { MXL::XLEN32 => 1, @@ -48,13 +62,10 @@ impl MisaBuilder { () => self.bits.set_bits(62..64, value), }; } - - pub fn build(&self) -> MisaValue { - MisaValue { bits: self.bits } - } } impl MisaValue { + #[inline] pub fn bits(&self) -> usize { self.bits } diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 7641bf9d..e30b07e9 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -3,3 +3,4 @@ mod macros; pub mod misa; pub mod mstatus; +pub mod mtvec; diff --git a/src/builder/mstatus.rs b/src/builder/mstatus.rs index a7579ed7..9836fd5b 100644 --- a/src/builder/mstatus.rs +++ b/src/builder/mstatus.rs @@ -6,14 +6,14 @@ use core::mem::size_of; /// mstatus register builder pub struct MstatusBuilder { - pub(self) bits: usize, + bits: usize, } /// mstatus register value #[derive(Clone, Copy, Debug)] #[repr(transparent)] pub struct MstatusValue { - pub(self) bits: usize, + bits: usize, } macro_rules! impl_mstatus_writable { @@ -161,29 +161,41 @@ impl_mstatus_readable!(MstatusBuilder, bits); impl_mstatus_writable!(MstatusBuilder, bits); impl MstatusBuilder { + #[inline] + pub fn new() -> Self { + Self { bits: 0usize } + } + + #[inline] pub fn bits(&self) -> usize { self.bits } + #[inline] pub fn build(&self) -> MstatusValue { MstatusValue { bits: self.bits } } } +impl_mstatus_readable!(MstatusValue, bits); + impl MstatusValue { + #[inline] pub fn bits(&self) -> usize { self.bits } } impl From for MstatusBuilder { + #[inline] fn from(value: MstatusValue) -> Self { - MstatusBuilder { bits: value.bits } + MstatusBuilder { bits: value.bits() } } } impl From for MstatusValue { + #[inline] fn from(value: MstatusBuilder) -> Self { - MstatusValue { bits: value.bits } + MstatusValue { bits: value.bits() } } } diff --git a/src/builder/mtvec.rs b/src/builder/mtvec.rs new file mode 100644 index 00000000..48d9151d --- /dev/null +++ b/src/builder/mtvec.rs @@ -0,0 +1,84 @@ +//! mtvec builder + +use crate::register::mtvec::*; +use bit_field::BitField; + +/// mtvec register builder +#[derive(Clone, Copy, Debug)] +pub struct MtvecBuilder { + bits: usize, +} + +/// mtvec register value +#[derive(Clone, Copy, Debug)] +#[repr(transparent)] +pub struct MtvecValue { + bits: usize, +} + +impl MtvecBuilder { + #[inline] + pub fn new() -> Self { + Self { bits: 0usize } + } + + #[inline] + pub fn bits(&self) -> usize { + self.bits + } + + #[inline] + pub fn build(&self) -> MtvecValue { + MtvecValue { bits: self.bits() } + } + + #[inline] + pub fn address(&self) -> usize { + self.bits - (self.bits & 0b11) + } + + #[inline] + pub fn set_address(&mut self, value: usize) { + self.bits = value - (value & 0b11); + } + + #[inline] + pub fn trap_mode(&self) -> Option { + let mode = self.bits & 0b11; + match mode { + 0 => Some(TrapMode::Direct), + 1 => Some(TrapMode::Vectored), + _ => None, + } + } + + #[inline] + pub fn set_trap_mode(&mut self, mode: TrapMode) { + let mode_bits = match mode { + TrapMode::Direct => 0, + TrapMode::Vectored => 1, + }; + self.bits.set_bits(0..2, mode_bits); + } +} + +impl MtvecValue { + #[inline] + pub fn bits(&self) -> usize { + self.bits + } +} + +impl From for MtvecBuilder { + #[inline] + fn from(value: MtvecValue) -> Self { + MtvecBuilder { bits: value.bits() } + } +} + +impl From for MtvecValue { + #[inline] + fn from(value: MtvecBuilder) -> Self { + MtvecValue { bits: value.bits() } + } +} diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 6fe0a94e..65fb8091 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -276,9 +276,3 @@ pub unsafe fn set_fs(fs: FS) { value.set_bits(13..15, fs as usize); _write(value); } - -/// Write from value to register -#[inline] -pub unsafe fn write(value: MstatusValue) { - _write(value.bits()); -} From dd3f6595ec1f793b0b3e56fe1dd30cb83ecd3c6c Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Sat, 5 Mar 2022 12:13:09 +0800 Subject: [PATCH 10/13] add builder for mideleg & remove unnecessary import --- src/builder/mideleg.rs | 96 +++++++++++++++++++++++++++++++++++++++++ src/builder/misa.rs | 16 +++++++ src/builder/mod.rs | 1 + src/builder/mtvec.rs | 15 +++++++ src/register/mstatus.rs | 1 - 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/builder/mideleg.rs diff --git a/src/builder/mideleg.rs b/src/builder/mideleg.rs new file mode 100644 index 00000000..da7f59ae --- /dev/null +++ b/src/builder/mideleg.rs @@ -0,0 +1,96 @@ +//! mideleg builder + +use crate::register::mideleg::*; +use bit_field::BitField; + +/// mideleg builder +#[derive(Clone, Copy, Debug)] +pub struct MidelegBuilder { + bits: usize, +} + +/// mideleg builder +#[derive(Clone, Copy, Debug)] +#[repr(transparent)] +pub struct MidelegValue { + bits: usize, +} + +macro_rules! impl_mideleg_writable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_set_bit!(set_usoft, $inner, set_bit, 0); + + impl_set_bit!(set_ssoft, $inner, set_bit, 1); + + impl_set_bit!(set_utimer, $inner, set_bit, 4); + + impl_set_bit!(set_stimer, $inner, set_bit, 5); + + impl_set_bit!(set_uext, $inner, set_bit, 8); + + impl_set_bit!(set_sext, $inner, set_bit, 9); + } + } +} + +macro_rules! impl_mideleg_readable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_get_bit!(usoft, $inner, get_bit, 0); + + impl_get_bit!(ssoft, $inner, get_bit, 1); + + impl_get_bit!(utimer, $inner, get_bit, 4); + + impl_get_bit!(stimer, $inner, get_bit, 5); + + impl_get_bit!(uext, $inner, get_bit, 8); + + impl_get_bit!(sext, $inner, get_bit, 9); + } + } +} + +impl_mideleg_readable!(MidelegBuilder, bits); +impl_mideleg_writable!(MidelegBuilder, bits); + +impl MidelegBuilder { + #[inline] + pub fn new() -> Self { + Self { bits: 0usize } + } + + #[inline] + pub fn bits(&self) -> usize { + self.bits + } + + #[inline] + pub fn build(&self) -> MidelegValue { + MidelegValue { bits: self.bits } + } +} + +impl_mideleg_readable!(MidelegValue, bits); + +impl MidelegValue { + #[inline] + pub fn bits(&self) -> usize { + self.bits + } +} + +impl From for MidelegBuilder { + #[inline] + fn from(value: MidelegValue) -> Self { + MidelegBuilder { bits: value.bits() } + } +} + +impl From for MidelegValue { + #[inline] + fn from(value: MidelegBuilder) -> Self { + MidelegValue { bits: value.bits() } + } +} diff --git a/src/builder/misa.rs b/src/builder/misa.rs index 61e210bc..3d8960d0 100644 --- a/src/builder/misa.rs +++ b/src/builder/misa.rs @@ -69,6 +69,22 @@ impl MisaValue { pub fn bits(&self) -> usize { self.bits } + + #[inline] + pub fn mxl(&self) -> MXL { + let value = match () { + #[cfg(target_pointer_width = "32")] + () => (self.bits() >> 30) as u8, + #[cfg(target_pointer_width = "64")] + () => (self.bits() >> 62) as u8, + }; + match value { + 1 => MXL::XLEN32, + 2 => MXL::XLEN64, + 3 => MXL::XLEN128, + _ => unreachable!(), + } + } } impl From for MisaBuilder { diff --git a/src/builder/mod.rs b/src/builder/mod.rs index e30b07e9..ddaf2ee1 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -4,3 +4,4 @@ mod macros; pub mod misa; pub mod mstatus; pub mod mtvec; +pub mod mideleg; diff --git a/src/builder/mtvec.rs b/src/builder/mtvec.rs index 48d9151d..740124e9 100644 --- a/src/builder/mtvec.rs +++ b/src/builder/mtvec.rs @@ -67,6 +67,21 @@ impl MtvecValue { pub fn bits(&self) -> usize { self.bits } + + #[inline] + pub fn address(&self) -> usize { + self.bits - (self.bits & 0b11) + } + + #[inline] + pub fn trap_mode(&self) -> Option { + let mode = self.bits & 0b11; + match mode { + 0 => Some(TrapMode::Direct), + 1 => Some(TrapMode::Vectored), + _ => None, + } + } } impl From for MtvecBuilder { diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index 65fb8091..7c477335 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -8,7 +8,6 @@ // which would be the best way we implement this using Rust? use bit_field::BitField; -use builder::mstatus::MstatusValue; use core::mem::size_of; /// mstatus register From 7b393f09162cde718c9c5bc904c490ff21c6cc67 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Sat, 5 Mar 2022 12:14:44 +0800 Subject: [PATCH 11/13] cargo fmt --- src/builder/mideleg.rs | 4 ++-- src/builder/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builder/mideleg.rs b/src/builder/mideleg.rs index da7f59ae..1f873475 100644 --- a/src/builder/mideleg.rs +++ b/src/builder/mideleg.rs @@ -31,7 +31,7 @@ macro_rules! impl_mideleg_writable { impl_set_bit!(set_sext, $inner, set_bit, 9); } - } + }; } macro_rules! impl_mideleg_readable { @@ -49,7 +49,7 @@ macro_rules! impl_mideleg_readable { impl_get_bit!(sext, $inner, get_bit, 9); } - } + }; } impl_mideleg_readable!(MidelegBuilder, bits); diff --git a/src/builder/mod.rs b/src/builder/mod.rs index ddaf2ee1..701800c6 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -1,7 +1,7 @@ #[macro_use] mod macros; +pub mod mideleg; pub mod misa; pub mod mstatus; pub mod mtvec; -pub mod mideleg; From ce6082db7cafff8ecabd9f0c9156413a4de80680 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Sun, 6 Mar 2022 11:01:57 +0800 Subject: [PATCH 12/13] add builder for --- src/builder/medeleg.rs | 128 +++++++++++++++++++++++++++++++++++++++++ src/builder/mod.rs | 1 + 2 files changed, 129 insertions(+) create mode 100644 src/builder/medeleg.rs diff --git a/src/builder/medeleg.rs b/src/builder/medeleg.rs new file mode 100644 index 00000000..071d5a25 --- /dev/null +++ b/src/builder/medeleg.rs @@ -0,0 +1,128 @@ +//! medeleg register builder + +use crate::register::medeleg::*; +use bit_field::BitField; +use core::mem::size_of; + +/// medeleg register builder +pub struct MedelegBuilder { + bits: usize, +} + +/// medeleg register value +#[derive(Clone, Copy, Debug)] +#[repr(transparent)] +pub struct MedelegValue { + bits: usize, +} + +macro_rules! impl_medeleg_writable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_set_bit!(set_instruction_misaligned, $inner, set_bit, 0); + + impl_set_bit!(set_instruction_fault, $inner, set_bit, 1); + + impl_set_bit!(set_illegal_instruction, $inner, set_bit, 2); + + impl_set_bit!(set_breakpoint, $inner, set_bit, 3); + + impl_set_bit!(set_load_misaligned, $inner, set_bit, 4); + + impl_set_bit!(set_load_fault, $inner, set_bit, 5); + + impl_set_bit!(set_store_misaligned, $inner, set_bit, 6); + + impl_set_bit!(set_store_fault, $inner, set_bit, 7); + + impl_set_bit!(set_user_env_call, $inner, set_bit, 8); + + impl_set_bit!(set_supervisor_env_call, $inner, set_bit, 9); + + impl_set_bit!(set_machine_env_call, $inner, set_bit, 11); + + impl_set_bit!(set_instruction_page_fault, $inner, set_bit, 12); + + impl_set_bit!(set_load_page_fault, $inner, set_bit, 13); + + impl_set_bit!(set_store_page_fault, $inner, set_bit, 15); + } + } +} + +macro_rules! impl_medeleg_readable { + ($type_name: ident, $inner: ident) => { + impl $type_name { + impl_get_bit!(instruction_misaligned, $inner, get_bit, 0); + + impl_get_bit!(instruction_fault, $inner, get_bit, 1); + + impl_get_bit!(illegal_instruction, $inner, get_bit, 2); + + impl_get_bit!(breakpoint, $inner, get_bit, 3); + + impl_get_bit!(load_misaligned, $inner, get_bit, 4); + + impl_get_bit!(load_fault, $inner, get_bit, 5); + + impl_get_bit!(store_misaligned, $inner, get_bit, 6); + + impl_get_bit!(store_fault, $inner, get_bit, 7); + + impl_get_bit!(user_env_call, $inner, get_bit, 8); + + impl_get_bit!(supervisor_env_call, $inner, get_bit, 9); + + impl_get_bit!(machine_env_call, $inner, get_bit, 11); + + impl_get_bit!(instruction_page_fault, $inner, get_bit, 12); + + impl_get_bit!(load_page_fault, $inner, get_bit, 13); + + impl_get_bit!(store_page_fault, $inner, get_bit, 15); + } + } +} + +impl_medeleg_writable!(MedelegBuilder, bits); +impl_medeleg_readable!(MedelegBuilder, bits); + +impl MedelegBuilder { + #[inline] + pub fn new() -> Self { + Self { bits: 0usize } + } + + #[inline] + pub fn bits(&self) -> usize { + self.bits + } + + #[inline] + pub fn build(&self) -> MedelegValue { + MedelegValue { bits: self.bits } + } +} + +impl_medeleg_readable!(MedelegValue, bits); + +impl MedelegValue { + #[inline] + pub fn bits(&self) -> usize { + self.bits + } +} + +impl From for MedelegBuilder { + #[inline] + fn from(value: MedelegValue) -> Self { + MedelegBuilder { bits: value.bits() } + } +} + +impl From for MedelegValue { + #[inline] + fn from(value: MedelegBuilder) -> Self { + MedelegValue { bits: value.bits() } + } +} diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 701800c6..e35f67ba 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -5,3 +5,4 @@ pub mod mideleg; pub mod misa; pub mod mstatus; pub mod mtvec; +pub mod medeleg; From edda449902c6c5b49a0568f863e7fb4ad53db812 Mon Sep 17 00:00:00 2001 From: jwnhy <799433746@qq.com> Date: Sun, 6 Mar 2022 17:18:07 +0800 Subject: [PATCH 13/13] cargo fmt --- src/builder/medeleg.rs | 10 +++++----- src/builder/mod.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/builder/medeleg.rs b/src/builder/medeleg.rs index 071d5a25..3cabec6f 100644 --- a/src/builder/medeleg.rs +++ b/src/builder/medeleg.rs @@ -46,8 +46,8 @@ macro_rules! impl_medeleg_writable { impl_set_bit!(set_load_page_fault, $inner, set_bit, 13); impl_set_bit!(set_store_page_fault, $inner, set_bit, 15); - } - } + } + }; } macro_rules! impl_medeleg_readable { @@ -80,8 +80,8 @@ macro_rules! impl_medeleg_readable { impl_get_bit!(load_page_fault, $inner, get_bit, 13); impl_get_bit!(store_page_fault, $inner, get_bit, 15); - } - } + } + }; } impl_medeleg_writable!(MedelegBuilder, bits); @@ -100,7 +100,7 @@ impl MedelegBuilder { #[inline] pub fn build(&self) -> MedelegValue { - MedelegValue { bits: self.bits } + MedelegValue { bits: self.bits } } } diff --git a/src/builder/mod.rs b/src/builder/mod.rs index e35f67ba..419c2827 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -1,8 +1,8 @@ #[macro_use] mod macros; +pub mod medeleg; pub mod mideleg; pub mod misa; pub mod mstatus; pub mod mtvec; -pub mod medeleg;