Skip to content

Commit abdce51

Browse files
Merge pull request #266 from rmsyn/riscv/sstatus-csr-macro
riscv: define `sstatus` CSR with macro helpers
2 parents f463f22 + 494ab90 commit abdce51

File tree

2 files changed

+125
-71
lines changed

2 files changed

+125
-71
lines changed

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3737
- Use CSR helper macros to define `sie` register
3838
- Use CSR helper macros to define `scounteren` field types
3939
- Use CSR helper macros to define `sip` register
40+
- Use CSR helper macros to define `sstatus` field types
4041

4142
## [v0.12.1] - 2024-10-20
4243

riscv/src/register/sstatus.rs

Lines changed: 124 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,111 @@
11
//! sstatus register
22
33
pub use super::misa::XLEN;
4-
pub use super::mstatus::FS;
4+
pub use super::mstatus::{FS, XS};
55

6-
/// Supervisor Status Register
7-
#[derive(Clone, Copy, Debug)]
8-
pub struct Sstatus {
9-
bits: usize,
6+
#[cfg(target_arch = "riscv32")]
7+
const MASK: usize = 0x800d_e122;
8+
#[cfg(not(target_arch = "riscv32"))]
9+
const MASK: usize = 0x8000_0003_000d_e122;
10+
11+
read_write_csr! {
12+
/// Supervisor Status Register
13+
Sstatus: 0x100,
14+
mask: MASK,
1015
}
1116

12-
/// Supervisor Previous Privilege Mode
13-
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14-
pub enum SPP {
15-
Supervisor = 1,
16-
User = 0,
17+
csr_field_enum! {
18+
/// Supervisor Previous Privilege Mode
19+
SPP {
20+
default: User,
21+
/// Previous privilege mode is User mode.
22+
User = 0,
23+
/// Previous privilege mode is Supervisor mode.
24+
Supervisor = 1,
25+
}
1726
}
1827

19-
impl Sstatus {
28+
read_write_csr_field! {
29+
Sstatus,
2030
/// Supervisor Interrupt Enable
21-
#[inline]
22-
pub fn sie(&self) -> bool {
23-
self.bits & (1 << 1) != 0
24-
}
31+
sie: 1,
32+
}
2533

34+
read_write_csr_field! {
35+
Sstatus,
2636
/// Supervisor Previous Interrupt Enable
27-
#[inline]
28-
pub fn spie(&self) -> bool {
29-
self.bits & (1 << 5) != 0
30-
}
37+
spie: 5,
38+
}
3139

40+
read_write_csr_field! {
41+
Sstatus,
3242
/// Supervisor Previous Privilege Mode
33-
#[inline]
34-
pub fn spp(&self) -> SPP {
35-
match self.bits & (1 << 8) != 0 {
36-
true => SPP::Supervisor,
37-
false => SPP::User,
38-
}
39-
}
43+
spp,
44+
SPP: [8:8],
45+
}
4046

47+
read_write_csr_field! {
48+
Sstatus,
4149
/// The status of the floating-point unit
42-
#[inline]
43-
pub fn fs(&self) -> FS {
44-
let fs = (self.bits >> 13) & 0x3; // bits 13-14
45-
match fs {
46-
0 => FS::Off,
47-
1 => FS::Initial,
48-
2 => FS::Clean,
49-
3 => FS::Dirty,
50-
_ => unreachable!(),
51-
}
52-
}
50+
fs,
51+
FS: [13:14],
52+
}
5353

54+
read_only_csr_field! {
55+
Sstatus,
5456
/// The status of additional user-mode extensions
5557
/// and associated state
56-
#[inline]
57-
pub fn xs(&self) -> FS {
58-
let xs = (self.bits >> 15) & 0x3; // bits 15-16
59-
match xs {
60-
0 => FS::Off,
61-
1 => FS::Initial,
62-
2 => FS::Clean,
63-
3 => FS::Dirty,
64-
_ => unreachable!(),
65-
}
66-
}
58+
xs,
59+
XS: [15:16],
60+
}
6761

62+
read_write_csr_field! {
63+
Sstatus,
6864
/// Permit Supervisor User Memory access
69-
#[inline]
70-
pub fn sum(&self) -> bool {
71-
self.bits & (1 << 18) != 0
72-
}
65+
sum: 18,
66+
}
7367

68+
read_write_csr_field! {
69+
Sstatus,
7470
/// Make eXecutable Readable
75-
#[inline]
76-
pub fn mxr(&self) -> bool {
77-
self.bits & (1 << 19) != 0
78-
}
71+
mxr: 19,
72+
}
7973

74+
#[cfg(not(target_arch = "riscv32"))]
75+
read_write_csr_field! {
76+
Sstatus,
8077
/// Effective xlen in U-mode (i.e., `UXLEN`).
81-
///
82-
/// In RISCV-32, UXL does not exist, and `UXLEN` is always [`XLEN::XLEN32`].
83-
#[inline]
84-
pub fn uxl(&self) -> XLEN {
85-
match () {
86-
#[cfg(riscv32)]
87-
() => XLEN::XLEN32,
88-
#[cfg(not(riscv32))]
89-
() => XLEN::try_from((self.bits >> 32) & 0x3).unwrap_or_default(),
90-
}
91-
}
78+
uxl,
79+
XLEN: [32:33],
80+
}
9281

82+
#[cfg(target_arch = "riscv32")]
83+
read_write_csr_field! {
84+
Sstatus,
9385
/// Whether either the FS field or XS field
9486
/// signals the presence of some dirty state
87+
sd: 31,
88+
}
89+
90+
#[cfg(not(target_arch = "riscv32"))]
91+
read_write_csr_field! {
92+
Sstatus,
93+
/// Whether either the FS field or XS field
94+
/// signals the presence of some dirty state
95+
sd: 63,
96+
}
97+
98+
impl Sstatus {
99+
/// Effective xlen in U-mode (i.e., `UXLEN`).
100+
///
101+
/// In RISCV-32, UXL does not exist, and `UXLEN` is always [`XLEN::XLEN32`].
95102
#[inline]
96-
pub fn sd(&self) -> bool {
97-
self.bits & (1 << (usize::BITS as usize - 1)) != 0
103+
#[cfg(target_arch = "riscv32")]
104+
pub fn uxl(&self) -> XLEN {
105+
XLEN::XLEN32
98106
}
99107
}
100108

101-
read_csr_as!(Sstatus, 0x100);
102-
write_csr!(0x100);
103109
set!(0x100);
104110
clear!(0x100);
105111

@@ -139,3 +145,50 @@ pub unsafe fn set_fs(fs: FS) {
139145
value |= (fs as usize) << 13;
140146
_write(value);
141147
}
148+
149+
#[cfg(test)]
150+
mod tests {
151+
use super::*;
152+
153+
#[test]
154+
fn test_sstatus() {
155+
let mut sstatus = Sstatus::from_bits(0);
156+
157+
test_csr_field!(sstatus, sie);
158+
test_csr_field!(sstatus, spie);
159+
160+
[SPP::User, SPP::Supervisor].into_iter().for_each(|spp| {
161+
test_csr_field!(sstatus, spp: spp);
162+
});
163+
164+
[FS::Off, FS::Initial, FS::Clean, FS::Dirty]
165+
.into_iter()
166+
.for_each(|fs| {
167+
test_csr_field!(sstatus, fs: fs);
168+
});
169+
170+
[
171+
XS::AllOff,
172+
XS::NoneDirtyOrClean,
173+
XS::NoneDirtySomeClean,
174+
XS::SomeDirty,
175+
]
176+
.into_iter()
177+
.for_each(|xs| {
178+
let sstatus = Sstatus::from_bits(xs.into_usize() << 15);
179+
assert_eq!(sstatus.xs(), xs);
180+
assert_eq!(sstatus.try_xs(), Ok(xs));
181+
});
182+
183+
test_csr_field!(sstatus, sum);
184+
test_csr_field!(sstatus, mxr);
185+
186+
[XLEN::XLEN32, XLEN::XLEN64, XLEN::XLEN128]
187+
.into_iter()
188+
.for_each(|xlen| {
189+
test_csr_field!(sstatus, uxl: xlen);
190+
});
191+
192+
test_csr_field!(sstatus, sd);
193+
}
194+
}

0 commit comments

Comments
 (0)