add S-Mode registers
- use macros to simplify CSR ops - use crate 'bit_field' to make bits operation clear
This commit is contained in:
parent
9dc7b40fdd
commit
8776d30d3b
|
@ -10,6 +10,7 @@ license = "ISC"
|
|||
|
||||
[dependencies]
|
||||
bare-metal = "0.2.0"
|
||||
bit_field = "0.9.0"
|
||||
|
||||
[features]
|
||||
inline-asm = []
|
|
@ -12,6 +12,7 @@
|
|||
#![feature(const_fn)]
|
||||
|
||||
extern crate bare_metal;
|
||||
extern crate bit_field;
|
||||
|
||||
pub mod asm;
|
||||
pub mod interrupt;
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
macro_rules! read_csr {
|
||||
($csr_number:expr) => {
|
||||
/// Reads the CSR
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
unsafe fn _read() -> usize {
|
||||
let r: usize;
|
||||
asm!("csrrs $0, $1, x0" : "=r"(r) : "i"($csr_number) :: "volatile");
|
||||
r
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||
unsafe fn _read() -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! read_csr_as {
|
||||
($register:ident, $csr_number:expr) => {
|
||||
read_csr!($csr_number);
|
||||
|
||||
/// Reads the CSR
|
||||
#[inline]
|
||||
pub fn read() -> $register {
|
||||
$register { bits: unsafe{ _read() } }
|
||||
}
|
||||
};
|
||||
}
|
||||
macro_rules! read_csr_as_usize {
|
||||
($csr_number:expr) => {
|
||||
read_csr!($csr_number);
|
||||
|
||||
/// Reads the CSR
|
||||
#[inline]
|
||||
pub fn read() -> usize {
|
||||
unsafe{ _read() }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! write_csr {
|
||||
($csr_number:expr) => {
|
||||
/// Writes the CSR
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
unsafe fn _write(bits: usize) {
|
||||
asm!("csrrw x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||
unsafe fn _write(_bits: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! write_csr_as_usize {
|
||||
($csr_number:expr) => {
|
||||
write_csr!($csr_number);
|
||||
|
||||
/// Writes the CSR
|
||||
#[inline]
|
||||
pub fn write(bits: usize) {
|
||||
unsafe{ _write(bits) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! set {
|
||||
($csr_number:expr) => {
|
||||
/// Set the CSR
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
unsafe fn _set(bits: usize) {
|
||||
asm!("csrrs x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||
unsafe fn _set(_bits: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! clear {
|
||||
($csr_number:expr) => {
|
||||
/// Clear the CSR
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
unsafe fn _clear(bits: usize) {
|
||||
asm!("csrrc x0, $1, $0" :: "r"(bits), "i"($csr_number) :: "volatile");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||
unsafe fn _clear(_bits: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! set_csr {
|
||||
($set_field:ident, $e:expr) => {
|
||||
#[inline]
|
||||
pub unsafe fn $set_field() {
|
||||
_set($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! clear_csr {
|
||||
($clear_field:ident, $e:expr) => {
|
||||
#[inline]
|
||||
pub unsafe fn $clear_field() {
|
||||
_clear($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! set_clear_csr {
|
||||
($set_field:ident, $clear_field:ident, $e:expr) => {
|
||||
set_csr!($set_field, $e);
|
||||
clear_csr!($clear_field, $e);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,9 @@
|
|||
//! - minstreth
|
||||
//! - mhpmcounter[3-31]h
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
pub mod mcause;
|
||||
pub mod mcycle;
|
||||
pub mod mcycleh;
|
||||
|
@ -22,3 +25,16 @@ pub mod misa;
|
|||
pub mod mstatus;
|
||||
pub mod mtvec;
|
||||
pub mod mvendorid;
|
||||
|
||||
pub mod sstatus;
|
||||
pub mod stvec;
|
||||
pub mod sie;
|
||||
pub mod sip;
|
||||
pub mod scause;
|
||||
pub mod stval;
|
||||
pub mod satp;
|
||||
pub mod sscratch;
|
||||
pub mod sepc;
|
||||
|
||||
pub mod time;
|
||||
pub mod timeh;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
//! satp register
|
||||
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
use bit_field::BitField;
|
||||
|
||||
/// satp register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Satp {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Satp {
|
||||
/// Returns the contents of the register as raw bits
|
||||
#[inline]
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// Current address-translation scheme
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub fn mode(&self) -> Mode {
|
||||
match self.bits.get_bit(31) {
|
||||
false => Mode::Bare,
|
||||
true => Mode::Sv32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Current address-translation scheme
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub fn mode(&self) -> Mode {
|
||||
match self.bits.get_bits(60..64) {
|
||||
0 => Mode::Bare,
|
||||
8 => Mode::Sv39,
|
||||
9 => Mode::Sv48,
|
||||
10 => Mode::Sv57,
|
||||
11 => Mode::Sv64,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Address space identifier
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub fn asid(&self) -> usize {
|
||||
self.bits.get_bits(22..31)
|
||||
}
|
||||
|
||||
/// Address space identifier
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub fn asid(&self) -> usize {
|
||||
self.bits.get_bits(44..60)
|
||||
}
|
||||
|
||||
/// Physical page number
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub fn ppn(&self) -> usize {
|
||||
self.bits.get_bits(0..22)
|
||||
}
|
||||
|
||||
/// Physical page number
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub fn ppn(&self) -> usize {
|
||||
self.bits.get_bits(0..44)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub enum Mode {
|
||||
Bare = 0,
|
||||
Sv32 = 1,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub enum Mode {
|
||||
Bare = 0,
|
||||
Sv39 = 8,
|
||||
Sv48 = 9,
|
||||
Sv57 = 10,
|
||||
Sv64 = 11,
|
||||
}
|
||||
|
||||
read_csr_as!(Satp, 0x180);
|
||||
write_csr!(0x180);
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
|
||||
let mut bits = 0usize;
|
||||
bits.set_bits(31..32, mode as usize);
|
||||
bits.set_bits(22..31, asid);
|
||||
bits.set_bits(0..22, ppn);
|
||||
_write(bits);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
|
||||
let mut bits = 0usize;
|
||||
bits.set_bits(60..64, mode as usize);
|
||||
bits.set_bits(44..60, asid);
|
||||
bits.set_bits(0..44, ppn);
|
||||
_write(bits);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
//! scause register
|
||||
|
||||
use bit_field::BitField;
|
||||
use core::mem::size_of;
|
||||
|
||||
/// scause register
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Scause {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
/// Trap Cause
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Trap {
|
||||
Interrupt(Interrupt),
|
||||
Exception(Exception),
|
||||
}
|
||||
|
||||
/// Interrupt
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Interrupt {
|
||||
UserSoft,
|
||||
SupervisorSoft,
|
||||
UserTimer,
|
||||
SupervisorTimer,
|
||||
UserExternal,
|
||||
SupervisorExternal,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Exception
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Exception {
|
||||
InstructionMisaligned,
|
||||
InstructionFault,
|
||||
IllegalInstruction,
|
||||
Breakpoint,
|
||||
LoadFault,
|
||||
StoreMisaligned,
|
||||
StoreFault,
|
||||
UserEnvCall,
|
||||
InstructionPageFault,
|
||||
LoadPageFault,
|
||||
StorePageFault,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Interrupt {
|
||||
pub fn from(nr: usize) -> Self {
|
||||
match nr {
|
||||
0 => Interrupt::UserSoft,
|
||||
1 => Interrupt::SupervisorSoft,
|
||||
4 => Interrupt::UserTimer,
|
||||
5 => Interrupt::SupervisorTimer,
|
||||
8 => Interrupt::UserExternal,
|
||||
9 => Interrupt::SupervisorExternal,
|
||||
_ => Interrupt::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Exception {
|
||||
pub fn from(nr: usize) -> Self {
|
||||
match nr {
|
||||
0 => Exception::InstructionMisaligned,
|
||||
1 => Exception::InstructionFault,
|
||||
2 => Exception::IllegalInstruction,
|
||||
3 => Exception::Breakpoint,
|
||||
5 => Exception::LoadFault,
|
||||
6 => Exception::StoreMisaligned,
|
||||
7 => Exception::StoreFault,
|
||||
8 => Exception::UserEnvCall,
|
||||
12 => Exception::InstructionPageFault,
|
||||
13 => Exception::LoadPageFault,
|
||||
15 => Exception::StorePageFault,
|
||||
_ => Exception::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Scause {
|
||||
/// Returns the contents of the register as raw bits
|
||||
#[inline]
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// Returns the code field
|
||||
pub fn code(&self) -> usize {
|
||||
let bit = 1 << (size_of::<usize>() * 8 - 1);
|
||||
self.bits & !bit
|
||||
}
|
||||
|
||||
/// Trap Cause
|
||||
#[inline]
|
||||
pub fn cause(&self) -> Trap {
|
||||
if self.is_interrupt() {
|
||||
Trap::Interrupt(Interrupt::from(self.code()))
|
||||
} else {
|
||||
Trap::Exception(Exception::from(self.code()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Is trap cause an interrupt.
|
||||
#[inline]
|
||||
pub fn is_interrupt(&self) -> bool {
|
||||
self.bits.get_bit(size_of::<usize>() * 8 - 1)
|
||||
}
|
||||
|
||||
/// Is trap cause an exception.
|
||||
#[inline]
|
||||
pub fn is_exception(&self) -> bool {
|
||||
!self.is_interrupt()
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Scause, 0x142);
|
|
@ -0,0 +1,4 @@
|
|||
//! sepc register
|
||||
|
||||
read_csr_as_usize!(0x141);
|
||||
write_csr_as_usize!(0x141);
|
|
@ -0,0 +1,70 @@
|
|||
//! sie register
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// sie register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Sie {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Sie {
|
||||
/// Returns the contents of the register as raw bits
|
||||
#[inline]
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// User Software Interrupt Enable
|
||||
#[inline]
|
||||
pub fn usoft(&self) -> bool {
|
||||
self.bits.get_bit(0)
|
||||
}
|
||||
|
||||
/// Supervisor Software Interrupt Enable
|
||||
#[inline]
|
||||
pub fn ssoft(&self) -> bool {
|
||||
self.bits.get_bit(1)
|
||||
}
|
||||
|
||||
/// User Timer Interrupt Enable
|
||||
#[inline]
|
||||
pub fn utimer(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
|
||||
/// Supervisor Timer Interrupt Enable
|
||||
#[inline]
|
||||
pub fn stimer(&self) -> bool {
|
||||
self.bits.get_bit(5)
|
||||
}
|
||||
|
||||
/// User External Interrupt Enable
|
||||
#[inline]
|
||||
pub fn uext(&self) -> bool {
|
||||
self.bits.get_bit(8)
|
||||
}
|
||||
|
||||
/// Supervisor External Interrupt Enable
|
||||
#[inline]
|
||||
pub fn sext(&self) -> bool {
|
||||
self.bits.get_bit(9)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Sie, 0x104);
|
||||
set!(0x104);
|
||||
clear!(0x104);
|
||||
|
||||
/// User Software Interrupt Enable
|
||||
set_clear_csr!(set_usoft, clear_usoft, 1 << 0);
|
||||
/// Supervisor Software Interrupt Enable
|
||||
set_clear_csr!(set_ssoft, clear_ssoft, 1 << 1);
|
||||
/// User Timer Interrupt Enable
|
||||
set_clear_csr!(set_utimer, clear_utimer, 1 << 4);
|
||||
/// Supervisor Timer Interrupt Enable
|
||||
set_clear_csr!(set_stimer, clear_stimer, 1 << 5);
|
||||
/// User External Interrupt Enable
|
||||
set_clear_csr!(set_uext, clear_uext, 1 << 8);
|
||||
/// Supervisor External Interrupt Enable
|
||||
set_clear_csr!(set_sext, clear_sext, 1 << 9);
|
|
@ -0,0 +1,55 @@
|
|||
//! sip register
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// sip register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Sip {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Sip {
|
||||
/// Returns the contents of the register as raw bits
|
||||
#[inline]
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// User Software Interrupt Pending
|
||||
#[inline]
|
||||
pub fn usoft(&self) -> bool {
|
||||
self.bits.get_bit(0)
|
||||
}
|
||||
|
||||
/// Supervisor Software Interrupt Pending
|
||||
#[inline]
|
||||
pub fn ssoft(&self) -> bool {
|
||||
self.bits.get_bit(1)
|
||||
}
|
||||
|
||||
/// User Timer Interrupt Pending
|
||||
#[inline]
|
||||
pub fn utimer(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
|
||||
/// Supervisor Timer Interrupt Pending
|
||||
#[inline]
|
||||
pub fn stimer(&self) -> bool {
|
||||
self.bits.get_bit(5)
|
||||
}
|
||||
|
||||
/// User External Interrupt Pending
|
||||
#[inline]
|
||||
pub fn uext(&self) -> bool {
|
||||
self.bits.get_bit(8)
|
||||
}
|
||||
|
||||
/// Supervisor External Interrupt Pending
|
||||
#[inline]
|
||||
pub fn sext(&self) -> bool {
|
||||
self.bits.get_bit(9)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Sip, 0x144);
|
|
@ -0,0 +1,4 @@
|
|||
//! sscratch register
|
||||
|
||||
read_csr_as_usize!(0x140);
|
||||
write_csr_as_usize!(0x140);
|
|
@ -0,0 +1,136 @@
|
|||
//! sstatus register
|
||||
|
||||
use bit_field::BitField;
|
||||
use core::mem::size_of;
|
||||
|
||||
/// Supervisor Status Register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Sstatus {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
/// Supervisor Previous Privilege Mode
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum SPP {
|
||||
Supervisor = 1,
|
||||
User = 0,
|
||||
}
|
||||
|
||||
/// Floating-point unit Status
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum FS {
|
||||
Off = 0,
|
||||
Initial = 1,
|
||||
Clean = 2,
|
||||
Dirty = 3,
|
||||
}
|
||||
|
||||
impl Sstatus {
|
||||
/// User Interrupt Enable
|
||||
#[inline]
|
||||
pub fn uie(&self) -> bool {
|
||||
self.bits.get_bit(0)
|
||||
}
|
||||
|
||||
/// Supervisor Interrupt Enable
|
||||
#[inline]
|
||||
pub fn sie(&self) -> bool {
|
||||
self.bits.get_bit(1)
|
||||
}
|
||||
|
||||
/// User Previous Interrupt Enable
|
||||
#[inline]
|
||||
pub fn upie(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
|
||||
/// Supervisor Previous Interrupt Enable
|
||||
#[inline]
|
||||
pub fn spie(&self) -> bool {
|
||||
self.bits.get_bit(5)
|
||||
}
|
||||
|
||||
/// Supervisor Previous Privilege Mode
|
||||
#[inline]
|
||||
pub fn spp(&self) -> SPP {
|
||||
match self.bits.get_bit(8) {
|
||||
true => SPP::Supervisor,
|
||||
false => SPP::User,
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of the floating-point unit
|
||||
#[inline]
|
||||
pub fn fs(&self) -> FS {
|
||||
match self.bits.get_bits(13..15) {
|
||||
0 => FS::Off,
|
||||
1 => FS::Initial,
|
||||
2 => FS::Clean,
|
||||
3 => FS::Dirty,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of additional user-mode extensions
|
||||
/// and associated state
|
||||
#[inline]
|
||||
pub fn xs(&self) -> FS {
|
||||
match self.bits.get_bits(15..17) {
|
||||
0 => FS::Off,
|
||||
1 => FS::Initial,
|
||||
2 => FS::Clean,
|
||||
3 => FS::Dirty,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Permit Supervisor User Memory access
|
||||
#[inline]
|
||||
pub fn sum(&self) -> bool {
|
||||
self.bits.get_bit(18)
|
||||
}
|
||||
|
||||
/// Make eXecutable Readable
|
||||
#[inline]
|
||||
pub fn mxr(&self) -> bool {
|
||||
self.bits.get_bit(19)
|
||||
}
|
||||
|
||||
/// Whether either the FS field or XS field
|
||||
/// signals the presence of some dirty state
|
||||
#[inline]
|
||||
pub fn sd(&self) -> bool {
|
||||
self.bits.get_bit(size_of::<usize>() * 8 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Sstatus, 0x100);
|
||||
set!(0x100);
|
||||
clear!(0x100);
|
||||
|
||||
/// User Interrupt Enable
|
||||
set_clear_csr!(set_uie, clear_uie, 1 << 0);
|
||||
/// Supervisor Interrupt Enable
|
||||
set_clear_csr!(set_sie, clear_sie, 1 << 1);
|
||||
/// User Previous Interrupt Enable
|
||||
set_csr!(set_upie, 1 << 4);
|
||||
/// Supervisor Previous Interrupt Enable
|
||||
set_csr!(set_spie, 1 << 5);
|
||||
/// Make eXecutable Readable
|
||||
set_clear_csr!(set_mxr, clear_mxr, 1 << 19);
|
||||
/// Permit Supervisor User Memory access
|
||||
set_clear_csr!(set_sum, clear_sum, 1 << 18);
|
||||
|
||||
/// Supervisor Previous Privilege Mode
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
pub unsafe fn set_spp(spp: SPP) {
|
||||
_set((spp as usize) << 8);
|
||||
}
|
||||
|
||||
/// The status of the floating-point unit
|
||||
#[inline]
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
pub unsafe fn set_fs(fs: FS) {
|
||||
_set((fs as usize) << 13);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
//! stval register
|
||||
|
||||
read_csr_as_usize!(0x143);
|
|
@ -0,0 +1,45 @@
|
|||
//! stvec register
|
||||
|
||||
/// stvec register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Stvec {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
/// Trap mode
|
||||
pub enum TrapMode {
|
||||
Direct = 0,
|
||||
Vectored = 1,
|
||||
}
|
||||
|
||||
impl Stvec {
|
||||
/// Returns the contents of the register as raw bits
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// Returns the trap-vector base-address
|
||||
pub fn address(&self) -> usize {
|
||||
self.bits - (self.bits & 0b11)
|
||||
}
|
||||
|
||||
/// Returns the trap-vector mode
|
||||
pub fn trap_mode(&self) -> TrapMode {
|
||||
let mode = self.bits & 0b11;
|
||||
match mode {
|
||||
0 => TrapMode::Direct,
|
||||
1 => TrapMode::Vectored,
|
||||
_ => unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Stvec, 0x105);
|
||||
write_csr!(0x105);
|
||||
|
||||
/// Writes the CSR
|
||||
#[inline]
|
||||
#[cfg_attr(not(any(target_arch = "riscv32", target_arch = "riscv64")), allow(unused_variables))]
|
||||
pub unsafe fn write(addr: usize, mode: TrapMode) {
|
||||
_write(addr + mode as usize);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
//! time register
|
||||
|
||||
read_csr_as_usize!(0xC01);
|
|
@ -0,0 +1,18 @@
|
|||
//! timeh register
|
||||
|
||||
/// Reads the CSR
|
||||
#[inline]
|
||||
pub fn read() -> usize {
|
||||
match () {
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
() => {
|
||||
let r: usize;
|
||||
unsafe {
|
||||
asm!("csrrs $0, 0xC81, x0" : "=r"(r) ::: "volatile");
|
||||
}
|
||||
r
|
||||
}
|
||||
#[cfg(not(target_arch = "riscv32"))]
|
||||
() => unimplemented!(),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue