xous-kernel/xous-riscv/src/register/macros.rs

271 lines
7.0 KiB
Rust

macro_rules! read_csr {
($csr_number:expr, $asm_fn: ident) => {
/// Reads the CSR
#[inline]
unsafe fn _read() -> usize {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => {
let r: usize;
asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
r
}
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn() -> usize;
}
$asm_fn()
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
};
}
macro_rules! read_csr_rv32 {
($csr_number:expr, $asm_fn: ident) => {
/// Reads the CSR
#[inline]
unsafe fn _read() -> usize {
match () {
#[cfg(all(riscv32, feature = "inline-asm"))]
() => {
let r: usize;
asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
r
}
#[cfg(all(riscv32, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn() -> usize;
}
$asm_fn()
}
#[cfg(not(riscv32))]
() => unimplemented!(),
}
}
};
}
macro_rules! read_csr_as {
($register:ident, $csr_number:expr, $asm_fn: ident) => {
read_csr!($csr_number, $asm_fn);
/// Reads the CSR
#[inline]
pub fn read() -> $register {
$register { bits: unsafe{ _read() } }
}
};
}
macro_rules! read_csr_as_usize {
($csr_number:expr, $asm_fn: ident) => {
read_csr!($csr_number, $asm_fn);
/// Reads the CSR
#[inline]
pub fn read() -> usize {
unsafe{ _read() }
}
};
}
macro_rules! read_csr_as_usize_rv32 {
($csr_number:expr, $asm_fn: ident) => {
read_csr_rv32!($csr_number, $asm_fn);
/// Reads the CSR
#[inline]
pub fn read() -> usize {
unsafe{ _read() }
}
};
}
macro_rules! write_csr {
($csr_number:expr, $asm_fn: ident) => {
/// Writes the CSR
#[inline]
#[allow(unused_variables)]
unsafe fn _write(bits: usize) {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn(bits: usize);
}
$asm_fn(bits);
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
};
}
macro_rules! write_csr_rv32 {
($csr_number:expr, $asm_fn: ident) => {
/// Writes the CSR
#[inline]
#[allow(unused_variables)]
unsafe fn _write(bits: usize) {
match () {
#[cfg(all(riscv32, feature = "inline-asm"))]
() => asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
#[cfg(all(riscv32, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn(bits: usize);
}
$asm_fn(bits);
}
#[cfg(not(riscv32))]
() => unimplemented!(),
}
}
};
}
macro_rules! write_csr_as_usize {
($csr_number:expr, $asm_fn: ident) => {
write_csr!($csr_number, $asm_fn);
/// Writes the CSR
#[inline]
pub fn write(bits: usize) {
unsafe{ _write(bits) }
}
};
}
macro_rules! write_csr_as_usize_rv32 {
($csr_number:expr, $asm_fn: ident) => {
write_csr_rv32!($csr_number, $asm_fn);
/// Writes the CSR
#[inline]
pub fn write(bits: usize) {
unsafe{ _write(bits) }
}
};
}
macro_rules! set {
($csr_number:expr, $asm_fn: ident) => {
/// Set the CSR
#[inline]
#[allow(unused_variables)]
unsafe fn _set(bits: usize) {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => asm!("csrrs x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn(bits: usize);
}
$asm_fn(bits);
}
#[cfg(not(riscv))]
() => unimplemented!(),
}
}
};
}
macro_rules! clear {
($csr_number:expr, $asm_fn: ident) => {
/// Clear the CSR
#[inline]
#[allow(unused_variables)]
unsafe fn _clear(bits: usize) {
match () {
#[cfg(all(riscv, feature = "inline-asm"))]
() => asm!("csrrc x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
#[cfg(all(riscv, not(feature = "inline-asm")))]
() => {
extern "C" {
fn $asm_fn(bits: usize);
}
$asm_fn(bits);
}
#[cfg(not(riscv))]
() => 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,
}
}
}
}