浏览代码

Merge branch 'rust-embedded:master' into master

dkhayes117 3 年之前
父节点
当前提交
5558865fc8

+ 7 - 1
.github/bors.toml

@@ -1,4 +1,10 @@
 block_labels = ["needs-decision"]
 delete_merged_branches = true
 required_approvals = 1
-status = ["continuous-integration/travis-ci/push"]
+status = [
+    "ci-linux (stable)",
+    "ci-linux (1.42.0)",
+    "build-other (macOS-latest)",
+    "build-other (windows-latest)",
+    "Rustfmt"
+]

+ 61 - 0
.github/workflows/ci.yaml

@@ -0,0 +1,61 @@
+on:
+  push:
+    branches: [ staging, trying, master ]
+  pull_request:
+
+name: Continuous integration
+
+jobs:
+  ci-linux:
+    runs-on: ubuntu-20.04
+    continue-on-error: ${{ matrix.experimental || false }}
+    strategy:
+      matrix:
+        # All generated code should be running on stable now, MRSV is 1.42.0
+        rust: [nightly, stable, 1.42.0]
+
+        include:
+          # Nightly is only for reference and allowed to fail
+          - rust: nightly
+            experimental: true
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: ${{ matrix.rust }}
+          override: true
+      - name: Install all Rust targets for ${{ matrix.rust }}
+        run: rustup target install --toolchain=${{ matrix.rust }} x86_64-unknown-linux-gnu riscv32imac-unknown-none-elf riscv64imac-unknown-none-elf riscv64gc-unknown-none-elf
+      - name: Install riscv gcc
+        run: sudo apt-get update && sudo apt-get install -y gcc-riscv64-unknown-elf
+      - name: Run CI script for x86_64-unknown-linux-gnu under ${{ matrix.rust }}
+        run: cargo check --target x86_64-unknown-linux-gnu
+      - name: Run CI script for riscv32imac-unknown-none-elf under ${{ matrix.rust }}
+        run: cargo check --target riscv32imac-unknown-none-elf
+      - name: Run CI script for riscv64imac-unknown-none-elf under ${{ matrix.rust }}
+        run: cargo check --target riscv64imac-unknown-none-elf
+      - name: Run CI script for riscv64gc-unknown-none-elf under ${{ matrix.rust }}
+        run: cargo check --target riscv64gc-unknown-none-elf
+      - name: Check blobs
+        run: ./check-blobs.sh
+
+  # On macOS and Windows, we at least make sure that the crate builds and links.
+  build-other:
+    strategy:
+      matrix:
+        os:
+          - macOS-latest
+          - windows-latest
+    runs-on: ${{ matrix.os }}
+
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+      - name: Build crate for host OS
+        run: cargo build

+ 24 - 0
.github/workflows/rustfmt.yaml

@@ -0,0 +1,24 @@
+
+on:
+  push:
+    branches: [ staging, trying, master ]
+  pull_request:
+
+name: Code formatting check
+
+jobs:
+  fmt:
+    name: Rustfmt
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          override: true
+          components: rustfmt
+      - uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: --all -- --check

+ 0 - 51
.travis.yml

@@ -1,51 +0,0 @@
-language: rust
-
-env:
-  - TARGET=x86_64-unknown-linux-gnu
-  - TARGET=riscv32imac-unknown-none-elf
-  - TARGET=riscv64imac-unknown-none-elf
-  - TARGET=riscv64gc-unknown-none-elf
-
-rust:
-  - nightly
-  - stable
-  - 1.42.0 # MSRV
-
-if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
-
-matrix:
-  allow_failures:
-    - rust: nightly
-
-  include:
-    - env: CHECK_BLOBS=1
-      rust:
-      language: bash
-      if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
-
-    - env: RUSTFMT=1
-      rust: stable
-      if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
-
-
-install:
-  - ci/install.sh
-
-script:
-  - ci/script.sh
-
-
-cache:
-  cargo: true
-  directories:
-    - gcc
-
-branches:
-  only:
-    - master
-    - staging
-    - trying
-
-notifications:
-  email:
-    on_success: never

