Add fcsr register

This commit is contained in:
Vadim Kaushan 2019-03-17 19:06:29 +03:00
parent 2450868523
commit 4ad2150a24
No known key found for this signature in database
GPG Key ID: A501C5DF67C05C4E
3 changed files with 135 additions and 0 deletions

2
asm.S
View File

@ -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)

131
src/register/fcsr.rs Normal file
View File

@ -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);
}

View File

@ -13,6 +13,8 @@
#[macro_use]
mod macros;
pub mod fcsr;
pub mod mcause;
pub mod mcycle;
pub mod mcycleh;