@@ -21,6 +21,22 @@ macro_rules! read_csr {
2121 ( ) => unimplemented!( ) ,
2222 }
2323 }
24+
25+ /// Attempts to read the CSR.
26+ #[ inline]
27+ unsafe fn _try_read( ) -> $crate:: result:: Result <usize > {
28+ match ( ) {
29+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
30+ ( ) => {
31+ let r: usize ;
32+ core:: arch:: asm!( concat!( "csrrs {0}, " , stringify!( $csr_number) , ", x0" ) , out( reg) r) ;
33+ Ok ( r)
34+ }
35+
36+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
37+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
38+ }
39+ }
2440 } ;
2541}
2642
@@ -47,6 +63,22 @@ macro_rules! read_csr_rv32 {
4763 ( ) => unimplemented!( ) ,
4864 }
4965 }
66+
67+ /// Attempts to read the CSR.
68+ #[ inline]
69+ unsafe fn _try_read( ) -> $crate:: result:: Result <usize > {
70+ match ( ) {
71+ #[ cfg( target_arch = "riscv32" ) ]
72+ ( ) => {
73+ let r: usize ;
74+ core:: arch:: asm!( concat!( "csrrs {0}, " , stringify!( $csr_number) , ", x0" ) , out( reg) r) ;
75+ Ok ( r)
76+ }
77+
78+ #[ cfg( not( target_arch = "riscv32" ) ) ]
79+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
80+ }
81+ }
5082 } ;
5183}
5284
@@ -65,6 +97,14 @@ macro_rules! read_csr_as {
6597 bits: unsafe { _read( ) } ,
6698 }
6799 }
100+
101+ /// Attempts to reads the CSR.
102+ #[ inline]
103+ pub fn try_read( ) -> $crate:: result:: Result <$register> {
104+ Ok ( $register {
105+ bits: unsafe { _try_read( ) ? } ,
106+ } )
107+ }
68108 } ;
69109}
70110
@@ -83,6 +123,14 @@ macro_rules! read_csr_as_rv32 {
83123 bits: unsafe { _read( ) } ,
84124 }
85125 }
126+
127+ /// Attempts to reads the CSR.
128+ #[ inline]
129+ pub fn try_read( ) -> $crate:: result:: Result <$register> {
130+ Ok ( $register {
131+ bits: unsafe { _try_read( ) ? } ,
132+ } )
133+ }
86134 } ;
87135}
88136
@@ -97,6 +145,12 @@ macro_rules! read_csr_as_usize {
97145 pub fn read( ) -> usize {
98146 unsafe { _read( ) }
99147 }
148+
149+ /// Attempts to read the CSR.
150+ #[ inline]
151+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
152+ unsafe { _try_read( ) }
153+ }
100154 } ;
101155}
102156
@@ -111,6 +165,12 @@ macro_rules! read_csr_as_usize_rv32 {
111165 pub fn read( ) -> usize {
112166 unsafe { _read( ) }
113167 }
168+
169+ /// Attempts to reads the CSR.
170+ #[ inline]
171+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
172+ unsafe { _try_read( ) }
173+ }
114174 } ;
115175}
116176
@@ -134,6 +194,22 @@ macro_rules! write_csr {
134194 ( ) => unimplemented!( ) ,
135195 }
136196 }
197+
198+ /// Attempts to write the CSR.
199+ #[ inline]
200+ #[ allow( unused_variables) ]
201+ unsafe fn _try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
202+ match ( ) {
203+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
204+ ( ) => {
205+ core:: arch:: asm!( concat!( "csrrw x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
206+ Ok ( ( ) )
207+ }
208+
209+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
210+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
211+ }
212+ }
137213 } ;
138214}
139215
@@ -157,6 +233,22 @@ macro_rules! write_csr_rv32 {
157233 ( ) => unimplemented!( ) ,
158234 }
159235 }
236+
237+ /// Attempts to write the CSR.
238+ #[ inline]
239+ #[ allow( unused_variables) ]
240+ unsafe fn _try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
241+ match ( ) {
242+ #[ cfg( target_arch = "riscv32" ) ]
243+ ( ) => {
244+ core:: arch:: asm!( concat!( "csrrw x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
245+ Ok ( ( ) )
246+ }
247+
248+ #[ cfg( not( target_arch = "riscv32" ) ) ]
249+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
250+ }
251+ }
160252 } ;
161253}
162254
@@ -171,6 +263,12 @@ macro_rules! write_csr_as {
171263 pub fn write( value: $csr_type) {
172264 unsafe { _write( value. bits) }
173265 }
266+
267+ /// Attempts to write the CSR.
268+ #[ inline]
269+ pub fn try_write( value: $csr_type) -> $crate:: result:: Result <( ) > {
270+ unsafe { _try_write( value. bits) }
271+ }
174272 } ;
175273}
176274
@@ -185,6 +283,12 @@ macro_rules! write_csr_as_rv32 {
185283 pub fn write( value: $csr_type) {
186284 unsafe { _write( value. bits) }
187285 }
286+
287+ /// Attempts to write the CSR.
288+ #[ inline]
289+ pub fn try_write( value: $csr_type) -> $crate:: result:: Result <( ) > {
290+ unsafe { _try_write( value. bits) }
291+ }
188292 } ;
189293}
190294
@@ -199,6 +303,12 @@ macro_rules! write_csr_as_usize {
199303 pub fn write( bits: usize ) {
200304 unsafe { _write( bits) }
201305 }
306+
307+ /// Attempts to write the CSR.
308+ #[ inline]
309+ pub fn try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
310+ unsafe { _try_write( bits) }
311+ }
202312 } ;
203313}
204314
@@ -213,6 +323,12 @@ macro_rules! write_csr_as_usize_rv32 {
213323 pub fn write( bits: usize ) {
214324 unsafe { _write( bits) }
215325 }
326+
327+ /// Attempts to write the CSR.
328+ #[ inline]
329+ pub fn try_write( bits: usize ) -> $crate:: result:: Result <( ) > {
330+ unsafe { _try_write( bits) }
331+ }
216332 } ;
217333}
218334
@@ -234,6 +350,22 @@ macro_rules! set {
234350 ( ) => unimplemented!( ) ,
235351 }
236352 }
353+
354+ /// Attempts to set the CSR.
355+ #[ inline]
356+ #[ allow( unused_variables) ]
357+ unsafe fn _try_set( bits: usize ) -> $crate:: result:: Result <( ) > {
358+ match ( ) {
359+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
360+ ( ) => {
361+ core:: arch:: asm!( concat!( "csrrs x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
362+ Ok ( ( ) )
363+ }
364+
365+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
366+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
367+ }
368+ }
237369 } ;
238370}
239371
@@ -255,6 +387,22 @@ macro_rules! set_rv32 {
255387 ( ) => unimplemented!( ) ,
256388 }
257389 }
390+
391+ /// Attempts to set the CSR.
392+ #[ inline]
393+ #[ allow( unused_variables) ]
394+ unsafe fn _try_set( bits: usize ) -> $crate:: result:: Result <( ) > {
395+ match ( ) {
396+ #[ cfg( target_arch = "riscv32" ) ]
397+ ( ) => {
398+ core:: arch:: asm!( concat!( "csrrs x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
399+ Ok ( ( ) )
400+ }
401+
402+ #[ cfg( not( target_arch = "riscv32" ) ) ]
403+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
404+ }
405+ }
258406 } ;
259407}
260408
@@ -276,6 +424,22 @@ macro_rules! clear {
276424 ( ) => unimplemented!( ) ,
277425 }
278426 }
427+
428+ /// Attempts to clear the CSR.
429+ #[ inline]
430+ #[ allow( unused_variables) ]
431+ unsafe fn _try_clear( bits: usize ) -> $crate:: result:: Result <( ) > {
432+ match ( ) {
433+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
434+ ( ) => {
435+ core:: arch:: asm!( concat!( "csrrc x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
436+ Ok ( ( ) )
437+ }
438+
439+ #[ cfg( not( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ) ]
440+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
441+ }
442+ }
279443 } ;
280444}
281445
@@ -297,6 +461,22 @@ macro_rules! clear_rv32 {
297461 ( ) => unimplemented!( ) ,
298462 }
299463 }
464+
465+ /// Attempts to clear the CSR.
466+ #[ inline]
467+ #[ allow( unused_variables) ]
468+ unsafe fn _try_clear( bits: usize ) -> $crate:: result:: Result <( ) > {
469+ match ( ) {
470+ #[ cfg( target_arch = "riscv32" ) ]
471+ ( ) => {
472+ core:: arch:: asm!( concat!( "csrrc x0, " , stringify!( $csr_number) , ", {0}" ) , in( reg) bits) ;
473+ Ok ( ( ) )
474+ }
475+
476+ #[ cfg( not( target_arch = "riscv32" ) ) ]
477+ ( ) => Err ( $crate:: result:: Error :: Unimplemented ) ,
478+ }
479+ }
300480 } ;
301481}
302482
@@ -377,6 +557,39 @@ macro_rules! set_pmp {
377557 value |= byte << ( 8 * index) ;
378558 _write( value) ;
379559 }
560+
561+ /// Attempts to set the pmp configuration corresponding to the index.
562+ ///
563+ /// Returns an error if the index is invalid.
564+ #[ inline]
565+ pub unsafe fn try_set_pmp(
566+ index: usize ,
567+ range: Range ,
568+ permission: Permission ,
569+ locked: bool ,
570+ ) -> $crate:: result:: Result <( ) > {
571+ let max = if cfg!( target_arch = "riscv32" ) {
572+ Ok ( 4usize )
573+ } else if cfg!( target_arch = "riscv64" ) {
574+ Ok ( 8usize )
575+ } else {
576+ Err ( $crate:: result:: Error :: Unimplemented )
577+ } ?;
578+
579+ if index < max {
580+ let mut value = _try_read( ) ?;
581+ value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
582+ let byte = ( locked as usize ) << 7 | ( range as usize ) << 3 | ( permission as usize ) ;
583+ value |= byte << ( 8 * index) ;
584+ _try_write( value)
585+ } else {
586+ Err ( $crate:: result:: Error :: OutOfBounds {
587+ index,
588+ min: 0 ,
589+ max: max - 1 ,
590+ } )
591+ }
592+ }
380593 } ;
381594}
382595
@@ -395,5 +608,31 @@ macro_rules! clear_pmp {
395608 value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
396609 _write( value) ;
397610 }
611+
612+ /// Attempts to clear the pmp configuration corresponding to the index.
613+ ///
614+ /// Returns an error if the index is invalid.
615+ #[ inline]
616+ pub unsafe fn try_clear_pmp( index: usize ) -> $crate:: result:: Result <( ) > {
617+ let max = if cfg!( target_arch = "riscv32" ) {
618+ Ok ( 4usize )
619+ } else if cfg!( target_arch = "riscv64" ) {
620+ Ok ( 8usize )
621+ } else {
622+ Err ( $crate:: result:: Error :: Unimplemented )
623+ } ?;
624+
625+ if index < max {
626+ let mut value = _try_read( ) ?;
627+ value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
628+ _try_write( value)
629+ } else {
630+ Err ( $crate:: result:: Error :: OutOfBounds {
631+ index,
632+ min: 0 ,
633+ max: max - 1 ,
634+ } )
635+ }
636+ }
398637 } ;
399638}
0 commit comments