1
1
//! 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.
3
27
mod p;
4
28
mod zb;
5
29
mod zk;
@@ -531,44 +555,6 @@ pub unsafe fn hinval_gvma_all() {
531
555
asm ! ( ".insn r 0x73, 0, 0x33, x0, x0, x0" , options( nostack) )
532
556
}
533
557
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
-
572
558
/// Reads the floating-point rounding mode register `frm`
573
559
///
574
560
/// According to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
@@ -591,53 +577,3 @@ pub fn frrm() -> u32 {
591
577
unsafe { asm ! ( "frrm {}" , out( reg) value, options( nomem, nostack) ) } ;
592
578
value
593
579
}
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