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
#[cfg(feature = "instructions")]
pub use self::x86_64::*;
use bitflags::bitflags;
bitflags! {
#[repr(transparent)]
pub struct MxCsr: u32 {
const INVALID_OPERATION = 1 << 0;
const DENORMAL = 1 << 1;
const DIVIDE_BY_ZERO = 1 << 2;
const OVERFLOW = 1 << 3;
const UNDERFLOW = 1 << 4;
const PRECISION = 1 << 5;
const DENORMALS_ARE_ZEROS = 1 << 6;
const INVALID_OPERATION_MASK = 1 << 7;
const DENORMAL_MASK = 1 << 8;
const DIVIDE_BY_ZERO_MASK = 1 << 9;
const OVERFLOW_MASK = 1 << 10;
const UNDERFLOW_MASK = 1 << 11;
const PRECISION_MASK = 1 << 12;
const ROUNDING_CONTROL_NEGATIVE = 1 << 13;
const ROUNDING_CONTROL_POSITIVE = 1 << 14;
const ROUNDING_CONTROL_ZERO = 3 << 13;
const FLUSH_TO_ZERO = 1 << 15;
}
}
impl Default for MxCsr {
#[inline]
fn default() -> Self {
MxCsr::INVALID_OPERATION_MASK
| MxCsr::DENORMAL_MASK
| MxCsr::DIVIDE_BY_ZERO_MASK
| MxCsr::OVERFLOW_MASK
| MxCsr::UNDERFLOW_MASK
| MxCsr::PRECISION_MASK
}
}
#[cfg(feature = "instructions")]
mod x86_64 {
use super::*;
use core::arch::asm;
#[inline]
pub fn read() -> MxCsr {
let mut mxcsr: u32 = 0;
unsafe {
asm!("stmxcsr [{}]", in(reg) &mut mxcsr, options(nostack, preserves_flags));
}
MxCsr::from_bits_truncate(mxcsr)
}
#[inline]
pub fn write(mxcsr: MxCsr) {
unsafe {
asm!("ldmxcsr [{}]", in(reg) &mxcsr, options(nostack, readonly));
}
}
#[cfg(test)]
mod test {
use crate::registers::mxcsr::*;
#[test]
fn mxcsr_default() {
let mxcsr = read();
assert_eq!(mxcsr, MxCsr::from_bits_truncate(0x1F80));
}
#[test]
fn mxcsr_read() {
let mxcsr = read();
assert_eq!(mxcsr, MxCsr::default());
}
#[test]
fn mxcsr_write() {
let mxcsr = read();
write(mxcsr);
assert_eq!(mxcsr, read());
}
}
}