# fcsr.rs - source
Source of the Rust file `/home/runner/.cargo/git/checkouts/riscv-ab2abd16c438337b/11d43cf/src/register/fcsr.rs`.
Keywords: rust, rustlang, rust-lang

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134

    //! 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
    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    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);
    }