11//! `mcountinhibit` register
22
33use crate :: bits:: { bf_extract, bf_insert} ;
4+ use crate :: result:: { Error , Result } ;
45
56/// `mcountinhibit` register
67#[ derive( Clone , Copy , Debug ) ]
@@ -44,6 +45,22 @@ impl Mcountinhibit {
4445 bf_extract ( self . bits , index, 1 ) != 0
4546 }
4647
48+ /// Machine "hpm\[x\]" Disable (bits 3-31)
49+ ///
50+ /// Attempts to read the "hpm\[x\]" value, and returns an error if the index is invalid.
51+ #[ inline]
52+ pub fn try_hpm ( & self , index : usize ) -> Result < bool > {
53+ if ( 3 ..32 ) . contains ( & index) {
54+ Ok ( bf_extract ( self . bits , index, 1 ) != 0 )
55+ } else {
56+ Err ( Error :: OutOfBounds {
57+ index,
58+ min : 3 ,
59+ max : 31 ,
60+ } )
61+ }
62+ }
63+
4764 /// Sets whether to inhibit the "hpm\[X\]" counter.
4865 ///
4966 /// Only updates the in-memory value, does not modify the `mcountinhibit` register.
@@ -52,6 +69,25 @@ impl Mcountinhibit {
5269 assert ! ( ( 3 ..32 ) . contains( & index) ) ;
5370 self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
5471 }
72+
73+ /// Sets whether to inhibit the "hpm\[X\]" counter.
74+ ///
75+ /// Only updates the in-memory value, does not modify the `mcountinhibit` register.
76+ ///
77+ /// Attempts to update the "hpm\[x\]" value, and returns an error if the index is invalid.
78+ #[ inline]
79+ pub fn try_set_hpm ( & mut self , index : usize , hpm : bool ) -> Result < ( ) > {
80+ if ( 3 ..32 ) . contains ( & index) {
81+ self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
82+ Ok ( ( ) )
83+ } else {
84+ Err ( Error :: OutOfBounds {
85+ index,
86+ min : 3 ,
87+ max : 31 ,
88+ } )
89+ }
90+ }
5591}
5692
5793read_csr_as ! ( Mcountinhibit , 0x320 ) ;
@@ -73,12 +109,38 @@ pub unsafe fn set_hpm(index: usize) {
73109 _set ( 1 << index) ;
74110}
75111
112+ #[ inline]
113+ pub unsafe fn try_set_hpm ( index : usize ) -> Result < ( ) > {
114+ if ( 3 ..32 ) . contains ( & index) {
115+ _try_set ( 1 << index)
116+ } else {
117+ Err ( Error :: OutOfBounds {
118+ index,
119+ min : 3 ,
120+ max : 31 ,
121+ } )
122+ }
123+ }
124+
76125#[ inline]
77126pub unsafe fn clear_hpm ( index : usize ) {
78127 assert ! ( ( 3 ..32 ) . contains( & index) ) ;
79128 _clear ( 1 << index) ;
80129}
81130
131+ #[ inline]
132+ pub unsafe fn try_clear_hpm ( index : usize ) -> Result < ( ) > {
133+ if ( 3 ..32 ) . contains ( & index) {
134+ _try_clear ( 1 << index)
135+ } else {
136+ Err ( Error :: OutOfBounds {
137+ index,
138+ min : 3 ,
139+ max : 31 ,
140+ } )
141+ }
142+ }
143+
82144#[ cfg( test) ]
83145mod tests {
84146 use super :: * ;
@@ -105,12 +167,33 @@ mod tests {
105167
106168 ( 3 ..32 ) . for_each ( |i| {
107169 assert ! ( !m. hpm( i) ) ;
170+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
108171
109172 m. set_hpm ( i, true ) ;
110173 assert ! ( m. hpm( i) ) ;
174+ assert_eq ! ( m. try_hpm( i) , Ok ( true ) ) ;
111175
112- m. set_hpm ( i, false ) ;
113- assert ! ( !m. hpm( i) ) ;
176+ assert_eq ! ( m. try_set_hpm( i, false ) , Ok ( ( ) ) ) ;
177+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
178+ } ) ;
179+
180+ ( 0 ..2 ) . chain ( 32 ..64 ) . for_each ( |index| {
181+ assert_eq ! (
182+ m. try_hpm( index) ,
183+ Err ( Error :: OutOfBounds {
184+ index,
185+ min: 3 ,
186+ max: 31
187+ } )
188+ ) ;
189+ assert_eq ! (
190+ m. try_set_hpm( index, false ) ,
191+ Err ( Error :: OutOfBounds {
192+ index,
193+ min: 3 ,
194+ max: 31
195+ } )
196+ ) ;
114197 } ) ;
115198 }
116199}
0 commit comments