Skip to content

Commit ac3db5e

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

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

riscv/src/register/macros.rs

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

Comments
 (0)