+ 17 - 0
CHANGELOG.md

@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [v0.7.0] - 2020-07-29
+
+### Added
+
+- Add `medeleg` register
+- Add `cycle[h]`, `instret[h]` and `mcounteren`
+- Add additional binaries for floating-point ABIs
+- Add support for `mxr`
+- Add support for `mprv`
+
+### Changed
+
+- Fix `scause::set`
+- Various formatting and comment fixes
+- Update `bare-metal` to `v1.0.0` removing `Nr` trait
+- Build targets on `docs.rs` are now RISC-V targets other than default ones
+
 ## [v0.6.0] - 2020-06-20
 
 ### Changed

+ 9 - 2
Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "riscv"
-version = "0.6.0"
+version = "0.7.0"
 repository = "https://github.com/rust-embedded/riscv"
 authors = ["The RISC-V Team <risc-v@teams.rust-embedded.org>"]
 categories = ["embedded", "hardware-support", "no-std"]
@@ -8,8 +8,15 @@ description = "Low level access to RISC-V processors"
 keywords = ["riscv", "register", "peripheral"]
 license = "ISC"
 
+[package.metadata.docs.rs]
+default-target = "riscv64imac-unknown-none-elf"
+targets = [
+    "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf",
+    "riscv64imac-unknown-none-elf", "riscv64gc-unknown-none-elf",
+]
+
 [dependencies]
-bare-metal = "0.2.5"
+bare-metal = "1.0.0"
 bit_field = "0.10.0"
 
 [build-dependencies]

+ 1 - 1
README.md

@@ -38,4 +38,4 @@ Conduct][CoC], the maintainer of this crate, the [RISC-V team][team], promises
 to intervene to uphold that code of conduct.
 
 [CoC]: CODE_OF_CONDUCT.md
-[team]: https://github.com/rust-embedded/wg#the-riscv-team
+[team]: https://github.com/rust-embedded/wg#the-risc-v-team

+ 24 - 0
assemble.ps1

@@ -17,4 +17,28 @@ riscv64-unknown-elf-ar crs bin/riscv64i-unknown-none-elf.a bin/$crate.o
 riscv64-unknown-elf-gcc -c -mabi=lp64 -march=rv64ic asm.S -o bin/$crate.o
 riscv64-unknown-elf-ar crs bin/riscv64ic-unknown-none-elf.a bin/$crate.o
 
+riscv64-unknown-elf-gcc -c -mabi=ilp32f -march=rv32if asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv32if-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32f -march=rv32ifc asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv32ifc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64f -march=rv64if asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv64if-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64f -march=rv64ifc asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv64ifc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32d -march=rv32ifd asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv32ifd-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32d -march=rv32ifdc asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv32ifdc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64d -march=rv64ifd asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv64ifd-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64d -march=rv64ifdc asm.S -o bin/$crate.o
+riscv64-unknown-elf-ar crs bin/riscv64ifdc-unknown-none-elf.a bin/$crate.o
+
 Remove-Item bin/$crate.o

+ 24 - 0
assemble.sh

@@ -19,4 +19,28 @@ ar crs bin/riscv64i-unknown-none-elf.a bin/$crate.o
 riscv64-unknown-elf-gcc -c -mabi=lp64 -march=rv64ic asm.S -o bin/$crate.o
 ar crs bin/riscv64ic-unknown-none-elf.a bin/$crate.o
 
+riscv64-unknown-elf-gcc -c -mabi=ilp32f -march=rv32if asm.S -o bin/$crate.o
+ar crs bin/riscv32if-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32f -march=rv32ifc asm.S -o bin/$crate.o
+ar crs bin/riscv32ifc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64f -march=rv64if asm.S -o bin/$crate.o
+ar crs bin/riscv64if-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64f -march=rv64ifc asm.S -o bin/$crate.o
+ar crs bin/riscv64ifc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32d -march=rv32ifd asm.S -o bin/$crate.o
+ar crs bin/riscv32ifd-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=ilp32d -march=rv32ifdc asm.S -o bin/$crate.o
+ar crs bin/riscv32ifdc-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64d -march=rv64ifd asm.S -o bin/$crate.o
+ar crs bin/riscv64ifd-unknown-none-elf.a bin/$crate.o
+
+riscv64-unknown-elf-gcc -c -mabi=lp64d -march=rv64ifdc asm.S -o bin/$crate.o
+ar crs bin/riscv64ifdc-unknown-none-elf.a bin/$crate.o
+
 rm bin/$crate.o

