1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//! `mconfigptr` register.
use crate::result::{Error, Result};
const MASK: usize = usize::MAX;
read_only_csr! {
/// `mconfigptr` register.
Mconfigptr: 0xf15,
mask: MASK,
sentinel: 0,
}
impl Mconfigptr {
/// Represents the bitshift for a properly aligned configuration pointer.
pub const ALIGN_SHIFT: usize = (usize::BITS / 8).ilog2() as usize;
/// Represents the bitmask for a properly aligned configuration pointer.
pub const ALIGN_MASK: usize = (1usize << Self::ALIGN_SHIFT) - 1;
/// Gets the pointer to the machine configuration structure.
///
/// # Panics
///
/// Panics if:
///
/// - the value is `0`, indicating no configuration structure
/// - the pointer is not aligned to an MXLEN byte value
pub fn as_ptr(&self) -> *const u8 {
self.try_as_ptr().unwrap()
}
/// Attempts to get the pointer to the machine configuration structure.
///
/// # Note
///
/// Returns an error if:
///
/// - the value is `0`, indicating no configuration structure
/// - the pointer is not aligned to an MXLEN byte value
pub const fn try_as_ptr(&self) -> Result<*const u8> {
match self.bits() {
0 => Err(Error::InvalidFieldVariant {
field: "mconfigptr",
value: 0,
}),
p if p & Self::ALIGN_MASK != 0 => Err(Error::InvalidFieldValue {
field: "mconfigptr",
value: p,
bitmask: !Self::ALIGN_MASK,
}),
p => Ok(p as *const _),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mconfigptr() {
#[cfg(target_arch = "riscv32")]
const EXP_SHIFT: usize = 2;
#[cfg(not(target_arch = "riscv32"))]
const EXP_SHIFT: usize = 3;
const EXP_MASK: usize = (1usize << EXP_SHIFT) - 1;
assert_eq!(Mconfigptr::ALIGN_SHIFT, EXP_SHIFT);
assert_eq!(Mconfigptr::ALIGN_MASK, EXP_MASK);
(1..usize::BITS)
.map(|b| ((1u128 << b) - 1) as usize)
.for_each(|ptr| {
let mconfigptr = Mconfigptr::from_bits(ptr);
assert_eq!(mconfigptr.bits(), ptr);
match mconfigptr.try_as_ptr() {
Ok(cfg_ptr) => {
assert_eq!(cfg_ptr, ptr as *const _);
assert_eq!(mconfigptr.as_ptr(), ptr as *const _);
}
Err(err) if ptr == 0 => assert_eq!(
err,
Error::InvalidFieldVariant {
field: "mconfigptr",
value: 0
}
),
Err(err) => assert_eq!(
err,
Error::InvalidFieldValue {
field: "mconfigptr",
value: ptr,
bitmask: !Mconfigptr::ALIGN_MASK,
}
),
}
let aligned_ptr = ptr << Mconfigptr::ALIGN_SHIFT;
let aligned_mconfigptr = Mconfigptr::from_bits(aligned_ptr);
assert_eq!(aligned_mconfigptr.try_as_ptr(), Ok(aligned_ptr as *const _));
assert_eq!(aligned_mconfigptr.as_ptr(), aligned_ptr as *const _);
});
}
}