@@ -21,6 +21,24 @@ macro_rules! read_csr {
2121 ( ) => unimplemented!( ) ,
2222 }
2323 }
24+
25+ /// Attempts to read the CSR.
26+ ///
27+ /// Only implemented for `riscv32` and `riscv64` targets.
28+ #[ inline]
29+ unsafe fn _try_read( ) -> $crate:: result:: Result <usize > {
30+ match ( ) {
31+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
32+ ( ) => {
33+ let r: usize ;
34+ core:: arch:: asm!( concat!( "csrrs {0}, " , stringify!( $csr_number) , ", x0" ) , out( reg) r) ;
35+ Ok ( r)
36+ }
37+
38+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
39+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
40+ }
41+ }
2442 } ;
2543}
2644
@@ -47,6 +65,24 @@ macro_rules! read_csr_rv32 {
4765 ( ) => unimplemented!( ) ,
4866 }
4967 }
68+
69+ /// Attempts to read the CSR.
70+ ///
71+ /// Only implemented for `riscv32` targets.
72+ #[ inline]
73+ unsafe fn _try_read( ) -> $crate:: result:: Result <usize > {
74+ match ( ) {
75+ #[ cfg( target_arch = "riscv32" ) ]
76+ ( ) => {
77+ let r: usize ;
78+ core:: arch:: asm!( concat!( "csrrs {0}, " , stringify!( $csr_number) , ", x0" ) , out( reg) r) ;
79+ Ok ( r)
80+ }
81+
82+ #[ cfg( not( target_arch = "riscv32" ) ) ]
83+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
84+ }
85+ }
5086 } ;
5187}
5288
@@ -65,6 +101,16 @@ macro_rules! read_csr_as {
65101 bits: unsafe { _read( ) } ,
66102 }
67103 }
104+
105+ /// Attempts to reads the CSR.
106+ ///
107+ /// Only implemented for `riscv32` and `riscv64` targets.
108+ #[ inline]
109+ pub fn try_read( ) -> $crate:: result:: Result <$register> {
110+ Ok ( $register {
111+ bits: unsafe { _try_read( ) ? } ,
112+ } )
113+ }
68114 } ;
69115}
70116
@@ -83,6 +129,16 @@ macro_rules! read_csr_as_rv32 {
83129 bits: unsafe { _read( ) } ,
84130 }
85131 }
132+
133+ /// Attempts to reads the CSR.
134+ ///
135+ /// Only implemented for `riscv32` targets.
136+ #[ inline]
137+ pub fn try_read( ) -> $crate:: result:: Result <$register> {
138+ Ok ( $register {
139+ bits: unsafe { _try_read( ) ? } ,
140+ } )
141+ }
86142 } ;
87143}
88144
@@ -97,6 +153,14 @@ macro_rules! read_csr_as_usize {
97153 pub fn read( ) -> usize {
98154 unsafe { _read( ) }
99155 }
156+
157+ /// Attempts to read the CSR.
158+ ///
159+ /// Only implemented for `riscv32` and `riscv64` targets.
160+ #[ inline]
161+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
162+ unsafe { _try_read( ) }
163+ }
100164 } ;
101165}
102166
@@ -111,6 +175,14 @@ macro_rules! read_csr_as_usize_rv32 {
111175 pub fn read( ) -> usize {
112176 unsafe { _read( ) }
113177 }
178+
179+ /// Attempts to reads the CSR.
180+ ///
181+ /// Only implemented for `riscv32` targets.
182+ #[ inline]
183+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
184+ unsafe { _try_read( ) }
185+ }
114186 } ;
115187}
116188
@@ -134,6 +206,24 @@ macro_rules! write_csr {
134206 ( ) => unimplemented!( ) ,
135207 }
136208 }
209+
210+ /// Attempts to write the CSR.
211+ ///
212+ /// Only implemented for `riscv32` and `riscv64` targets.
213+ #[ inline]
214+ #[ allow( unused_variables) ]
215+ unsafe fn _try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
216+ match ( ) {
217+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
218+ ( ) => {
219+ core:: arch:: asm!( concat!( "csrrw x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
220+ Ok ( ( ) )
221+ }
222+
223+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
224+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
225+ }
226+ }
137227 } ;
138228}
139229
@@ -157,6 +247,24 @@ macro_rules! write_csr_rv32 {
157247 ( ) => unimplemented!( ) ,
158248 }
159249 }
250+
251+ /// Attempts to write the CSR.
252+ ///
253+ /// Only implemented for `riscv32` targets.
254+ #[ inline]
255+ #[ allow( unused_variables) ]
256+ unsafe fn _try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
257+ match ( ) {
258+ #[ cfg( target_arch = "riscv32" ) ]
259+ ( ) => {
260+ core:: arch:: asm!( concat!( "csrrw x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
261+ Ok ( ( ) )
262+ }
263+
264+ #[ cfg( not( target_arch = "riscv32" ) ) ]
265+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
266+ }
267+ }
160268 } ;
161269}
162270
@@ -171,6 +279,14 @@ macro_rules! write_csr_as {
171279 pub fn write( value: $csr_type) {
172280 unsafe { _write( value. bits) }
173281 }
282+
283+ /// Attempts to write the CSR.
284+ ///
285+ /// Only implemented for `riscv32` and `riscv64` targets.
286+ #[ inline]
287+ pub fn try_write( value: $csr_type) -> $crate:: result:: Result <( ) > {
288+ unsafe { _try_write( value. bits) }
289+ }
174290 } ;
175291}
176292
@@ -185,6 +301,14 @@ macro_rules! write_csr_as_rv32 {
185301 pub fn write( value: $csr_type) {
186302 unsafe { _write( value. bits) }
187303 }
304+
305+ /// Attempts to write the CSR.
306+ ///
307+ /// Only implemented for `riscv32` targets.
308+ #[ inline]
309+ pub fn try_write( value: $csr_type) -> $crate:: result:: Result <( ) > {
310+ unsafe { _try_write( value. bits) }
311+ }
188312 } ;
189313}
190314
@@ -199,6 +323,14 @@ macro_rules! write_csr_as_usize {
199323 pub fn write( bits: usize ) {
200324 unsafe { _write( bits) }
201325 }
326+
327+ /// Attempts to write the CSR.
328+ ///
329+ /// Only implemented for `riscv32` and `riscv64` targets.
330+ #[ inline]
331+ pub fn try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
332+ unsafe { _try_write( bits) }
333+ }
202334 } ;
203335}
204336
@@ -213,6 +345,14 @@ macro_rules! write_csr_as_usize_rv32 {
213345 pub fn write( bits: usize ) {
214346 unsafe { _write( bits) }
215347 }
348+
349+ /// Attempts to write the CSR.
350+ ///
351+ /// Only implemented for `riscv32` targets.
352+ #[ inline]
353+ pub fn try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
354+ unsafe { _try_write( bits) }
355+ }
216356 } ;
217357}
218358
@@ -234,6 +374,24 @@ macro_rules! set {
234374 ( ) => unimplemented!( ) ,
235375 }
236376 }
377+
378+ /// Attempts to set the CSR.
379+ ///
380+ /// Only implemented for `riscv32` and `riscv64` targets.
381+ #[ inline]
382+ #[ allow( unused_variables) ]
383+ unsafe fn _try_set( bits: usize ) -> $crate:: result:: Result <( ) > {
384+ match ( ) {
385+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
386+ ( ) => {
387+ core:: arch:: asm!( concat!( "csrrs x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
388+ Ok ( ( ) )
389+ }
390+
391+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
392+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
393+ }
394+ }
237395 } ;
238396}
239397
@@ -255,6 +413,24 @@ macro_rules! set_rv32 {
255413 ( ) => unimplemented!( ) ,
256414 }
257415 }
416+
417+ /// Attempts to set the CSR.
418+ ///
419+ /// Only implemented for `riscv32` targets.
420+ #[ inline]
421+ #[ allow( unused_variables) ]
422+ unsafe fn _try_set( bits: usize ) -> $crate:: result:: Result <( ) > {
423+ match ( ) {
424+ #[ cfg( target_arch = "riscv32" ) ]
425+ ( ) => {
426+ core:: arch:: asm!( concat!( "csrrs x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
427+ Ok ( ( ) )
428+ }
429+
430+ #[ cfg( not( target_arch = "riscv32" ) ) ]
431+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
432+ }
433+ }
258434 } ;
259435}
260436
@@ -276,6 +452,24 @@ macro_rules! clear {
276452 ( ) => unimplemented!( ) ,
277453 }
278454 }
455+
456+ /// Attempts to clear the CSR.
457+ ///
458+ /// Only implemented for `riscv32` and `riscv64` targets.
459+ #[ inline]
460+ #[ allow( unused_variables) ]
461+ unsafe fn _try_clear( bits: usize ) -> $crate:: result:: Result <( ) > {
462+ match ( ) {
463+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
464+ ( ) => {
465+ core:: arch:: asm!( concat!( "csrrc x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
466+ Ok ( ( ) )
467+ }
468+
469+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
470+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
471+ }
472+ }
279473 } ;
280474}
281475
@@ -297,6 +491,23 @@ macro_rules! clear_rv32 {
297491 ( ) => unimplemented!( ) ,
298492 }
299493 }
494+ /// Attempts to clear the CSR.
495+ ///
496+ /// Only implemented for `riscv32` targets.
497+ #[ inline]
498+ #[ allow( unused_variables) ]
499+ unsafe fn _try_clear( bits: usize ) -> $crate:: result:: Result <( ) > {
500+ match ( ) {
501+ #[ cfg( target_arch = "riscv32" ) ]
502+ ( ) => {
503+ core:: arch:: asm!( concat!( "csrrc x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
504+ Ok ( ( ) )
505+ }
506+
507+ #[ cfg( not( target_arch = "riscv32" ) ) ]
508+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
509+ }
510+ }
300511 } ;
301512}
302513
@@ -377,6 +588,39 @@ macro_rules! set_pmp {
377588 value |= byte << ( 8 * index) ;
378589 _write( value) ;
379590 }
591+
592+ /// Attempts to set the pmp configuration corresponding to the index.
593+ ///
594+ /// Returns an error if the index is invalid.
595+ #[ inline]
596+ pub unsafe fn try_set_pmp(
597+ index: usize ,
598+ range: Range ,
599+ permission: Permission ,
600+ locked: bool ,
601+ ) -> $crate:: result:: Result <( ) > {
602+ let max = if cfg!( target_arch = "riscv32" ) {
603+ Ok ( 4usize )
604+ } else if cfg!( target_arch = "riscv64" ) {
605+ Ok ( 8usize )
606+ } else {
607+ Err ( $crate:: result:: Error :: Unimplemented )
608+ } ?;
609+
610+ if index < max {
611+ let mut value = _try_read( ) ?;
612+ value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
613+ let byte = ( locked as usize ) << 7 | ( range as usize ) << 3 | ( permission as usize ) ;
614+ value |= byte << ( 8 * index) ;
615+ _try_write( value)
616+ } else {
617+ Err ( $crate:: result:: Error :: OutOfBounds {
618+ index,
619+ min: 0 ,
620+ max: max - 1 ,
621+ } )
622+ }
623+ }
380624 } ;
381625}
382626
@@ -395,5 +639,31 @@ macro_rules! clear_pmp {
395639 value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
396640 _write( value) ;
397641 }
642+
643+ /// Attempts to clear the pmp configuration corresponding to the index.
644+ ///
645+ /// Returns an error if the index is invalid.
646+ #[ inline]
647+ pub unsafe fn try_clear_pmp( index: usize ) -> $crate:: result:: Result <( ) > {
648+ let max = if cfg!( target_arch = "riscv32" ) {
649+ Ok ( 4usize )
650+ } else if cfg!( target_arch = "riscv64" ) {
651+ Ok ( 8usize )
652+ } else {
653+ Err ( $crate:: result:: Error :: Unimplemented )
654+ } ?;
655+
656+ if index < max {
657+ let mut value = _try_read( ) ?;
658+ value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
659+ _try_write( value)
660+ } else {
661+ Err ( $crate:: result:: Error :: OutOfBounds {
662+ index,
663+ min: 0 ,
664+ max: max - 1 ,
665+ } )
666+ }
667+ }
398668 } ;
399669}
0 commit comments