二进制
bin/riscv32i-unknown-none-elf.a


二进制
bin/riscv32ic-unknown-none-elf.a


二进制
bin/riscv32if-unknown-none-elf.a


二进制
bin/riscv32ifc-unknown-none-elf.a


二进制
bin/riscv32ifd-unknown-none-elf.a


二进制
bin/riscv32ifdc-unknown-none-elf.a


二进制
bin/riscv64i-unknown-none-elf.a


二进制
bin/riscv64ic-unknown-none-elf.a


二进制
bin/riscv64if-unknown-none-elf.a


二进制
bin/riscv64ifc-unknown-none-elf.a


二进制
bin/riscv64ifd-unknown-none-elf.a


二进制
bin/riscv64ifdc-unknown-none-elf.a


+ 1 - 1
build.rs

@@ -11,7 +11,7 @@ fn main() {
 
     if target.starts_with("riscv") && env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() {
         let mut target = Target::from_target_str(&target);
-        target.retain_extensions("ic");
+        target.retain_extensions("ifdc");
 
         let target = target.to_string();
 

+ 0 - 18
ci/install.sh

@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-set -euxo pipefail
-
-if [ -n "${TARGET:-}" ]; then
-    rustup target add $TARGET
-fi
-
-if [ -n "${CHECK_BLOBS:-}" ]; then
-    if [ ! -d gcc/bin ]; then
-        mkdir -p gcc
-        curl -L https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.1.0-2018.12.0-x86_64-linux-ubuntu14.tar.gz | tar --strip-components=1 -C gcc -xz
-    fi
-fi
-
-if [ -n "${RUSTFMT:-}" ]; then
-    rustup component add rustfmt
-fi

+ 0 - 20
ci/script.sh

@@ -1,20 +0,0 @@
-#!/usr/bin/env bash
-
-set -euxo pipefail
-
-if [ -n "${TARGET:-}" ]; then
-    cargo check --target $TARGET
-
-    if [ $TRAVIS_RUST_VERSION = nightly ]; then
-        cargo check --target $TARGET --features inline-asm
-    fi
-fi
-
-if [ -n "${CHECK_BLOBS:-}" ]; then
-    PATH="$PATH:$PWD/gcc/bin"
-    ./check-blobs.sh
-fi
-
-if [ -n "${RUSTFMT:-}" ]; then
-    cargo fmt -- --check
-fi

+ 1 - 1
src/interrupt.rs

@@ -1,7 +1,7 @@
 //! Interrupts
 
 // NOTE: Adapted from cortex-m/src/interrupt.rs
-pub use bare_metal::{CriticalSection, Mutex, Nr};
+pub use bare_metal::{CriticalSection, Mutex};
 use register::mstatus;
 
 /// Disables all interrupts

+ 1 - 0
src/register/cycle.rs

@@ -1,4 +1,5 @@
 //! cycle register
+//!
 //! Shadow of mcycle register
 //! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/cycleh.rs

@@ -1,4 +1,5 @@
 //! cycleh register
+//!
 //! Shadow of mcycleh register (rv32)
 //! must have `scounteren::cy` or `mcounteren::cy` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/instret.rs

@@ -1,4 +1,5 @@
 //! instret register
+//!
 //! Shadow of minstret register
 //! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
 //! S-mode is implemented or not

+ 1 - 0
src/register/instreth.rs

@@ -1,4 +1,5 @@
 //! instreth register
+//!
 //! Shadow of minstreth register (rv32)
 //! must have `scounteren::ir` or `mcounteren::ir` bit enabled depending on whether
 //! S-mode is implemented or not

+ 4 - 4
src/register/mcounteren.rs

@@ -9,25 +9,25 @@ pub struct Mcounteren {
 }
 
 impl Mcounteren {
-    /// Supervisor "cycle[h]" Enable
+    /// Supervisor "cycle\[h\]" Enable
     #[inline]
     pub fn cy(&self) -> bool {
         self.bits.get_bit(0)
     }
 
-    /// Supervisor "time[h]" Enable
+    /// Supervisor "time\[h\]" Enable
     #[inline]
     pub fn tm(&self) -> bool {
         self.bits.get_bit(1)
     }
 
-    /// Supervisor "instret[h]" Enable
+    /// Supervisor "instret\[h\]" Enable
     #[inline]
     pub fn ir(&self) -> bool {
         self.bits.get_bit(2)
     }
 
-    /// Supervisor "hpm[x]" Enable (bits 3-31)
+    /// Supervisor "hpm\[x\]" Enable (bits 3-31)
     #[inline]
     pub fn hpm(&self, index: usize) -> bool {
         assert!(3 <= index && index < 32);

+ 84 - 6
src/register/mstatus.rs

@@ -1,5 +1,11 @@
 //! mstatus register
-// TODO: Virtualization, Memory Privilege and Extension Context Fields
+
+// FIXME: in 1.12 spec there will be `SBE` and `MBE` bits.
+// They allows to execute supervisor in given big endian,
+// they would be in a new register `mstatush` in RV32; we should implement `mstatush`
+// at that time.
+// FIXME: `SXL` and `UXL` bits require a structure interpreting XLEN,
+// which would be the best way we implement this using Rust?
 
 use bit_field::BitField;
 use core::mem::size_of;
@@ -136,6 +142,65 @@ impl Mstatus {
         }
     }
 
+    /// Modify Memory PRiVilege
+    #[inline]
+    pub fn mprv(&self) -> bool {
+        self.bits.get_bit(17)
+    }
+
+    /// 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)
+    }
+
+    /// Trap Virtual Memory
+    ///
+    /// If this bit is set, reads or writes to `satp` CSR or execute `sfence.vma`
+    /// instruction when in S-mode will raise an illegal instruction exception.
+    ///
+    /// TVM is hard-wired to 0 when S-mode is not supported.
+    #[inline]
+    pub fn tvm(&self) -> bool {
+        self.bits.get_bit(20)
+    }
+
+    /// Timeout Wait
+    ///
+    /// Indicates that if WFI instruction should be intercepted.
+    ///
+    /// If this bit is set, when WFI is executed in S-mode, and it does not complete
+    /// within an implementation specific, bounded time limit, the WFI instruction will cause
+    /// an illegal instruction trap; or could always cause trap then the time limit is zero.
+    ///
+    /// TW is hard-wired to 0 when S-mode is not supported.
+    #[inline]
+    pub fn tw(&self) -> bool {
+        self.bits.get_bit(21)
+    }
+
+    /// Trap SRET
+    ///
+    /// Indicates that if SRET instruction should be trapped to raise illegal
+    /// instruction exception.
+    ///
+    /// If S-mode is not supported, TSR bit is hard-wired to 0.
+    #[inline]
+    pub fn tsr(&self) -> bool {
+        self.bits.get_bit(22)
+    }
+
+    /*
+        FIXME: There are MBE and SBE bits in 1.12; once Privileged Specification version 1.12
+        is ratified, there should be read functions of these bits as well.
+    */
+
     /// Whether either the FS field or XS field
     /// signals the presence of some dirty state
     #[inline]
@@ -152,26 +217,39 @@ 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);
+set_clear_csr!(
+    /// Modify Memory PRiVilege
+    , set_mprv, clear_mprv, 1 << 17);
+set_clear_csr!(
+    /// Permit Supervisor User Memory access
+    , set_sum, clear_sum, 1 << 18);
+set_clear_csr!(
+    /// Make eXecutable Readable
+    , set_mxr, clear_mxr, 1 << 19);
+set_clear_csr!(
+    /// Trap Virtual Memory
+    , set_tvm, clear_tvm, 1 << 20);
+set_clear_csr!(
+    /// Timeout Wait
+    , set_tw, clear_tw, 1 << 21);
+set_clear_csr!(
+    /// Trap SRET
+    , set_tsr, clear_tsr, 1 << 22);
 
 /// Supervisor Previous Privilege Mode
 #[inline]

+ 21 - 11
src/register/satp.rs

@@ -1,6 +1,5 @@
 //! satp register
 
-#[cfg(riscv)]
 use bit_field::BitField;
 
 /// satp register
@@ -18,7 +17,7 @@ impl Satp {
 
     /// Current address-translation scheme
     #[inline]
-    #[cfg(riscv32)]
+    #[cfg(target_pointer_width = "32")]
     pub fn mode(&self) -> Mode {
         match self.bits.get_bit(31) {
             false => Mode::Bare,
@@ -28,7 +27,7 @@ impl Satp {
 
     /// Current address-translation scheme
     #[inline]
-    #[cfg(riscv64)]
+    #[cfg(target_pointer_width = "64")]
     pub fn mode(&self) -> Mode {
         match self.bits.get_bits(60..64) {
             0 => Mode::Bare,
@@ -42,55 +41,65 @@ impl Satp {
 
     /// Address space identifier
     #[inline]
-    #[cfg(riscv32)]
+    #[cfg(target_pointer_width = "32")]
     pub fn asid(&self) -> usize {
         self.bits.get_bits(22..31)
     }
 
     /// Address space identifier
     #[inline]
-    #[cfg(riscv64)]
+    #[cfg(target_pointer_width = "64")]
     pub fn asid(&self) -> usize {
         self.bits.get_bits(44..60)
     }
 
     /// Physical page number
     #[inline]
-    #[cfg(riscv32)]
+    #[cfg(target_pointer_width = "32")]
     pub fn ppn(&self) -> usize {
         self.bits.get_bits(0..22)
     }
 
     /// Physical page number
     #[inline]
-    #[cfg(riscv64)]
+    #[cfg(target_pointer_width = "64")]
     pub fn ppn(&self) -> usize {
         self.bits.get_bits(0..44)
     }
 }
 
-#[cfg(riscv32)]
+/// 32-bit satp mode
+#[cfg(target_pointer_width = "32")]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum Mode {
+    /// No translation or protection
     Bare = 0,
+    /// Page-based 32-bit virtual addressing
     Sv32 = 1,
 }
 
-#[cfg(riscv64)]
+/// 64-bit satp mode
+#[cfg(target_pointer_width = "64")]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum Mode {
+    /// No translation or protection
     Bare = 0,
+    /// Page-based 39-bit virtual addressing
     Sv39 = 8,
+    /// Page-based 48-bit virtual addressing
     Sv48 = 9,
+    /// Page-based 57-bit virtual addressing
     Sv57 = 10,
+    /// Page-based 64-bit virtual addressing
     Sv64 = 11,
 }
 
 read_csr_as!(Satp, 0x180, __read_satp);
 write_csr_as_usize!(0x180, __write_satp);
 
+/// Sets the register to corresponding page table mode, physical page number and address space id.
 #[inline]
-#[cfg(riscv32)]
+#[cfg(target_pointer_width = "32")]
 pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
     let mut bits = 0usize;
     bits.set_bits(31..32, mode as usize);
@@ -99,8 +108,9 @@ pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
     _write(bits);
 }
 
+/// Sets the register to corresponding page table mode, physical page number and address space id.
 #[inline]
-#[cfg(riscv64)]
+#[cfg(target_pointer_width = "64")]
 pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
     let mut bits = 0usize;
     bits.set_bits(60..64, mode as usize);

+ 40 - 0
src/register/scause.rs

@@ -115,3 +115,43 @@ impl Scause {
 }
 
 read_csr_as!(Scause, 0x142, __read_scause);
+write_csr!(0x142, __write_scause);
+
+/// Writes the CSR
+#[inline]
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}
+
+/// Set supervisor cause register to corresponding cause.
+#[inline]
+pub unsafe fn set(cause: Trap) {
+    let bits = match cause {
+        Trap::Interrupt(i) => {
+            (match i {
+                Interrupt::UserSoft => 0,
+                Interrupt::SupervisorSoft => 1,
+                Interrupt::UserTimer => 4,
+                Interrupt::SupervisorTimer => 5,
+                Interrupt::UserExternal => 8,
+                Interrupt::SupervisorExternal => 9,
+                Interrupt::Unknown => panic!("unknown interrupt"),
+            } | (1 << (size_of::<usize>() * 8 - 1)))
+        } // interrupt bit is 1
+        Trap::Exception(e) => match e {
+            Exception::InstructionMisaligned => 0,
+            Exception::InstructionFault => 1,
+            Exception::IllegalInstruction => 2,
+            Exception::Breakpoint => 3,
+            Exception::LoadFault => 5,
+            Exception::StoreMisaligned => 6,
+            Exception::StoreFault => 7,
+            Exception::UserEnvCall => 8,
+            Exception::InstructionPageFault => 12,
+            Exception::LoadPageFault => 13,
+            Exception::StorePageFault => 15,
+            Exception::Unknown => panic!("unknown exception"),
+        }, // interrupt bit is 0
+    };
+    _write(bits);
+}

+ 4 - 4
src/register/scounteren.rs

@@ -9,25 +9,25 @@ pub struct Scounteren {
 }
 
 impl Scounteren {
-    /// User "cycle[h]" Enable
+    /// User "cycle\[h\]" Enable
     #[inline]
     pub fn cy(&self) -> bool {
         self.bits.get_bit(0)
     }
 
-    /// User "time[h]" Enable
+    /// User "time\[h\]" Enable
     #[inline]
     pub fn tm(&self) -> bool {
         self.bits.get_bit(1)
     }
 
-    /// User "instret[h]" Enable
+    /// User "instret\[h]\" Enable
     #[inline]
     pub fn ir(&self) -> bool {
         self.bits.get_bit(2)
     }
 
-    /// User "hpm[x]" Enable (bits 3-31)
+    /// User "hpm\[x\]" Enable (bits 3-31)
     #[inline]
     pub fn hpm(&self, index: usize) -> bool {
         assert!(3 <= index && index < 32);

+ 3 - 5
src/register/sstatus.rs

@@ -113,16 +113,15 @@ set_csr!(
 set_csr!(
     /// Supervisor Previous Interrupt Enable
     , set_spie, 1 << 5);
-set_clear_csr!(
-    /// Make eXecutable Readable
-    , set_mxr, clear_mxr, 1 << 19);
 set_clear_csr!(
     /// Permit Supervisor User Memory access
     , set_sum, clear_sum, 1 << 18);
+set_clear_csr!(
+    /// Make eXecutable Readable
+    , set_mxr, clear_mxr, 1 << 19);
 
 /// Supervisor Previous Privilege Mode
 #[inline]
-#[cfg(riscv)]
 pub unsafe fn set_spp(spp: SPP) {
     match spp {
         SPP::Supervisor => _set(1 << 8),
@@ -132,7 +131,6 @@ pub unsafe fn set_spp(spp: SPP) {
 
 /// The status of the floating-point unit
 #[inline]
-#[cfg(riscv)]
 pub unsafe fn set_fs(fs: FS) {
     let mut value = _read();
     value.set_bits(13..15, fs as usize);

+ 7 - 0
src/register/stval.rs

@@ -1,3 +1,10 @@
 //! stval register
 
 read_csr_as_usize!(0x143, __read_stval);
+write_csr!(0x143, __write_stval);
+
+/// Writes the CSR
+#[inline]
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}

+ 7 - 0
src/register/ucause.rs

@@ -15,3 +15,10 @@ impl Ucause {
 }
 
 read_csr_as!(Ucause, 0x042, __read_ucause);
+write_csr!(0x042, __write_ucause);
+
+/// Writes the CSR
+#[inline]
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}

+ 7 - 0
src/register/utval.rs

@@ -1,3 +1,10 @@
 //! utval register
 
 read_csr_as_usize!(0x043, __read_utval);
+write_csr!(0x043, __write_utval);
+
+/// Writes the CSR
+#[inline]
+pub unsafe fn write(bits: usize) {
+    _write(bits)
+}