@@ -21,6 +21,24 @@ macro_rules! read_csr {
21
21
( ) => unimplemented!( ) ,
22
22
}
23
23
}
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
+ }
24
42
} ;
25
43
}
26
44
@@ -47,6 +65,24 @@ macro_rules! read_csr_rv32 {
47
65
( ) => unimplemented!( ) ,
48
66
}
49
67
}
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
+ }
50
86
} ;
51
87
}
52
88
@@ -65,6 +101,16 @@ macro_rules! read_csr_as {
65
101
bits: unsafe { _read( ) } ,
66
102
}
67
103
}
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
+ }
68
114
} ;
69
115
}
70
116
@@ -83,6 +129,16 @@ macro_rules! read_csr_as_rv32 {
83
129
bits: unsafe { _read( ) } ,
84
130
}
85
131
}
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
+ }
86
142
} ;
87
143
}
88
144
@@ -97,6 +153,14 @@ macro_rules! read_csr_as_usize {
97
153
pub fn read( ) -> usize {
98
154
unsafe { _read( ) }
99
155
}
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
+ }
100
164
} ;
101
165
}
102
166
@@ -111,6 +175,14 @@ macro_rules! read_csr_as_usize_rv32 {
111
175
pub fn read( ) -> usize {
112
176
unsafe { _read( ) }
113
177
}
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
+ }
114
186
} ;
115
187
}
116
188
@@ -134,6 +206,24 @@ macro_rules! write_csr {
134
206
( ) => unimplemented!( ) ,
135
207
}
136
208
}
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
+ }
137
227
} ;
138
228
}
139
229
@@ -157,6 +247,24 @@ macro_rules! write_csr_rv32 {
157
247
( ) => unimplemented!( ) ,
158
248
}
159
249
}
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
+ }
160
268
} ;
161
269
}
162
270
@@ -171,6 +279,14 @@ macro_rules! write_csr_as {
171
279
pub fn write( value: $csr_type) {
172
280
unsafe { _write( value. bits) }
173
281
}
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
+ }
174
290
} ;
175
291
}
176
292
@@ -185,6 +301,14 @@ macro_rules! write_csr_as_rv32 {
185
301
pub fn write( value: $csr_type) {
186
302
unsafe { _write( value. bits) }
187
303
}
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
+ }
188
312
} ;
189
313
}
190
314
@@ -199,6 +323,14 @@ macro_rules! write_csr_as_usize {
199
323
pub fn write( bits: usize ) {
200
324
unsafe { _write( bits) }
201
325
}
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
+ }
202
334
} ;
203
335
}
204
336
@@ -213,6 +345,14 @@ macro_rules! write_csr_as_usize_rv32 {
213
345
pub fn write( bits: usize ) {
214
346
unsafe { _write( bits) }
215
347
}
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
+ }
216
356
} ;
217
357
}
218
358
@@ -234,6 +374,24 @@ macro_rules! set {
234
374
( ) => unimplemented!( ) ,
235
375
}
236
376
}
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
+ }
237
395
} ;
238
396
}
239
397
@@ -255,6 +413,24 @@ macro_rules! set_rv32 {
255
413
( ) => unimplemented!( ) ,
256
414
}
257
415
}
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
+ }
258
434
} ;
259
435
}
260
436
@@ -276,6 +452,24 @@ macro_rules! clear {
276
452
( ) => unimplemented!( ) ,
277
453
}
278
454
}
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
+ }
279
473
} ;
280
474
}
281
475
@@ -297,6 +491,23 @@ macro_rules! clear_rv32 {
297
491
( ) => unimplemented!( ) ,
298
492
}
299
493
}
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
+ }
300
511
} ;
301
512
}
302
513
@@ -377,6 +588,39 @@ macro_rules! set_pmp {
377
588
value |= byte << ( 8 * index) ;
378
589
_write( value) ;
379
590
}
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
+ }
380
624
} ;
381
625
}
382
626
@@ -395,5 +639,31 @@ macro_rules! clear_pmp {
395
639
value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
396
640
_write( value) ;
397
641
}
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
+ }
398
668
} ;
399
669
}
0 commit comments