1
1
//! mcounteren register
2
2
3
3
use crate :: bits:: { bf_extract, bf_insert} ;
4
+ use crate :: result:: { Error , Result } ;
4
5
5
6
/// mcounteren register
6
7
#[ derive( Clone , Copy , Debug ) ]
@@ -58,6 +59,22 @@ impl Mcounteren {
58
59
bf_extract ( self . bits , index, 1 ) != 0
59
60
}
60
61
62
+ /// Fallible Supervisor "hpm\[x\]" Enable (bits 3-31).
63
+ ///
64
+ /// Attempts to read the "hpm\[x\]" value, and returns an error if the `index` is invalid.
65
+ #[ inline]
66
+ pub fn try_hpm ( & self , index : usize ) -> Result < bool > {
67
+ if ( 3 ..32 ) . contains ( & index) {
68
+ Ok ( bf_extract ( self . bits , index, 1 ) != 0 )
69
+ } else {
70
+ Err ( Error :: OutOfBounds {
71
+ index,
72
+ min : 3 ,
73
+ max : 31 ,
74
+ } )
75
+ }
76
+ }
77
+
61
78
/// Sets whether to enable the "hpm\[X\]" counter.
62
79
///
63
80
/// Only updates the in-memory value, does not modify the `mcounteren` register.
@@ -66,6 +83,25 @@ impl Mcounteren {
66
83
assert ! ( ( 3 ..32 ) . contains( & index) ) ;
67
84
self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
68
85
}
86
+
87
+ /// Sets whether to enable the "hpm\[X\]" counter.
88
+ ///
89
+ /// Only updates the in-memory value, does not modify the `mcounteren` register.
90
+ ///
91
+ /// Attempts to update the "hpm\[x\]" value, and returns an error if the `index` is invalid.
92
+ #[ inline]
93
+ pub fn try_set_hpm ( & mut self , index : usize , hpm : bool ) -> Result < ( ) > {
94
+ if ( 3 ..32 ) . contains ( & index) {
95
+ self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
96
+ Ok ( ( ) )
97
+ } else {
98
+ Err ( Error :: OutOfBounds {
99
+ index,
100
+ min : 3 ,
101
+ max : 31 ,
102
+ } )
103
+ }
104
+ }
69
105
}
70
106
71
107
read_csr_as ! ( Mcounteren , 0x306 ) ;
@@ -91,12 +127,38 @@ pub unsafe fn set_hpm(index: usize) {
91
127
_set ( 1 << index) ;
92
128
}
93
129
130
+ #[ inline]
131
+ pub unsafe fn try_set_hpm ( index : usize ) -> Result < ( ) > {
132
+ if ( 3 ..32 ) . contains ( & index) {
133
+ _try_set ( 1 << index)
134
+ } else {
135
+ Err ( Error :: OutOfBounds {
136
+ index,
137
+ min : 3 ,
138
+ max : 31 ,
139
+ } )
140
+ }
141
+ }
142
+
94
143
#[ inline]
95
144
pub unsafe fn clear_hpm ( index : usize ) {
96
145
assert ! ( ( 3 ..32 ) . contains( & index) ) ;
97
146
_clear ( 1 << index) ;
98
147
}
99
148
149
+ #[ inline]
150
+ pub unsafe fn try_clear_hpm ( index : usize ) -> Result < ( ) > {
151
+ if ( 3 ..32 ) . contains ( & index) {
152
+ _try_clear ( 1 << index)
153
+ } else {
154
+ Err ( Error :: OutOfBounds {
155
+ index,
156
+ min : 3 ,
157
+ max : 31 ,
158
+ } )
159
+ }
160
+ }
161
+
100
162
#[ cfg( test) ]
101
163
mod tests {
102
164
use super :: * ;
@@ -131,12 +193,34 @@ mod tests {
131
193
132
194
( 3 ..32 ) . for_each ( |i| {
133
195
assert ! ( !m. hpm( i) ) ;
196
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
134
197
135
198
m. set_hpm ( i, true ) ;
136
199
assert ! ( m. hpm( i) ) ;
137
200
138
- m. set_hpm ( i, false ) ;
201
+ assert_eq ! ( m. try_set_hpm( i, false ) , Ok ( ( ) ) ) ;
202
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
203
+
139
204
assert ! ( !m. hpm( i) ) ;
140
205
} ) ;
206
+
207
+ ( 0 ..3 ) . chain ( 32 ..64 ) . for_each ( |index| {
208
+ assert_eq ! (
209
+ m. try_hpm( index) ,
210
+ Err ( Error :: OutOfBounds {
211
+ index,
212
+ min: 3 ,
213
+ max: 31
214
+ } )
215
+ ) ;
216
+ assert_eq ! (
217
+ m. try_set_hpm( index, false ) ,
218
+ Err ( Error :: OutOfBounds {
219
+ index,
220
+ min: 3 ,
221
+ max: 31
222
+ } )
223
+ ) ;
224
+ } )
141
225
}
142
226
}
0 commit comments