diff --git a/Cargo.toml b/Cargo.toml index d3e0314..2ebf0f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "riscv" -version = "0.5.0" +version = "0.5.1" repository = "https://github.com/rust-embedded/riscv" authors = ["The RISC-V Team "] categories = ["embedded", "hardware-support", "no-std"] diff --git a/asm.S b/asm.S index 89890be..1a83960 100644 --- a/asm.S +++ b/asm.S @@ -36,7 +36,7 @@ REG_SET_CLEAR(mie, 0x304) REG_READ(minstret, 0xB02) REG_READ(mip, 0x344) REG_READ(misa, 0x301) -REG_READ(mstatus, 0x300) +REG_READ_WRITE(mstatus, 0x300) REG_SET_CLEAR(mstatus, 0x300) REG_READ_WRITE(mtvec, 0x305) REG_READ(mvendorid, 0xF11) @@ -49,7 +49,7 @@ REG_READ(sie, 0x104) REG_SET_CLEAR(sie, 0x104) REG_READ(sip, 0x144) REG_READ_WRITE(sscratch, 0x140) -REG_READ(sstatus, 0x100) +REG_READ_WRITE(sstatus, 0x100) REG_SET_CLEAR(sstatus, 0x100) REG_READ(stval, 0x143) REG_READ_WRITE(stvec, 0x105) diff --git a/bin/riscv32imac-unknown-none-elf.a b/bin/riscv32imac-unknown-none-elf.a index 2bb3df2..bf9a206 100644 Binary files a/bin/riscv32imac-unknown-none-elf.a and b/bin/riscv32imac-unknown-none-elf.a differ diff --git a/bin/riscv32imc-unknown-none-elf.a b/bin/riscv32imc-unknown-none-elf.a index 2bb3df2..bf9a206 100644 Binary files a/bin/riscv32imc-unknown-none-elf.a and b/bin/riscv32imc-unknown-none-elf.a differ diff --git a/bin/riscv64gc-unknown-none-elf.a b/bin/riscv64gc-unknown-none-elf.a index a640944..8510d50 100644 Binary files a/bin/riscv64gc-unknown-none-elf.a and b/bin/riscv64gc-unknown-none-elf.a differ diff --git a/bin/riscv64imac-unknown-none-elf.a b/bin/riscv64imac-unknown-none-elf.a index a640944..8510d50 100644 Binary files a/bin/riscv64imac-unknown-none-elf.a and b/bin/riscv64imac-unknown-none-elf.a differ diff --git a/src/register/mstatus.rs b/src/register/mstatus.rs index d60792d..3988097 100644 --- a/src/register/mstatus.rs +++ b/src/register/mstatus.rs @@ -1,12 +1,37 @@ //! mstatus register // TODO: Virtualization, Memory Privilege and Extension Context Fields +use bit_field::BitField; + /// mstatus register #[derive(Clone, Copy, Debug)] pub struct Mstatus { bits: usize, } +/// Additional extension state +pub enum XS { + /// All off + AllOff = 0, + + /// None dirty or clean, some on + NoneDirtyOrClean = 1, + + /// None dirty, some clean + NoneDirtySomeClean = 2, + + /// Some dirty + SomeDirty = 3, +} + +/// Floating-point extension state +pub enum FS { + Off = 0, + Initial = 1, + Clean = 2, + Dirty = 3, +} + /// Machine Previous Privilege Mode pub enum MPP { Machine = 3, @@ -24,43 +49,43 @@ impl Mstatus { /// User Interrupt Enable #[inline] pub fn uie(&self) -> bool { - self.bits & (1 << 0) == 1 << 0 + self.bits.get_bit(0) } /// Supervisor Interrupt Enable #[inline] pub fn sie(&self) -> bool { - self.bits & (1 << 1) == 1 << 1 + self.bits.get_bit(1) } /// Machine Interrupt Enable #[inline] pub fn mie(&self) -> bool { - self.bits & (1 << 3) == 1 << 3 + self.bits.get_bit(3) } /// User Previous Interrupt Enable #[inline] pub fn upie(&self) -> bool { - self.bits & (1 << 4) == 1 << 4 + self.bits.get_bit(4) } /// Supervisor Previous Interrupt Enable #[inline] pub fn spie(&self) -> bool { - self.bits & (1 << 5) == 1 << 5 + self.bits.get_bit(5) } /// User Previous Interrupt Enable #[inline] pub fn mpie(&self) -> bool { - self.bits & (1 << 7) == 1 << 7 + self.bits.get_bit(7) } /// Supervisor Previous Privilege Mode #[inline] pub fn spp(&self) -> SPP { - match self.bits & (1 << 8) == (1 << 8) { + match self.bits.get_bit(8) { true => SPP::Supervisor, false => SPP::User, } @@ -69,45 +94,95 @@ impl Mstatus { /// Machine Previous Privilege Mode #[inline] pub fn mpp(&self) -> MPP { - match (self.bits & (0b11 << 11)) >> 11 { + match self.bits.get_bits(11..13) { 0b00 => MPP::User, 0b01 => MPP::Supervisor, 0b11 => MPP::Machine, _ => unreachable!(), } } + + /// Floating-point extension state + /// + /// Encodes the status of the floating-point unit, + /// including the CSR `fcsr` and floating-point data registers `f0–f31`. + #[inline] + pub fn fs(&self) -> FS { + match self.bits.get_bits(13..15) { + 0b00 => FS::Off, + 0b01 => FS::Initial, + 0b10 => FS::Clean, + 0b11 => FS::Dirty, + _ => unreachable!(), + } + } + + /// Additional extension state + /// + /// Encodes the status of additional user-mode extensions and associated state. + #[inline] + pub fn xs(&self) -> XS { + match self.bits.get_bits(15..17) { + 0b00 => XS::AllOff, + 0b01 => XS::NoneDirtyOrClean, + 0b10 => XS::NoneDirtySomeClean, + 0b11 => XS::SomeDirty, + _ => unreachable!(), + } + } } read_csr_as!(Mstatus, 0x300, __read_mstatus); +write_csr!(0x300, __write_mstatus); set!(0x300, __set_mstatus); clear!(0x300, __clear_mstatus); set_clear_csr!( /// User Interrupt Enable , set_uie, clear_uie, 1 << 0); + set_clear_csr!( /// Supervisor Interrupt Enable , set_sie, clear_sie, 1 << 1); + set_clear_csr!( /// Machine Interrupt Enable , set_mie, clear_mie, 1 << 3); + set_csr!( /// User Previous Interrupt Enable , set_upie, 1 << 4); + set_csr!( /// Supervisor Previous Interrupt Enable , set_spie, 1 << 5); + set_csr!( /// Machine Previous Interrupt Enable , set_mpie, 1 << 7); + /// Supervisor Previous Privilege Mode #[inline] pub unsafe fn set_spp(spp: SPP) { - _set((spp as usize) << 8); + match spp { + SPP::Supervisor => _set(1 << 8), + SPP::User => _clear(1 << 8), + } } + /// Machine Previous Privilege Mode #[inline] pub unsafe fn set_mpp(mpp: MPP) { - _set((mpp as usize) << 11); + let mut value = _read(); + value.set_bits(11..13, mpp as usize); + _write(value); +} + +/// Floating-point extension state +#[inline] +pub unsafe fn set_fs(fs: FS) { + let mut value = _read(); + value.set_bits(13..15, fs as usize); + _write(value); } diff --git a/src/register/sstatus.rs b/src/register/sstatus.rs index 7ae3d4e..ec4765a 100644 --- a/src/register/sstatus.rs +++ b/src/register/sstatus.rs @@ -105,6 +105,7 @@ impl Sstatus { } read_csr_as!(Sstatus, 0x100, __read_sstatus); +write_csr!(0x100, __write_sstatus); set!(0x100, __set_sstatus); clear!(0x100, __clear_sstatus); @@ -131,12 +132,17 @@ set_clear_csr!( #[inline] #[cfg(riscv)] pub unsafe fn set_spp(spp: SPP) { - _set((spp as usize) << 8); + match spp { + SPP::Supervisor => _set(1 << 8), + SPP::User => _clear(1 << 8), + } } /// The status of the floating-point unit #[inline] #[cfg(riscv)] pub unsafe fn set_fs(fs: FS) { - _set((fs as usize) << 13); + let mut value = _read(); + value.set_bits(13..15, fs as usize); + _write(value); }