11//! Shared RISC-V intrinsics
2-
2+ //!
3+ //! ## Missing floating-point register instructions
4+ //!
5+ //! We are deliberately *not* providing instructions that could change the floating-point rounding
6+ //! mode or exception behavior or read the accrued exceptions flags: `frcsr`, `fscsr`, `fsrm`,
7+ //! `frflags`, `fsflags`.
8+ //!
9+ //! Rust makes no guarantees whatsoever about the contents of the accrued exceptions register: Rust
10+ //! floating-point operations may or may not result in this register getting updated with exception
11+ //! state, and the register can change between two invocations of this function even when no
12+ //! floating-point operations appear in the source code (since floating-point operations appearing
13+ //! earlier or later can be reordered).
14+ //!
15+ //! Modifying the rounding mode leads to **immediate Undefined Behavior**: Rust assumes that the
16+ //! default rounding mode is always set and will optimize accordingly. This even applies when the
17+ //! rounding mode is altered and later reset to its original value without any floating-point
18+ //! operations appearing in the source code between those operations (since floating-point
19+ //! operations appearing earlier or later can be reordered).
20+ //!
21+ //! If you need to perform some floating-point operations and check whether they raised an
22+ //! exception, use a single inline assembly block for the entire sequence of operations.
23+ //!
24+ //! If you need to perform some floating-point operations under a differen rounding mode, use a
25+ //! single inline assembly block and make sure to restore the original rounding mode before the end
26+ //! of the block.
327mod p;
428mod zb;
529mod zk;
@@ -531,44 +555,6 @@ pub unsafe fn hinval_gvma_all() {
531555 asm ! ( ".insn r 0x73, 0, 0x33, x0, x0, x0" , options( nostack) )
532556}
533557
534- /// Reads the floating-point control and status register `fcsr`
535- ///
536- /// Register `fcsr` is a 32-bit read/write register that selects the dynamic rounding mode
537- /// for floating-point arithmetic operations and holds the accrued exception flag.
538- ///
539- /// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
540- /// register `fcsr` is defined as:
541- ///
542- /// | Bit index | Meaning |
543- /// |:----------|:--------|
544- /// | 0..=4 | Accrued Exceptions (`fflags`) |
545- /// | 5..=7 | Rounding Mode (`frm`) |
546- /// | 8..=31 | _Reserved_ |
547- ///
548- /// For definition of each field, visit [`frrm`] and [`frflags`].
549- ///
550- /// [`frrm`]: fn.frrm.html
551- /// [`frflags`]: fn.frflags.html
552- #[ inline]
553- #[ unstable( feature = "riscv_ext_intrinsics" , issue = "114544" ) ]
554- pub fn frcsr ( ) -> u32 {
555- let value: u32 ;
556- unsafe { asm ! ( "frcsr {}" , out( reg) value, options( nomem, nostack) ) } ;
557- value
558- }
559-
560- /// Swaps the floating-point control and status register `fcsr`
561- ///
562- /// This function swaps the value in `fcsr` by copying the original value to be returned,
563- /// and then writing a new value obtained from input variable `value` into `fcsr`.
564- #[ inline]
565- #[ unstable( feature = "riscv_ext_intrinsics" , issue = "114544" ) ]
566- pub fn fscsr ( value : u32 ) -> u32 {
567- let original: u32 ;
568- unsafe { asm ! ( "fscsr {}, {}" , out( reg) original, in( reg) value, options( nomem, nostack) ) }
569- original
570- }
571-
572558/// Reads the floating-point rounding mode register `frm`
573559///
574560/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
@@ -591,53 +577,3 @@ pub fn frrm() -> u32 {
591577 unsafe { asm ! ( "frrm {}" , out( reg) value, options( nomem, nostack) ) } ;
592578 value
593579}
594-
595- /// Swaps the floating-point rounding mode register `frm`
596- ///
597- /// This function swaps the value in `frm` by copying the original value to be returned,
598- /// and then writing a new value obtained from the three least-significant bits of
599- /// input variable `value` into `frm`.
600- #[ inline]
601- #[ unstable( feature = "riscv_ext_intrinsics" , issue = "114544" ) ]
602- pub fn fsrm ( value : u32 ) -> u32 {
603- let original: u32 ;
604- unsafe { asm ! ( "fsrm {}, {}" , out( reg) original, in( reg) value, options( nomem, nostack) ) }
605- original
606- }
607-
608- /// Reads the floating-point accrued exception flags register `fflags`
609- ///
610- /// The accrued exception flags indicate the exception conditions that have arisen
611- /// on any floating-point arithmetic instruction since the field was last reset by software.
612- ///
613- /// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
614- /// the accrued exception flags is defined as a bit vector of 5 bits.
615- /// The meaning of each binary bit is listed in the table below.
616- ///
617- /// | Bit index | Mnemonic | Meaning |
618- /// |:--|:---|:-----------------|
619- /// | 4 | NV | Invalid Operation |
620- /// | 3 | DZ | Divide by Zero |
621- /// | 2 | OF | Overflow |
622- /// | 1 | UF | Underflow |
623- /// | 0 | NX | Inexact |
624- #[ inline]
625- #[ unstable( feature = "riscv_ext_intrinsics" , issue = "114544" ) ]
626- pub fn frflags ( ) -> u32 {
627- let value: u32 ;
628- unsafe { asm ! ( "frflags {}" , out( reg) value, options( nomem, nostack) ) } ;
629- value
630- }
631-
632- /// Swaps the floating-point accrued exception flags register `fflags`
633- ///
634- /// This function swaps the value in `fflags` by copying the original value to be returned,
635- /// and then writing a new value obtained from the five least-significant bits of
636- /// input variable `value` into `fflags`.
637- #[ inline]
638- #[ unstable( feature = "riscv_ext_intrinsics" , issue = "114544" ) ]
639- pub fn fsflags ( value : u32 ) -> u32 {
640- let original: u32 ;
641- unsafe { asm ! ( "fsflags {}, {}" , out( reg) original, in( reg) value, options( nomem, nostack) ) }
642- original
643- }
0 commit comments