Skip to content

Commit

Permalink
riscv: remove intrinsics that cannot be used from Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung authored and Amanieu committed Nov 5, 2023
1 parent e504eff commit 39e3779
Showing 1 changed file with 25 additions and 89 deletions.
114 changes: 25 additions & 89 deletions crates/core_arch/src/riscv_shared/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
//! Shared RISC-V intrinsics

//!
//! ## Missing floating-point register instructions
//!
//! We are deliberately *not* providing instructions that could change the floating-point rounding
//! mode or exception behavior or read the accrued exceptions flags: `frcsr`, `fscsr`, `fsrm`,
//! `frflags`, `fsflags`.
//!
//! Rust makes no guarantees whatsoever about the contents of the accrued exceptions register: Rust
//! floating-point operations may or may not result in this register getting updated with exception
//! state, and the register can change between two invocations of this function even when no
//! floating-point operations appear in the source code (since floating-point operations appearing
//! earlier or later can be reordered).
//!
//! Modifying the rounding mode leads to **immediate Undefined Behavior**: Rust assumes that the
//! default rounding mode is always set and will optimize accordingly. This even applies when the
//! rounding mode is altered and later reset to its original value without any floating-point
//! operations appearing in the source code between those operations (since floating-point
//! operations appearing earlier or later can be reordered).
//!
//! If you need to perform some floating-point operations and check whether they raised an
//! exception, use a single inline assembly block for the entire sequence of operations.
//!
//! If you need to perform some floating-point operations under a differen rounding mode, use a
//! single inline assembly block and make sure to restore the original rounding mode before the end
//! of the block.
mod p;
mod zb;
mod zk;
Expand Down Expand Up @@ -531,44 +555,6 @@ pub unsafe fn hinval_gvma_all() {
asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack))
}

/// Reads the floating-point control and status register `fcsr`
///
/// Register `fcsr` is a 32-bit read/write register that selects the dynamic rounding mode
/// for floating-point arithmetic operations and holds the accrued exception flag.
///
/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
/// register `fcsr` is defined as:
///
/// | Bit index | Meaning |
/// |:----------|:--------|
/// | 0..=4 | Accrued Exceptions (`fflags`) |
/// | 5..=7 | Rounding Mode (`frm`) |
/// | 8..=31 | _Reserved_ |
///
/// For definition of each field, visit [`frrm`] and [`frflags`].
///
/// [`frrm`]: fn.frrm.html
/// [`frflags`]: fn.frflags.html
#[inline]
#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
pub fn frcsr() -> u32 {
let value: u32;
unsafe { asm!("frcsr {}", out(reg) value, options(nomem, nostack)) };
value
}

/// Swaps the floating-point control and status register `fcsr`
///
/// This function swaps the value in `fcsr` by copying the original value to be returned,
/// and then writing a new value obtained from input variable `value` into `fcsr`.
#[inline]
#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
pub fn fscsr(value: u32) -> u32 {
let original: u32;
unsafe { asm!("fscsr {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
original
}

/// Reads the floating-point rounding mode register `frm`
///
/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
Expand All @@ -591,53 +577,3 @@ pub fn frrm() -> u32 {
unsafe { asm!("frrm {}", out(reg) value, options(nomem, nostack)) };
value
}

/// Swaps the floating-point rounding mode register `frm`
///
/// This function swaps the value in `frm` by copying the original value to be returned,
/// and then writing a new value obtained from the three least-significant bits of
/// input variable `value` into `frm`.
#[inline]
#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
pub fn fsrm(value: u32) -> u32 {
let original: u32;
unsafe { asm!("fsrm {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
original
}

/// Reads the floating-point accrued exception flags register `fflags`
///
/// The accrued exception flags indicate the exception conditions that have arisen
/// on any floating-point arithmetic instruction since the field was last reset by software.
///
/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
/// the accrued exception flags is defined as a bit vector of 5 bits.
/// The meaning of each binary bit is listed in the table below.
///
/// | Bit index | Mnemonic | Meaning |
/// |:--|:---|:-----------------|
/// | 4 | NV | Invalid Operation |
/// | 3 | DZ | Divide by Zero |
/// | 2 | OF | Overflow |
/// | 1 | UF | Underflow |
/// | 0 | NX | Inexact |
#[inline]
#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
pub fn frflags() -> u32 {
let value: u32;
unsafe { asm!("frflags {}", out(reg) value, options(nomem, nostack)) };
value
}

/// Swaps the floating-point accrued exception flags register `fflags`
///
/// This function swaps the value in `fflags` by copying the original value to be returned,
/// and then writing a new value obtained from the five least-significant bits of
/// input variable `value` into `fflags`.
#[inline]
#[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
pub fn fsflags(value: u32) -> u32 {
let original: u32;
unsafe { asm!("fsflags {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
original
}

0 comments on commit 39e3779

Please sign in to comment.