11//! mstatus register
22
3- // FIXME: in 1.12 spec there will be `SBE` and `MBE` bits.
4- // They allows to execute supervisor in given big endian,
5- // they would be in a new register `mstatush` in RV32; we should implement `mstatush`
6- // at that time.
7- // FIXME: `SXL` and `UXL` bits require a structure interpreting XLEN,
8- // which would be the best way we implement this using Rust?
3+ pub use super :: misa:: XLEN ;
94
105/// mstatus register
116#[ derive( Clone , Copy , Debug ) ]
@@ -53,13 +48,23 @@ pub enum SPP {
5348 User = 0 ,
5449}
5550
56- impl Mstatus {
57- /// User Interrupt Enable
58- #[ inline]
59- pub fn uie ( & self ) -> bool {
60- self . bits & ( 1 << 0 ) != 0
51+ /// Non-instruction-fetch memory endianness
52+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
53+ pub enum Endianness {
54+ BigEndian = 1 ,
55+ LittleEndian = 0 ,
56+ }
57+
58+ impl From < bool > for Endianness {
59+ fn from ( value : bool ) -> Self {
60+ match value {
61+ true => Self :: BigEndian ,
62+ false => Self :: LittleEndian ,
63+ }
6164 }
65+ }
6266
67+ impl Mstatus {
6368 /// Supervisor Interrupt Enable
6469 #[ inline]
6570 pub fn sie ( & self ) -> bool {
@@ -72,18 +77,18 @@ impl Mstatus {
7277 self . bits & ( 1 << 3 ) != 0
7378 }
7479
75- /// User Previous Interrupt Enable
76- #[ inline]
77- pub fn upie ( & self ) -> bool {
78- self . bits & ( 1 << 4 ) != 0
79- }
80-
8180 /// Supervisor Previous Interrupt Enable
8281 #[ inline]
8382 pub fn spie ( & self ) -> bool {
8483 self . bits & ( 1 << 5 ) != 0
8584 }
8685
86+ /// U-mode non-instruction-fetch memory endianness
87+ #[ inline]
88+ pub fn ube ( & self ) -> Endianness {
89+ Endianness :: from ( self . bits & ( 1 << 6 ) != 0 )
90+ }
91+
8792 /// Machine Previous Interrupt Enable
8893 #[ inline]
8994 pub fn mpie ( & self ) -> bool {
@@ -196,13 +201,57 @@ impl Mstatus {
196201 self . bits & ( 1 << 22 ) != 0
197202 }
198203
199- /*
200- FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12
201- is ratified, there should be read functions of these bits as well.
202- */
204+ /// Effective xlen in U-mode (i.e., `UXLEN`).
205+ ///
206+ /// In RISCV-32, UXL does not exist, and `UXLEN` is always [`XLEN::XLEN32`].
207+ #[ inline]
208+ pub fn uxl ( & self ) -> XLEN {
209+ match ( ) {
210+ #[ cfg( riscv32) ]
211+ ( ) => XLEN :: XLEN32 ,
212+ #[ cfg( not( riscv32) ) ]
213+ ( ) => XLEN :: from ( ( self . bits ( ) >> 32 ) as u8 & 0x3 ) ,
214+ }
215+ }
203216
204- /// Whether either the FS field or XS field
205- /// signals the presence of some dirty state
217+ /// Effective xlen in S-mode (i.e., `SXLEN`).
218+ ///
219+ /// In RISCV-32, SXL does not exist, and SXLEN is always [`XLEN::XLEN32`].
220+ #[ inline]
221+ pub fn sxl ( & self ) -> XLEN {
222+ match ( ) {
223+ #[ cfg( riscv32) ]
224+ ( ) => XLEN :: XLEN32 ,
225+ #[ cfg( not( riscv32) ) ]
226+ ( ) => XLEN :: from ( ( self . bits ( ) >> 34 ) as u8 & 0x3 ) ,
227+ }
228+ }
229+
230+ /// S-mode non-instruction-fetch memory endianness.
231+ ///
232+ /// In RISCV-32, this field is read from the [`crate::register::mstatush`] register.
233+ pub fn sbe ( & self ) -> Endianness {
234+ match ( ) {
235+ #[ cfg( riscv32) ]
236+ ( ) => super :: mstatush:: read ( ) . sbe ( ) ,
237+ #[ cfg( not( riscv32) ) ]
238+ ( ) => Endianness :: from ( self . bits & ( 1 << 36 ) != 0 ) ,
239+ }
240+ }
241+
242+ /// M-mode non-instruction-fetch memory endianness
243+ ///
244+ /// In RISCV-32, this field is read from the [`crate::register::mstatush`] register
245+ pub fn mbe ( & self ) -> Endianness {
246+ match ( ) {
247+ #[ cfg( riscv32) ]
248+ ( ) => super :: mstatush:: read ( ) . mbe ( ) ,
249+ #[ cfg( not( riscv32) ) ]
250+ ( ) => Endianness :: from ( self . bits & ( 1 << 37 ) != 0 ) ,
251+ }
252+ }
253+
254+ /// Whether either the FS field or XS field signals the presence of some dirty state
206255 #[ inline]
207256 pub fn sd ( & self ) -> bool {
208257 self . bits & ( 1 << ( usize:: BITS as usize - 1 ) ) != 0
@@ -251,6 +300,15 @@ set_clear_csr!(
251300 /// Trap SRET
252301 , set_tsr, clear_tsr, 1 << 22 ) ;
253302
303+ /// Set U-mode non-instruction-fetch memory endianness
304+ #[ inline]
305+ pub unsafe fn set_ube ( endianness : Endianness ) {
306+ match endianness {
307+ Endianness :: BigEndian => _set ( 1 << 6 ) ,
308+ Endianness :: LittleEndian => _clear ( 1 << 6 ) ,
309+ }
310+ }
311+
254312/// Supervisor Previous Privilege Mode
255313#[ inline]
256314pub unsafe fn set_spp ( spp : SPP ) {
@@ -277,3 +335,39 @@ pub unsafe fn set_fs(fs: FS) {
277335 value |= ( fs as usize ) << 13 ;
278336 _write ( value) ;
279337}
338+
339+ /// Set S-mode non-instruction-fetch memory endianness
340+ ///
341+ /// # Note
342+ ///
343+ /// In RISCV-32, this function calls [`crate::register::mstatush::set_sbe`]
344+ #[ inline]
345+ pub unsafe fn set_sbe ( endianness : Endianness ) {
346+ match ( ) {
347+ #[ cfg( riscv32) ]
348+ ( ) => super :: mstatush:: set_sbe ( endianness) ,
349+ #[ cfg( not( riscv32) ) ]
350+ ( ) => match endianness {
351+ Endianness :: BigEndian => _set ( 1 << 36 ) ,
352+ Endianness :: LittleEndian => _clear ( 1 << 36 ) ,
353+ } ,
354+ }
355+ }
356+
357+ /// Set M-mode non-instruction-fetch memory endianness
358+ ///
359+ /// # Note
360+ ///
361+ /// In RISCV-32, this function calls [`crate::register::mstatush::set_mbe`]
362+ #[ inline]
363+ pub unsafe fn set_mbe ( endianness : Endianness ) {
364+ match ( ) {
365+ #[ cfg( riscv32) ]
366+ ( ) => super :: mstatush:: set_mbe ( endianness) ,
367+ #[ cfg( not( riscv32) ) ]
368+ ( ) => match endianness {
369+ Endianness :: BigEndian => _set ( 1 << 37 ) ,
370+ Endianness :: LittleEndian => _clear ( 1 << 37 ) ,
371+ } ,
372+ }
373+ }
0 commit comments