Skip to content

Commit f968990

Browse files
committed
Add bitfield helpers and use them in mstatus
1 parent 8de908c commit f968990

File tree

3 files changed

+46
-22
lines changed

3 files changed

+46
-22
lines changed

riscv/src/bits.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// Insert a new value into a bitfield
2+
///
3+
/// `value` is masked to `width` bits and inserted into `orig`.`
4+
#[inline]
5+
pub fn bf_insert(orig: usize, bit: usize, width: usize, value: usize) -> usize {
6+
let mask = (1 << width) - 1;
7+
orig & !(mask << bit) | ((value & mask) << bit)
8+
}
9+
10+
/// Extract a value from a bitfield
11+
///
12+
/// Extracts `width` bits from bit offset `bit` and returns it shifted to bit 0.s
13+
#[inline]
14+
pub fn bf_extract(orig: usize, bit: usize, width: usize) -> usize {
15+
let mask = (1 << width) - 1;
16+
(orig >> bit) & mask
17+
}

riscv/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#![allow(clippy::missing_safety_doc)]
3737

3838
pub mod asm;
39+
pub(crate) mod bits;
3940
pub mod delay;
4041
pub mod interrupt;
4142
pub mod register;

riscv/src/register/mstatus.rs

+28-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! mstatus register
22
33
pub use super::misa::XLEN;
4+
use crate::bits::{bf_extract, bf_insert};
45

