macro_rules! read_csr { ($csr_number:literal) => { /// Reads the CSR #[inline] unsafe fn _read() -> usize { match () { #[cfg(riscv)] () => { let r: usize; core::arch::asm!(concat!("csrrs {0}, ", stringify!($csr_number), ", x0"), out(reg) r); r } #[cfg(not(riscv))] () => unimplemented!(), } } }; } macro_rules! read_csr_rv32 { ($csr_number:literal) => { /// Reads the CSR #[inline] unsafe fn _read() -> usize { match () { #[cfg(riscv32)] () => { let r: usize; core::arch::asm!(concat!("csrrs {0}, ", stringify!($csr_number), ", x0"), out(reg) r); r } #[cfg(not(riscv32))] () => unimplemented!(), } } }; } macro_rules! read_csr_as { ($register:ident, $csr_number:literal) => { read_csr!($csr_number); /// Reads the CSR #[inline] pub fn read() -> $register { $register { bits: unsafe { _read() }, } } }; } macro_rules! read_csr_as_rv32 { ($register:ident, $csr_number:literal) => { read_csr_rv32!($csr_number); /// Reads the CSR #[inline] pub fn read() -> $register { $register { bits: unsafe { _read() }, } } }; } macro_rules! read_csr_as_usize { ($csr_number:literal) => { read_csr!($csr_number); /// Reads the CSR #[inline] pub fn read() -> usize { unsafe { _read() } } }; } macro_rules! read_csr_as_usize_rv32 { ($csr_number:literal) => { read_csr_rv32!($csr_number); /// Reads the CSR #[inline] pub fn read() -> usize { unsafe { _read() } } }; } macro_rules! write_csr { ($csr_number:literal) => { /// Writes the CSR #[inline] #[allow(unused_variables)] unsafe fn _write(bits: usize) { match () { #[cfg(riscv)] () => core::arch::asm!(concat!("csrrw x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv))] () => unimplemented!(), } } }; } macro_rules! write_csr_rv32 { ($csr_number:literal) => { /// Writes the CSR #[inline] #[allow(unused_variables)] unsafe fn _write(bits: usize) { match () { #[cfg(riscv32)] () => core::arch::asm!(concat!("csrrw x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv32))] () => unimplemented!(), } } }; } macro_rules! write_csr_as_usize { ($csr_number:literal) => { write_csr!($csr_number); /// Writes the CSR #[inline] pub fn write(bits: usize) { unsafe { _write(bits) } } }; } macro_rules! write_csr_as_usize_rv32 { ($csr_number:literal) => { write_csr_rv32!($csr_number); /// Writes the CSR #[inline] pub fn write(bits: usize) { unsafe { _write(bits) } } }; } macro_rules! set { ($csr_number:literal) => { /// Set the CSR #[inline] #[allow(unused_variables)] unsafe fn _set(bits: usize) { match () { #[cfg(riscv)] () => core::arch::asm!(concat!("csrrs x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv))] () => unimplemented!(), } } }; } macro_rules! set_rv32 { ($csr_number:literal) => { /// Set the CSR #[inline] #[allow(unused_variables)] unsafe fn _set(bits: usize) { match () { #[cfg(riscv32)] () => core::arch::asm!(concat!("csrrs x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv32))] () => unimplemented!(), } } }; } macro_rules! clear { ($csr_number:literal) => { /// Clear the CSR #[inline] #[allow(unused_variables)] unsafe fn _clear(bits: usize) { match () { #[cfg(riscv)] () => core::arch::asm!(concat!("csrrc x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv))] () => unimplemented!(), } } }; } macro_rules! clear_rv32 { ($csr_number:literal) => { /// Clear the CSR #[inline] #[allow(unused_variables)] unsafe fn _clear(bits: usize) { match () { #[cfg(riscv32)] () => core::arch::asm!(concat!("csrrc x0, ", stringify!($csr_number), ", {0}"), in(reg) bits), #[cfg(not(riscv32))] () => unimplemented!(), } } }; } macro_rules! set_csr { ($(#[$attr:meta])*, $set_field:ident, $e:expr) => { $(#[$attr])* #[inline] pub unsafe fn $set_field() { _set($e); } }; } macro_rules! clear_csr { ($(#[$attr:meta])*, $clear_field:ident, $e:expr) => { $(#[$attr])* #[inline] pub unsafe fn $clear_field() { _clear($e); } }; } macro_rules! set_clear_csr { ($(#[$attr:meta])*, $set_field:ident, $clear_field:ident, $e:expr) => { set_csr!($(#[$attr])*, $set_field, $e); clear_csr!($(#[$attr])*, $clear_field, $e); } } macro_rules! read_composite_csr { ($hi:expr, $lo:expr) => { /// Reads the CSR as a 64-bit value #[inline] pub fn read64() -> u64 { match () { #[cfg(riscv32)] () => loop { let hi = $hi; let lo = $lo; if hi == $hi { return ((hi as u64) << 32) | lo as u64; } }, #[cfg(not(riscv32))] () => $lo as u64, } } }; } macro_rules! set_pmp { () => { /// Set the pmp configuration corresponding to the index #[inline] pub unsafe fn set_pmp(index: usize, range: Range, permission: Permission, locked: bool) { #[cfg(riscv32)] assert!(index < 4); #[cfg(riscv64)] assert!(index < 8); let mut value = _read(); value &= !(0xFF << (8 * index)); // clear previous value let byte = (locked as usize) << 7 | (range as usize) << 3 | (permission as usize); value |= byte << (8 * index); _write(value); } }; } macro_rules! clear_pmp { () => { /// Clear the pmp configuration corresponding to the index #[inline] pub unsafe fn clear_pmp(index: usize) { #[cfg(riscv32)] assert!(index < 4); #[cfg(riscv64)] assert!(index < 8); let mut value = _read(); value &= !(0xFF << (8 * index)); // clear previous value _write(value); } }; }