@@ -21,6 +21,22 @@ macro_rules! read_csr {
21
21
( ) => unimplemented!( ) ,
22
22
}
23
23
}
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
+ }
24
40
} ;
25
41
}
26
42
@@ -47,6 +63,22 @@ macro_rules! read_csr_rv32 {
47
63
( ) => unimplemented!( ) ,
48
64
}
49
65
}
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
+ }
50
82
} ;
51
83
}
52
84
@@ -65,6 +97,14 @@ macro_rules! read_csr_as {
65
97
bits: unsafe { _read( ) } ,
66
98
}
67
99
}
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
+ }
68
108
} ;
69
109
}
70
110
@@ -83,6 +123,14 @@ macro_rules! read_csr_as_rv32 {
83
123
bits: unsafe { _read( ) } ,
84
124
}
85
125
}
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
+ }
86
134
} ;
87
135
}
88
136
@@ -97,6 +145,12 @@ macro_rules! read_csr_as_usize {
97
145
pub fn read( ) -> usize {
98
146
unsafe { _read( ) }
99
147
}
148
+
149
+ /// Attempts to read the CSR.
150
+ #[ inline]
151
+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
152
+ unsafe { _try_read( ) }
153
+ }
100
154
} ;
101
155
}
102
156
@@ -111,6 +165,12 @@ macro_rules! read_csr_as_usize_rv32 {
111
165
pub fn read( ) -> usize {
112
166
unsafe { _read( ) }
113
167
}
168
+
169
+ /// Attempts to reads the CSR.
170
+ #[ inline]
171
+ pub fn try_read( ) -> $crate:: result:: Result <usize > {
172
+ unsafe { _try_read( ) }
173
+ }
114
174
} ;
115
175
}
116
176
@@ -134,6 +194,22 @@ macro_rules! write_csr {
134
194
( ) => unimplemented!( ) ,
135
195
}
136
196
}
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
+ }
137
213
} ;
138
214
}
139
215
@@ -157,6 +233,22 @@ macro_rules! write_csr_rv32 {
157
233
( ) => unimplemented!( ) ,
158
234
}
159
235
}
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
+ }
160
252
} ;
161
253
}
162
254
@@ -171,6 +263,12 @@ macro_rules! write_csr_as {
171
263
pub fn write( value: $csr_type) {
172
264
unsafe { _write( value. bits) }
173
265
}
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
+ }
174
272
} ;
175
273
}
176
274
@@ -185,6 +283,12 @@ macro_rules! write_csr_as_rv32 {
185
283
pub fn write( value: $csr_type) {
186
284
unsafe { _write( value. bits) }
187
285
}
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
+ }
188
292
} ;
189
293
}
190
294
@@ -199,6 +303,12 @@ macro_rules! write_csr_as_usize {
199
303
pub fn write( bits: usize ) {
200
304
unsafe { _write( bits) }
201
305
}
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
+ }
202
312
} ;
203
313
}
204
314
@@ -213,6 +323,12 @@ macro_rules! write_csr_as_usize_rv32 {
213
323
pub fn write( bits: usize ) {
214
324
unsafe { _write( bits) }
215
325
}
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
+ }
216
332
} ;
217
333
}
218
334
@@ -234,6 +350,22 @@ macro_rules! set {
234
350
( ) => unimplemented!( ) ,
235
351
}
236
352
}
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
+ }
237
369
} ;
238
370
}
239
371
@@ -255,6 +387,22 @@ macro_rules! set_rv32 {
255
387
( ) => unimplemented!( ) ,
256
388
}
257
389
}
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
+ }
258
406
} ;
259
407
}
260
408
@@ -276,6 +424,22 @@ macro_rules! clear {
276
424
( ) => unimplemented!( ) ,
277
425
}
278
426
}
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
+ }
279
443
} ;
280
444
}
281
445
@@ -297,6 +461,22 @@ macro_rules! clear_rv32 {
297
461
( ) => unimplemented!( ) ,
298
462
}
299
463
}
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
+ }
300
480
} ;
301
481
}
302
482
@@ -377,6 +557,39 @@ macro_rules! set_pmp {
377
557
value |= byte << ( 8 * index) ;
378
558
_write( value) ;
379
559
}
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
+ }
380
593
} ;
381
594
}
382
595
@@ -395,5 +608,31 @@ macro_rules! clear_pmp {
395
608
value &= !( 0xFF << ( 8 * index) ) ; // clear previous value
396
609
_write( value) ;
397
610
}
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
+ }
398
637
} ;
399
638
}
0 commit comments