2020-06-14 19:33:44 +08:00
|
|
|
#![allow(unused_macros)]
|
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! read_csr {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
2018-11-09 22:42:46 +08:00
|
|
|
/// Reads the CSR
|
|
|
|
#[inline]
|
|
|
|
unsafe fn _read() -> usize {
|
2018-12-22 17:32:52 +08:00
|
|
|
match () {
|
|
|
|
#[cfg(all(riscv, feature = "inline-asm"))]
|
|
|
|
() => {
|
|
|
|
let r: usize;
|
2020-08-04 17:18:10 +08:00
|
|
|
llvm_asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
|
2018-12-22 17:32:52 +08:00
|
|
|
r
|
|
|
|
}
|
2018-11-09 22:42:46 +08:00
|
|
|
|
2018-12-22 17:32:52 +08:00
|
|
|
#[cfg(all(riscv, not(feature = "inline-asm")))]
|
2018-12-23 16:44:08 +08:00
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn() -> usize;
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn()
|
|
|
|
}
|
2018-12-22 17:32:52 +08:00
|
|
|
|
|
|
|
#[cfg(not(riscv))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
2018-11-09 22:42:46 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-12-22 05:49:23 +08:00
|
|
|
macro_rules! read_csr_rv32 {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
2018-12-22 05:49:23 +08:00
|
|
|
/// Reads the CSR
|
|
|
|
#[inline]
|
|
|
|
unsafe fn _read() -> usize {
|
2018-12-22 17:32:52 +08:00
|
|
|
match () {
|
|
|
|
#[cfg(all(riscv32, feature = "inline-asm"))]
|
|
|
|
() => {
|
|
|
|
let r: usize;
|
2020-08-04 17:18:10 +08:00
|
|
|
llvm_asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
|
2018-12-22 17:32:52 +08:00
|
|
|
r
|
|
|
|
}
|
2018-12-22 05:49:23 +08:00
|
|
|
|
2018-12-22 17:32:52 +08:00
|
|
|
#[cfg(all(riscv32, not(feature = "inline-asm")))]
|
2018-12-23 16:44:08 +08:00
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn() -> usize;
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn()
|
|
|
|
}
|
2018-12-22 17:32:52 +08:00
|
|
|
|
|
|
|
#[cfg(not(riscv32))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
2018-12-22 05:49:23 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! read_csr_as {
|
2018-12-23 16:44:08 +08:00
|
|
|
($register:ident, $csr_number:expr, $asm_fn: ident) => {
|
|
|
|
read_csr!($csr_number, $asm_fn);
|
2018-11-09 22:42:46 +08:00
|
|
|
|
|
|
|
/// Reads the CSR
|
|
|
|
#[inline]
|
|
|
|
pub fn read() -> $register {
|
|
|
|
$register { bits: unsafe{ _read() } }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2018-12-22 05:49:23 +08:00
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! read_csr_as_usize {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
|
|
|
read_csr!($csr_number, $asm_fn);
|
2018-11-09 22:42:46 +08:00
|
|
|
|
|
|
|
/// Reads the CSR
|
|
|
|
#[inline]
|
|
|
|
pub fn read() -> usize {
|
|
|
|
unsafe{ _read() }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-12-22 05:49:23 +08:00
|
|
|
macro_rules! read_csr_as_usize_rv32 {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
|
|
|
read_csr_rv32!($csr_number, $asm_fn);
|
2018-12-22 05:49:23 +08:00
|
|
|
|
|
|
|
/// Reads the CSR
|
|
|
|
#[inline]
|
|
|
|
pub fn read() -> usize {
|
|
|
|
unsafe{ _read() }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! write_csr {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
2018-11-09 22:42:46 +08:00
|
|
|
/// Writes the CSR
|
|
|
|
#[inline]
|
2018-12-22 17:32:52 +08:00
|
|
|
#[allow(unused_variables)]
|
2018-11-09 22:42:46 +08:00
|
|
|
unsafe fn _write(bits: usize) {
|
2018-12-22 17:32:52 +08:00
|
|
|
match () {
|
|
|
|
#[cfg(all(riscv, feature = "inline-asm"))]
|
2020-08-04 17:18:10 +08:00
|
|
|
() => llvm_asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
|
2018-11-09 22:42:46 +08:00
|
|
|
|
2018-12-22 17:32:52 +08:00
|
|
|
#[cfg(all(riscv, not(feature = "inline-asm")))]
|
2018-12-23 16:44:08 +08:00
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn(bits: usize);
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn(bits);
|
|
|
|
}
|
2018-12-22 17:32:52 +08:00
|
|
|
|
|
|
|
#[cfg(not(riscv))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
2018-11-09 22:42:46 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-26 05:51:37 +08:00
|
|
|
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"))]
|
2020-08-04 17:18:10 +08:00
|
|
|
() => llvm_asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
|
2019-06-26 05:51:37 +08:00
|
|
|
|
|
|
|
#[cfg(all(riscv32, not(feature = "inline-asm")))]
|
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn(bits: usize);
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn(bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(riscv32))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! write_csr_as_usize {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
|
|
|
write_csr!($csr_number, $asm_fn);
|
2018-11-09 22:42:46 +08:00
|
|
|
|
|
|
|
/// Writes the CSR
|
|
|
|
#[inline]
|
|
|
|
pub fn write(bits: usize) {
|
|
|
|
unsafe{ _write(bits) }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-26 05:51:37 +08:00
|
|
|
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) }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-09 22:42:46 +08:00
|
|
|
macro_rules! set {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
2018-11-09 22:42:46 +08:00
|
|
|
/// Set the CSR
|
|
|
|
#[inline]
|
2018-12-22 17:32:52 +08:00
|
|
|
#[allow(unused_variables)]
|
2018-11-09 22:42:46 +08:00
|
|
|
unsafe fn _set(bits: usize) {
|
2018-12-22 17:32:52 +08:00
|
|
|
match () {
|
|
|
|
#[cfg(all(riscv, feature = "inline-asm"))]
|
2020-08-04 17:18:10 +08:00
|
|
|
() => llvm_asm!("csrrs x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
|
2018-11-09 22:42:46 +08:00
|
|
|
|
2018-12-22 17:32:52 +08:00
|
|
|
#[cfg(all(riscv, not(feature = "inline-asm")))]
|
2018-12-23 16:44:08 +08:00
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn(bits: usize);
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn(bits);
|
|
|
|
}
|
2018-12-22 17:32:52 +08:00
|
|
|
|
|
|
|
#[cfg(not(riscv))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
2018-11-09 22:42:46 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! clear {
|
2018-12-23 16:44:08 +08:00
|
|
|
($csr_number:expr, $asm_fn: ident) => {
|
2018-11-09 22:42:46 +08:00
|
|
|
/// Clear the CSR
|
|
|
|
#[inline]
|
2018-12-22 17:32:52 +08:00
|
|
|
#[allow(unused_variables)]
|
2018-11-09 22:42:46 +08:00
|
|
|
unsafe fn _clear(bits: usize) {
|
2018-12-22 17:32:52 +08:00
|
|
|
match () {
|
|
|
|
#[cfg(all(riscv, feature = "inline-asm"))]
|
2020-08-04 17:18:10 +08:00
|
|
|
() => llvm_asm!("csrrc x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile"),
|
2018-11-09 22:42:46 +08:00
|
|
|
|
2018-12-22 17:32:52 +08:00
|
|
|
#[cfg(all(riscv, not(feature = "inline-asm")))]
|
2018-12-23 16:44:08 +08:00
|
|
|
() => {
|
|
|
|
extern "C" {
|
|
|
|
fn $asm_fn(bits: usize);
|
|
|
|
}
|
|
|
|
|
|
|
|
$asm_fn(bits);
|
|
|
|
}
|
2018-12-22 17:32:52 +08:00
|
|
|
|
|
|
|
#[cfg(not(riscv))]
|
|
|
|
() => unimplemented!(),
|
|
|
|
}
|
2018-11-09 22:42:46 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! set_csr {
|
2019-02-20 02:45:32 +08:00
|
|
|
($(#[$attr:meta])*, $set_field:ident, $e:expr) => {
|
|
|
|
$(#[$attr])*
|
2018-11-09 22:42:46 +08:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn $set_field() {
|
|
|
|
_set($e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! clear_csr {
|
2019-02-20 02:45:32 +08:00
|
|
|
($(#[$attr:meta])*, $clear_field:ident, $e:expr) => {
|
|
|
|
$(#[$attr])*
|
2018-11-09 22:42:46 +08:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn $clear_field() {
|
|
|
|
_clear($e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! set_clear_csr {
|
2019-02-20 02:45:32 +08:00
|
|
|
($(#[$attr:meta])*, $set_field:ident, $clear_field:ident, $e:expr) => {
|
|
|
|
set_csr!($(#[$attr])*, $set_field, $e);
|
|
|
|
clear_csr!($(#[$attr])*, $clear_field, $e);
|
2018-11-09 22:42:46 +08:00
|
|
|
}
|
2019-02-20 02:45:32 +08:00
|
|
|
}
|
2019-03-01 22:41:41 +08:00
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|