Skip to content

Commit 596762d

Browse files
committed
riscv: floating-point register operations
1 parent 132e4c4 commit 596762d

File tree

1 file changed

+105
-0
lines changed
  • crates/core_arch/src/riscv_shared

1 file changed

+105
-0
lines changed

crates/core_arch/src/riscv_shared/mod.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,111 @@ pub unsafe fn hinval_gvma_vmid(vmid: usize) {
469469
asm!(".insn r 0x73, 0, 0x33, x0, x0, {}", in(reg) vmid, options(nostack))
470470
}
471471

472+
/// Reads the floating-point control and status register `fcsr`
473+
///
474+
/// Register `fcsr` is a 32-bit read/write register that selects the dynamic rounding mode
475+
/// for floating-point arithmetic operations and holds the accrued exception flag.
476+
///
477+
/// Accoding to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
478+
/// register `fcsr` is defined as:
479+
///
480+
/// | Bit index | Meaning |
481+
/// |:----------|:--------|
482+
/// | 0..=4 | Accrued Exceptions (`fflags`) |
483+
/// | 5..=7 | Rounding Mode (`frm`) |
484+
/// | 8..=31 | _Reserved_ |
485+
///
486+
/// For definition of each field, visit [`frrm`] and [`frflags`].
487+
///
488+
/// [`frrm`]: fn.frrm.html
489+
/// [`frflags`]: fn.frflags.html
490+
#[inline]
491+
pub fn frcsr() -> u32 {
492+
let value: u32;
493+
unsafe { asm!("frcsr {}", out(reg) value, options(nomem, nostack)) };
494+
value
495+
}
496+
497+
/// Swaps the floating-point control and status register `fcsr`
498+
///
499+
/// This function swaps the value in `fcsr` by copying the original value to be returned,
500+
/// and then writing a new value obtained from input variable `value` into `fcsr`.
501+
#[inline]
502+
pub fn fscsr(value: u32) -> u32 {
503+
let original: u32;
504+
unsafe { asm!("fscsr {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
505+
original
506+
}
507+
508+
/// Reads the floating-point rounding mode register `frm`
509+
///
510+
/// Accoding to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
511+
/// the rounding mode field is defined as listed in the table below:
512+
///
513+
/// | Rounding Mode | Mnemonic | Meaning |
514+
/// |:-------------|:----------|:---------|
515+
/// | 000 | RNE | Round to Nearest, ties to Even |
516+
/// | 001 | RTZ | Round towards Zero |
517+
/// | 010 | RDN | Round Down (towards −∞) |
518+
/// | 011 | RUP | Round Up (towards +∞) |
519+
/// | 100 | RMM | Round to Nearest, ties to Max Magnitude |
520+
/// | 101 | | _Reserved for future use._ |
521+
/// | 110 | | _Reserved for future use._ |
522+
/// | 111 | DYN | In Rounding Mode register, _reserved_. |
523+
#[inline]
524+
pub fn frrm() -> u32 {
525+
let value: u32;
526+
unsafe { asm!("frrm {}", out(reg) value, options(nomem, nostack)) };
527+
value
528+
}
529+
530+
/// Swaps the floating-point rounding mode register `frm`
531+
///
532+
/// This function swaps the value in `frm` by copying the original value to be returned,
533+
/// and then writing a new value obtained from the three least-significant bits of
534+
/// input variable `value` into `frm`.
535+
#[inline]
536+
pub fn fsrm(value: u32) -> u32 {
537+
let original: u32;
538+
unsafe { asm!("fsrm {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
539+
original
540+
}
541+
542+
/// Reads the floating-point accrued exception flags register `fflags`
543+
///
544+
/// The accrued exception flags indicate the exception conditions that have arisen
545+
/// on any floating-point arithmetic instruction since the field was last reset by software.
546+
///
547+
/// Accoding to "F" Standard Extension for Single-Precision Floating-Point, Version 2.2,
548+
/// the accured exception flags is defined as a bit vector of 5 bits.
549+
/// The meaning of each binary bit is listed in the table below.
550+
///
551+
/// | Bit index | Mnemonic | Meaning |
552+
/// |:--|:---|:-----------------|
553+
/// | 4 | NV | Invalid Operation |
554+
/// | 3 | DZ | Divide by Zero |
555+
/// | 2 | OF | Overflow |
556+
/// | 1 | UF | Underflow |
557+
/// | 0 | NX | Inexact |
558+
#[inline]
559+
pub fn frflags() -> u32 {
560+
let value: u32;
561+
unsafe { asm!("frflags {}", out(reg) value, options(nomem, nostack)) };
562+
value
563+
}
564+
565+
/// Swaps the floating-point accrued exception flags register `fflags`
566+
///
567+
/// This function swaps the value in `fflags` by copying the original value to be returned,
568+
/// and then writing a new value obtained from the five least-significant bits of
569+
/// input variable `value` into `fflags`.
570+
#[inline]
571+
pub fn fsflags(value: u32) -> u32 {
572+
let original: u32;
573+
unsafe { asm!("fsflags {}, {}", out(reg) original, in(reg) value, options(nomem, nostack)) }
574+
original
575+
}
576+
472577
/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
473578
///
474579
/// This instruction invalidates any address-translation cache entries that an

0 commit comments

Comments
 (0)