1
1
//! mstatus register
2
2
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 ;
9
4
10
5
/// mstatus register
11
6
#[ derive( Clone , Copy , Debug ) ]
@@ -53,13 +48,23 @@ pub enum SPP {
53
48
User = 0 ,
54
49
}
55
50
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
+ }
61
64
}
65
+ }
62
66
67
+ impl Mstatus {
63
68
/// Supervisor Interrupt Enable
64
69
#[ inline]
65
70
pub fn sie ( & self ) -> bool {
@@ -72,18 +77,18 @@ impl Mstatus {
72
77
self . bits & ( 1 << 3 ) != 0
73
78
}
74
79
75
- /// User Previous Interrupt Enable
76
- #[ inline]
77
- pub fn upie ( & self ) -> bool {
78
- self . bits & ( 1 << 4 ) != 0
79
- }
80
-
81
80
/// Supervisor Previous Interrupt Enable
82
81
#[ inline]
83
82
pub fn spie ( & self ) -> bool {
84
83
self . bits & ( 1 << 5 ) != 0
85
84
}
86
85
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
+
87
92
/// Machine Previous Interrupt Enable
88
93
#[ inline]
89
94
pub fn mpie ( & self ) -> bool {
@@ -196,13 +201,57 @@ impl Mstatus {
196
201
self . bits & ( 1 << 22 ) != 0
197
202
}
198
203
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
+ }
203
216
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
206
255
#[ inline]
207
256
pub fn sd ( & self ) -> bool {
208
257
self . bits & ( 1 << ( usize:: BITS as usize - 1 ) ) != 0
@@ -251,6 +300,15 @@ set_clear_csr!(
251
300
/// Trap SRET
252
301
, set_tsr, clear_tsr, 1 << 22 ) ;
253
302
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
+
254
312
/// Supervisor Previous Privilege Mode
255
313
#[ inline]
256
314
pub unsafe fn set_spp ( spp : SPP ) {
@@ -277,3 +335,39 @@ pub unsafe fn set_fs(fs: FS) {
277
335
value |= ( fs as usize ) << 13 ;
278
336
_write ( value) ;
279
337
}
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