11//! mcounteren register
22
33use crate :: bits:: { bf_extract, bf_insert} ;
4+ use crate :: result:: { Error , Result } ;
45
56/// mcounteren register
67#[ derive( Clone , Copy , Debug ) ]
@@ -58,6 +59,22 @@ impl Mcounteren {
5859 bf_extract ( self . bits , index, 1 ) != 0
5960 }
6061
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+
6178 /// Sets whether to enable the "hpm\[X\]" counter.
6279 ///
6380 /// Only updates the in-memory value, does not modify the `mcounteren` register.
@@ -66,6 +83,25 @@ impl Mcounteren {
6683 assert ! ( ( 3 ..32 ) . contains( & index) ) ;
6784 self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
6885 }
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+ }
69105}
70106
71107read_csr_as ! ( Mcounteren , 0x306 ) ;
@@ -91,12 +127,38 @@ pub unsafe fn set_hpm(index: usize) {
91127 _set ( 1 << index) ;
92128}
93129
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+
94143#[ inline]
95144pub unsafe fn clear_hpm ( index : usize ) {
96145 assert ! ( ( 3 ..32 ) . contains( & index) ) ;
97146 _clear ( 1 << index) ;
98147}
99148
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+
100162#[ cfg( test) ]
101163mod tests {
102164 use super :: * ;
@@ -131,12 +193,34 @@ mod tests {
131193
132194 ( 3 ..32 ) . for_each ( |i| {
133195 assert ! ( !m. hpm( i) ) ;
196+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
134197
135198 m. set_hpm ( i, true ) ;
136199 assert ! ( m. hpm( i) ) ;
137200
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+
139204 assert ! ( !m. hpm( i) ) ;
140205 } ) ;
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+ } )
141225 }
142226}
0 commit comments