56
/// mstatus register
67
#[derive(Clone, Copy, Debug)]
@@ -75,12 +76,17 @@ impl Mstatus {
7576
/// Helper to insert a bitfield into Mstatus
7677
#[inline]
7778
fn bf_insert(&self, bit: usize, width: usize, val: usize) -> Self {
78-
let mask = (1 << width) - 1;
7979
Self {
80-
bits: self.bits & !(mask << bit) | ((val & mask) << bit),
80+
bits: bf_insert(self.bits, bit, width, val),
8181
}
8282
}
8383

84+
/// Helper to extract a bitfield from Mstatus
85+
#[inline]
86+
fn bf_extract(&self, bit: usize, width: usize) -> usize {
87+
bf_extract(self.bits, bit, width)
88+
}
89+
8490
/// Returns the contents of the register as raw bits
8591
#[inline]
8692
pub fn bits(&self) -> usize {
@@ -90,7 +96,7 @@ impl Mstatus {
9096
/// Supervisor Interrupt Enable
9197
#[inline]
9298
pub fn sie(&self) -> bool {
93-
self.bits & (1 << 1) != 0
99+
self.bf_extract(1, 1) != 0
94100
}
95101

96102
/// Update Supervisor Interrupt Enable
@@ -106,7 +112,7 @@ impl Mstatus {
106112
/// Machine Interrupt Enable
107113
#[inline]
108114
pub fn mie(&self) -> bool {
109-
self.bits & (1 << 3) != 0
115+
self.bf_extract(3, 1) != 0
110116
}
111117

112118
/// Update Machine Interrupt Enable
@@ -122,7 +128,7 @@ impl Mstatus {
122128
/// Supervisor Previous Interrupt Enable
123129
#[inline]
124130
pub fn spie(&self) -> bool {
125-
self.bits & (1 << 5) != 0
131+
self.bf_extract(5, 1) != 0
126132
}
127133

128134
/// Update Supervisor Previous Interrupt Enable
@@ -138,7 +144,7 @@ impl Mstatus {
138144
/// U-mode non-instruction-fetch memory endianness
139145
#[inline]
140146
pub fn ube(&self) -> Endianness {
141-
Endianness::from(self.bits & (1 << 6) != 0)
147+
Endianness::from(self.bf_extract(6, 1) != 0)
142148
}
143149

144150
/// Update U-mode non-instruction-fetch memory endianness
@@ -154,7 +160,7 @@ impl Mstatus {
154160
/// Machine Previous Interrupt Enable
155161
#[inline]
156162
pub fn mpie(&self) -> bool {
157-
self.bits & (1 << 7) != 0
163+
self.bf_extract(7, 1) != 0
158164
}
159165

160166
/// Update Machine Previous Interrupt Enable
@@ -170,7 +176,7 @@ impl Mstatus {
170176
/// Supervisor Previous Privilege Mode
171177
#[inline]
172178
pub fn spp(&self) -> SPP {
173-
match self.bits & (1 << 8) != 0 {
179+
match self.bf_extract(7, 1) != 0 {
174180
true => SPP::Supervisor,
175181
false => SPP::User,
176182
}
@@ -189,7 +195,7 @@ impl Mstatus {
189195
/// Machine Previous Privilege Mode
190196
#[inline]
191197
pub fn mpp(&self) -> MPP {
192-
let mpp = (self.bits >> 11) & 0x3; // bits 11-12
198+
let mpp = self.bf_extract(11, 2); // bits 11-12
193199
match mpp {
194200
0b00 => MPP::User,
195201
0b01 => MPP::Supervisor,
@@ -214,7 +220,7 @@ impl Mstatus {
214220
/// and floating-point data registers `f0–f31`.
215221
#[inline]
216222
pub fn fs(&self) -> FS {
217-
let fs = (self.bits >> 13) & 0x3; // bits 13-14
223+
let fs = self.bf_extract(13, 2); // bits 13-14
218224
match fs {
219225
0b00 => FS::Off,
220226
0b01 => FS::Initial,
@@ -240,7 +246,7 @@ impl Mstatus {
240246
/// state.
241247
#[inline]
242248
pub fn xs(&self) -> XS {
243-
let xs = (self.bits >> 15) & 0x3; // bits 15-16
249+
let xs = self.bf_extract(15, 2); // bits 15-16
244250
match xs {
245251
0b00 => XS::AllOff,
246252
0b01 => XS::NoneDirtyOrClean,
@@ -262,7 +268,7 @@ impl Mstatus {
262268
/// Modify Memory PRiVilege
263269
#[inline]
264270
pub fn mprv(&self) -> bool {
265-
self.bits & (1 << 17) != 0
271+
self.bf_extract(17, 1) != 0
266272
}
267273

268274
/// Update Modify Memory PRiVilege
@@ -278,7 +284,7 @@ impl Mstatus {
278284
/// Permit Supervisor User Memory access
279285
#[inline]
280286
pub fn sum(&self) -> bool {
281-
self.bits & (1 << 18) != 0
287+
self.bf_extract(18, 1) != 0
282288
}
283289

284290
/// Update Permit Supervisor User Memory access
@@ -294,7 +300,7 @@ impl Mstatus {
294300
/// Make eXecutable Readable
295301
#[inline]
296302
pub fn mxr(&self) -> bool {
297-
self.bits & (1 << 19) != 0
303+
self.bf_extract(19, 1) != 0
298304
}
299305

300306
/// Update Make eXecutable Readable
@@ -315,7 +321,7 @@ impl Mstatus {
315321
/// TVM is hard-wired to 0 when S-mode is not supported.
316322
#[inline]
317323
pub fn tvm(&self) -> bool {
318-
self.bits & (1 << 20) != 0
324+
self.bf_extract(20, 1) != 0
319325
}
320326

321327
/// Update Trap Virtual Memory
@@ -339,7 +345,7 @@ impl Mstatus {
339345
/// TW is hard-wired to 0 when S-mode is not supported.
340346
#[inline]
341347
pub fn tw(&self) -> bool {
342-
self.bits & (1 << 21) != 0
348+
self.bf_extract(21, 1) != 0
343349
}
344350

345351
/// Update Timeout Wait
@@ -360,7 +366,7 @@ impl Mstatus {
360366
/// If S-mode is not supported, TSR bit is hard-wired to 0.
361367
#[inline]
362368
pub fn tsr(&self) -> bool {
363-
self.bits & (1 << 22) != 0
369+
self.bf_extract(22, 1) != 0
364370
}
365371

366372
/// Update Trap SRET
@@ -382,7 +388,7 @@ impl Mstatus {
382388
#[cfg(riscv32)]
383389
() => XLEN::XLEN32,
384390
#[cfg(not(riscv32))]
385-
() => XLEN::from((self.bits >> 32) as u8 & 0x3),
391+
() => XLEN::from(self.bf_extract(32, 2) as u8),
386392
}
387393
}
388394

@@ -409,7 +415,7 @@ impl Mstatus {
409415
#[cfg(riscv32)]
410416
() => XLEN::XLEN32,
411417
#[cfg(not(riscv32))]
412-
() => XLEN::from((self.bits >> 34) as u8 & 0x3),
418+
() => XLEN::from(self.bf_extract(34, 2) as u8),
413419
}
414420
}
415421

@@ -435,7 +441,7 @@ impl Mstatus {
435441
#[cfg(riscv32)]
436442
() => super::mstatush::read().sbe(),
437443
#[cfg(not(riscv32))]
438-
() => Endianness::from(self.bits & (1 << 36) != 0),
444+
() => Endianness::from(self.bf_extract(36, 1) != 0),
439445
}
440446
}
441447

@@ -462,7 +468,7 @@ impl Mstatus {
462468
#[cfg(riscv32)]
463469
() => super::mstatush::read().mbe(),
464470
#[cfg(not(riscv32))]
465-
() => Endianness::from(self.bits & (1 << 37) != 0),
471+
() => Endianness::from(self.bf_extract(37, 1) != 0),
466472
}
467473
}
468474
/// Update M-mode non-instruction-fetch memory endianness
@@ -483,7 +489,7 @@ impl Mstatus {
483489
/// Whether either the FS field or XS field signals the presence of some dirty state
484490
#[inline]
485491
pub fn sd(&self) -> bool {
486-
self.bits & (1 << (usize::BITS as usize - 1)) != 0
492+
self.bf_extract(usize::BITS as usize - 1, 1) != 0
487493
}
488494

489495
/// Update whether either the FS field or XS field signals the presence of

0 commit comments

Comments
 (0)