1
1
//! `mcountinhibit` register
2
2
3
3
use crate :: bits:: { bf_extract, bf_insert} ;
4
+ use crate :: result:: { Error , Result } ;
4
5
5
6
/// `mcountinhibit` register
6
7
#[ derive( Clone , Copy , Debug ) ]
@@ -44,6 +45,22 @@ impl Mcountinhibit {
44
45
bf_extract ( self . bits , index, 1 ) != 0
45
46
}
46
47
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 :: IndexOutOfBounds {
57
+ index,
58
+ min : 3 ,
59
+ max : 31 ,
60
+ } )
61
+ }
62
+ }
63
+
47
64
/// Sets whether to inhibit the "hpm\[X\]" counter.
48
65
///
49
66
/// Only updates the in-memory value, does not modify the `mcountinhibit` register.
@@ -52,6 +69,25 @@ impl Mcountinhibit {
52
69
assert ! ( ( 3 ..32 ) . contains( & index) ) ;
53
70
self . bits = bf_insert ( self . bits , index, 1 , hpm as usize ) ;
54
71
}
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 :: IndexOutOfBounds {
85
+ index,
86
+ min : 3 ,
87
+ max : 31 ,
88
+ } )
89
+ }
90
+ }
55
91
}
56
92
57
93
read_csr_as ! ( Mcountinhibit , 0x320 ) ;
@@ -73,12 +109,38 @@ pub unsafe fn set_hpm(index: usize) {
73
109
_set ( 1 << index) ;
74
110
}
75
111
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 :: IndexOutOfBounds {
118
+ index,
119
+ min : 3 ,
120
+ max : 31 ,
121
+ } )
122
+ }
123
+ }
124
+
76
125
#[ inline]
77
126
pub unsafe fn clear_hpm ( index : usize ) {
78
127
assert ! ( ( 3 ..32 ) . contains( & index) ) ;
79
128
_clear ( 1 << index) ;
80
129
}
81
130
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 :: IndexOutOfBounds {
137
+ index,
138
+ min : 3 ,
139
+ max : 31 ,
140
+ } )
141
+ }
142
+ }
143
+
82
144
#[ cfg( test) ]
83
145
mod tests {
84
146
use super :: * ;
@@ -105,12 +167,33 @@ mod tests {
105
167
106
168
( 3 ..32 ) . for_each ( |i| {
107
169
assert ! ( !m. hpm( i) ) ;
170
+ assert_eq ! ( m. try_hpm( i) , Ok ( false ) ) ;
108
171
109
172
m. set_hpm ( i, true ) ;
110
173
assert ! ( m. hpm( i) ) ;
174
+ assert_eq ! ( m. try_hpm( i) , Ok ( true ) ) ;
111
175
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 :: IndexOutOfBounds {
184
+ index,
185
+ min: 3 ,
186
+ max: 31
187
+ } )
188
+ ) ;
189
+ assert_eq ! (
190
+ m. try_set_hpm( index, false ) ,
191
+ Err ( Error :: IndexOutOfBounds {
192
+ index,
193
+ min: 3 ,
194
+ max: 31
195
+ } )
196
+ ) ;
114
197
} ) ;
115
198
}
116
199
}
0 commit comments