Skip to content

Commit 573a8a5

Browse files
committed
riscv: add fallible functions to register macros
Adds fallible `try_` function variants to most `register` module macros.
1 parent 0f3b9b2 commit 573a8a5

File tree

1 file changed

+270
-0
lines changed

1 file changed

+270
-0
lines changed

riscv/src/register/macros.rs

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)