Kaynağa Gözat

Merge #24

24: Add FS and XS fields, fix incorrect field setting, bump version r=dvc94ch a=Disasm



Co-authored-by: Vadim Kaushan <admin@disasm.info>
bors[bot] 6 yıl önce
ebeveyn
işleme
6425cab701

+ 1 - 1
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 <risc-v@teams.rust-embedded.org>"]
 categories = ["embedded", "hardware-support", "no-std"]

+ 2 - 2
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)

BIN
bin/riscv32imac-unknown-none-elf.a


BIN
bin/riscv32imc-unknown-none-elf.a


BIN
bin/riscv64gc-unknown-none-elf.a


BIN
bin/riscv64imac-unknown-none-elf.a


+ 85 - 10
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);
 }

+ 8 - 2
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);
 }