x86_64/registers/
mxcsr.rs

1//! Functions to read and write MXCSR register.
2
3#[cfg(all(feature = "instructions", target_arch = "x86_64"))]
4pub use self::x86_64::*;
5
6use bitflags::bitflags;
7
8bitflags! {
9    /// MXCSR register.
10    #[repr(transparent)]
11    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
12    pub struct MxCsr: u32 {
13        /// Invalid operation
14        const INVALID_OPERATION = 1 << 0;
15        /// Denormal
16        const DENORMAL = 1 << 1;
17        /// Divide-by-zero
18        const DIVIDE_BY_ZERO = 1 << 2;
19        /// Overflow
20        const OVERFLOW = 1 << 3;
21        /// Underflow
22        const UNDERFLOW = 1 << 4;
23        /// Precision
24        const PRECISION = 1 << 5;
25        /// Denormals are zeros
26        const DENORMALS_ARE_ZEROS = 1 << 6;
27        /// Invalid operation mask
28        const INVALID_OPERATION_MASK = 1 << 7;
29        /// Denormal mask
30        const DENORMAL_MASK = 1 << 8;
31        /// Divide-by-zero mask
32        const DIVIDE_BY_ZERO_MASK = 1 << 9;
33        /// Overflow mask
34        const OVERFLOW_MASK = 1 << 10;
35        /// Underflow mask
36        const UNDERFLOW_MASK = 1 << 11;
37        /// Precision mask
38        const PRECISION_MASK = 1 << 12;
39        /// Toward negative infinity
40        const ROUNDING_CONTROL_NEGATIVE = 1 << 13;
41        /// Toward positive infinity
42        const ROUNDING_CONTROL_POSITIVE = 1 << 14;
43        /// Toward zero (positive + negative)
44        const ROUNDING_CONTROL_ZERO = 3 << 13;
45        /// Flush to zero
46        const FLUSH_TO_ZERO = 1 << 15;
47    }
48}
49
50impl Default for MxCsr {
51    /// Return the default MXCSR value at reset, as documented in Intel SDM volume 2A.
52    #[inline]
53    fn default() -> Self {
54        MxCsr::INVALID_OPERATION_MASK
55            | MxCsr::DENORMAL_MASK
56            | MxCsr::DIVIDE_BY_ZERO_MASK
57            | MxCsr::OVERFLOW_MASK
58            | MxCsr::UNDERFLOW_MASK
59            | MxCsr::PRECISION_MASK
60    }
61}
62
63#[cfg(all(feature = "instructions", target_arch = "x86_64"))]
64mod x86_64 {
65    use super::*;
66    use core::arch::asm;
67
68    /// Read the value of MXCSR.
69    #[inline]
70    pub fn read() -> MxCsr {
71        let mut mxcsr: u32 = 0;
72        unsafe {
73            asm!("stmxcsr [{}]", in(reg) &mut mxcsr, options(nostack, preserves_flags));
74        }
75        MxCsr::from_bits_truncate(mxcsr)
76    }
77
78    /// Write MXCSR.
79    #[inline]
80    pub fn write(mxcsr: MxCsr) {
81        unsafe {
82            asm!("ldmxcsr [{}]", in(reg) &mxcsr, options(nostack, readonly));
83        }
84    }
85
86    #[cfg(test)]
87    mod test {
88        use crate::registers::mxcsr::*;
89
90        #[test]
91        fn mxcsr_default() {
92            let mxcsr = read();
93            assert_eq!(mxcsr, MxCsr::from_bits_truncate(0x1F80));
94        }
95
96        #[test]
97        fn mxcsr_read() {
98            let mxcsr = read();
99            assert_eq!(mxcsr, MxCsr::default());
100        }
101
102        #[test]
103        fn mxcsr_write() {
104            let mxcsr = read();
105            write(mxcsr);
106            assert_eq!(mxcsr, read());
107        }
108    }
109}