Merge #32
32: add user trap setup and handling registers r=almindor a=almindor Adds CSR handlers for user trap setup and handling registers. Also unifies common shared types. NOTE: untested, will test on real device ASAP Co-authored-by: Ales Katona <almindor@gmail.com>
This commit is contained in:
commit
0eda3c511c
|
@ -13,11 +13,17 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// TODO: User Trap Setup
|
||||
|
||||
|
||||
// TODO: User Trap Handling
|
||||
// User Trap Setup
|
||||
pub mod ustatus;
|
||||
pub mod uie;
|
||||
pub mod utvec;
|
||||
|
||||
// User Trap Handling
|
||||
pub mod uscratch;
|
||||
pub mod uepc;
|
||||
pub mod ucause;
|
||||
pub mod utval;
|
||||
pub mod uip;
|
||||
|
||||
// User Floating-Point CSRs
|
||||
// TODO: frm, fflags
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// TODO: Virtualization, Memory Privilege and Extension Context Fields
|
||||
|
||||
use bit_field::BitField;
|
||||
use core::mem::size_of;
|
||||
|
||||
/// mstatus register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -80,7 +81,7 @@ impl Mstatus {
|
|||
self.bits.get_bit(5)
|
||||
}
|
||||
|
||||
/// User Previous Interrupt Enable
|
||||
/// Machine Previous Interrupt Enable
|
||||
#[inline]
|
||||
pub fn mpie(&self) -> bool {
|
||||
self.bits.get_bit(7)
|
||||
|
@ -134,6 +135,13 @@ impl Mstatus {
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,6 @@ impl Interrupt {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl Exception {
|
||||
pub fn from(nr: usize) -> Self {
|
||||
match nr {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use bit_field::BitField;
|
||||
use core::mem::size_of;
|
||||
pub use super::mstatus::FS;
|
||||
|
||||
/// Supervisor Status Register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -16,15 +17,6 @@ pub enum SPP {
|
|||
User = 0,
|
||||
}
|
||||
|
||||
/// Floating-point unit Status
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum FS {
|
||||
Off = 0,
|
||||
Initial = 1,
|
||||
Clean = 2,
|
||||
Dirty = 3,
|
||||
}
|
||||
|
||||
impl Sstatus {
|
||||
/// User Interrupt Enable
|
||||
#[inline]
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
//! stvec register
|
||||
|
||||
pub use crate::register::mtvec::TrapMode;
|
||||
|
||||
/// stvec register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Stvec {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
/// Trap mode
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum TrapMode {
|
||||
Direct = 0,
|
||||
Vectored = 1,
|
||||
}
|
||||
|
||||
impl Stvec {
|
||||
/// Returns the contents of the register as raw bits
|
||||
pub fn bits(&self) -> usize {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//! ucause register
|
||||
|
||||
/// ucause register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Ucause {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Ucause {
|
||||
/// Returns the contents of the register as raw bits
|
||||
#[inline]
|
||||
pub fn bits(&self) -> usize {
|
||||
self.bits
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Ucause, 0x042, __read_ucause);
|
|
@ -0,0 +1,4 @@
|
|||
//! uepc register
|
||||
|
||||
read_csr_as_usize!(0x041, __read_uepc);
|
||||
write_csr_as_usize!(0x041, __write_uepc);
|
|
@ -0,0 +1,49 @@
|
|||
//! uie register
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// uie register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Uie {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Uie {
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// User Timer Interrupt Enable
|
||||
#[inline]
|
||||
pub fn utimer(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
|
||||
/// User External Interrupt Enable
|
||||
#[inline]
|
||||
pub fn uext(&self) -> bool {
|
||||
self.bits.get_bit(8)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Uie, 0x004, __read_uie);
|
||||
set!(0x004, __set_uie);
|
||||
clear!(0x004, __clear_uie);
|
||||
|
||||
set_clear_csr!(
|
||||
/// User Software Interrupt Enable
|
||||
, set_usoft, clear_usoft, 1 << 0);
|
||||
set_clear_csr!(
|
||||
/// User Timer Interrupt Enable
|
||||
, set_utimer, clear_utimer, 1 << 4);
|
||||
set_clear_csr!(
|
||||
/// User External Interrupt Enable
|
||||
, set_uext, clear_uext, 1 << 8);
|
|
@ -0,0 +1,37 @@
|
|||
//! uip register
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// uip register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Uip {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Uip {
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// User Timer Interrupt Pending
|
||||
#[inline]
|
||||
pub fn utimer(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
|
||||
/// User External Interrupt Pending
|
||||
#[inline]
|
||||
pub fn uext(&self) -> bool {
|
||||
self.bits.get_bit(8)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Uip, 0x044, __read_uip);
|
|
@ -0,0 +1,4 @@
|
|||
//! uscratch register
|
||||
|
||||
read_csr_as_usize!(0x040, __read_uscratch);
|
||||
write_csr_as_usize!(0x040, __write_uscratch);
|
|
@ -0,0 +1,37 @@
|
|||
//! ustatus register
|
||||
// TODO: Virtualization, Memory Privilege and Extension Context Fields
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// ustatus register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Ustatus {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Ustatus {
|
||||
/// User Interrupt Enable
|
||||
#[inline]
|
||||
pub fn uie(&self) -> bool {
|
||||
self.bits.get_bit(0)
|
||||
}
|
||||
|
||||
/// User Previous Interrupt Enable
|
||||
#[inline]
|
||||
pub fn upie(&self) -> bool {
|
||||
self.bits.get_bit(4)
|
||||
}
|
||||
}
|
||||
|
||||
read_csr_as!(Ustatus, 0x000, __read_ustatus);
|
||||
write_csr!(0x000, __write_ustatus);
|
||||
set!(0x000, __set_ustatus);
|
||||
clear!(0x000, __clear_ustatus);
|
||||
|
||||
set_clear_csr!(
|
||||
/// User Interrupt Enable
|
||||
, set_uie, clear_uie, 1 << 0);
|
||||
|
||||
set_csr!(
|
||||
/// User Previous Interrupt Enable
|
||||
, set_upie, 1 << 4);
|
|
@ -0,0 +1,3 @@
|
|||
//! utval register
|
||||
|
||||
read_csr_as_usize!(0x043, __read_utval);
|
|
@ -0,0 +1,40 @@
|
|||
//! stvec register
|
||||
|
||||
pub use crate::register::mtvec::TrapMode;
|
||||
|
||||
/// stvec register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Utvec {
|
||||
bits: usize,
|
||||
}
|
||||
|
||||
impl Utvec {
|
||||
/// 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!(Utvec, 0x005, __read_utvec);
|
||||
write_csr!(0x005, __write_utvec);
|
||||
|
||||
/// Writes the CSR
|
||||
#[inline]
|
||||
pub unsafe fn write(addr: usize, mode: TrapMode) {
|
||||
_write(addr + mode as usize);
|
||||
}
|
Loading…
Reference in New Issue