Add fcsr register
This commit is contained in:
parent
2450868523
commit
4ad2150a24
2
asm.S
2
asm.S
|
@ -24,6 +24,8 @@ __sfence_vma:
|
|||
sfence.vma a0, a1
|
||||
ret
|
||||
|
||||
REG_READ_WRITE(fcsr, 0x003)
|
||||
REG_SET_CLEAR(fcsr, 0x003)
|
||||
|
||||
// M-mode registers
|
||||
REG_READ(mcause, 0x342)
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
//! Floating-point control and status register
|
||||
|
||||
use bit_field::BitField;
|
||||
|
||||
/// Floating-point control and status register
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct FCSR {
|
||||
bits: u32,
|
||||
}
|
||||
|
||||
/// Accrued Exception Flags
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Flags(u32);
|
||||
|
||||
/// Accrued Exception Flag
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Flag {
|
||||
/// Inexact
|
||||
NX = 0b00001,
|
||||
|
||||
/// Underflow
|
||||
UF = 0b00010,
|
||||
|
||||
/// Overflow
|
||||
OF = 0b00100,
|
||||
|
||||
/// Divide by Zero
|
||||
DZ = 0b01000,
|
||||
|
||||
/// Invalid Operation
|
||||
NV = 0b10000,
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
/// Inexact
|
||||
#[inline]
|
||||
pub fn nx(&self) -> bool {
|
||||
self.0.get_bit(0)
|
||||
}
|
||||
|
||||
/// Underflow
|
||||
#[inline]
|
||||
pub fn uf(&self) -> bool {
|
||||
self.0.get_bit(1)
|
||||
}
|
||||
|
||||
/// Overflow
|
||||
#[inline]
|
||||
pub fn of(&self) -> bool {
|
||||
self.0.get_bit(2)
|
||||
}
|
||||
|
||||
/// Divide by Zero
|
||||
#[inline]
|
||||
pub fn dz(&self) -> bool {
|
||||
self.0.get_bit(3)
|
||||
}
|
||||
|
||||
/// Invalid Operation
|
||||
#[inline]
|
||||
pub fn nv(&self) -> bool {
|
||||
self.0.get_bit(4)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rounding Mode
|
||||
pub enum RoundingMode {
|
||||
RoundToNearestEven = 0b000,
|
||||
RoundTowardsZero = 0b001,
|
||||
RoundDown = 0b010,
|
||||
RoundUp = 0b011,
|
||||
RoundToNearestMaxMagnitude = 0b100,
|
||||
Invalid = 0b111,
|
||||
}
|
||||
|
||||
impl FCSR {
|
||||
/// Returns the contents of the register as raw bits
|
||||
pub fn bits(&self) -> u32 {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// Accrued Exception Flags
|
||||
#[inline]
|
||||
pub fn fflags(&self) -> Flags {
|
||||
Flags(self.bits.get_bits(0..5))
|
||||
}
|
||||
|
||||
/// Rounding Mode
|
||||
#[inline]
|
||||
pub fn frm(&self) -> RoundingMode {
|
||||
match self.bits.get_bits(5..8) {
|
||||
0b000 => RoundingMode::RoundToNearestEven,
|
||||
0b001 => RoundingMode::RoundTowardsZero,
|
||||
0b010 => RoundingMode::RoundDown,
|
||||
0b011 => RoundingMode::RoundUp,
|
||||
0b100 => RoundingMode::RoundToNearestMaxMagnitude,
|
||||
_ => RoundingMode::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
read_csr!(0x003, __read_fcsr);
|
||||
write_csr!(0x003, __write_fcsr);
|
||||
clear!(0x003, __clear_fcsr);
|
||||
|
||||
/// Reads the CSR
|
||||
#[inline]
|
||||
pub fn read() -> FCSR {
|
||||
FCSR { bits: unsafe{ _read() as u32 } }
|
||||
}
|
||||
|
||||
/// Writes the CSR
|
||||
#[inline]
|
||||
pub unsafe fn set_rounding_mode(frm: RoundingMode) {
|
||||
let old = read();
|
||||
let bits = ((frm as u32) << 5) | old.fflags().0;
|
||||
_write(bits as usize);
|
||||
}
|
||||
|
||||
/// Resets `fflags` field bits
|
||||
#[inline]
|
||||
pub unsafe fn clear_flags() {
|
||||
let mask = 0b11111;
|
||||
_clear(mask);
|
||||
}
|
||||
|
||||
/// Resets `fflags` field bit
|
||||
#[inline]
|
||||
pub unsafe fn clear_flag(flag: Flag) {
|
||||
_clear(flag as usize);
|
||||
}
|
|
@ -13,6 +13,8 @@
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
pub mod fcsr;
|
||||
|
||||
pub mod mcause;
|
||||
pub mod mcycle;
|
||||
pub mod mcycleh;
|
||||
|
|
Loading…
Reference in New Issue