Skip to main content

cortex_m/register/
fpscr.rs

1//! Floating-point Status Control Register
2
3#[cfg(has_fpu)]
4use core::arch::asm;
5
6/// Floating-point Status Control Register
7#[derive(Clone, Copy, Debug)]
8pub struct Fpscr {
9    bits: u32,
10}
11
12impl Fpscr {
13    /// Creates a `Fspcr` value from raw bits.
14    #[inline]
15    pub fn from_bits(bits: u32) -> Self {
16        Self { bits }
17    }
18
19    /// Returns the contents of the register as raw bits
20    #[inline]
21    pub fn bits(self) -> u32 {
22        self.bits
23    }
24
25    /// Read the Negative condition code flag
26    #[inline]
27    pub fn n(self) -> bool {
28        self.bits & (1 << 31) != 0
29    }
30
31    /// Sets the Negative condition code flag
32    #[inline]
33    pub fn set_n(&mut self, n: bool) {
34        let mask = 1 << 31;
35        match n {
36            true => self.bits |= mask,
37            false => self.bits &= !mask,
38        }
39    }
40
41    /// Read the Zero condition code flag
42    #[inline]
43    pub fn z(self) -> bool {
44        self.bits & (1 << 30) != 0
45    }
46
47    /// Sets the Zero condition code flag
48    #[inline]
49    pub fn set_z(&mut self, z: bool) {
50        let mask = 1 << 30;
51        match z {
52            true => self.bits |= mask,
53            false => self.bits &= !mask,
54        }
55    }
56
57    /// Read the Carry condition code flag
58    #[inline]
59    pub fn c(self) -> bool {
60        self.bits & (1 << 29) != 0
61    }
62
63    /// Sets the Carry condition code flag
64    #[inline]
65    pub fn set_c(&mut self, c: bool) {
66        let mask = 1 << 29;
67        match c {
68            true => self.bits |= mask,
69            false => self.bits &= !mask,
70        }
71    }
72
73    /// Read the Overflow condition code flag
74    #[inline]
75    pub fn v(self) -> bool {
76        self.bits & (1 << 28) != 0
77    }
78
79    /// Sets the Zero condition code flag
80    #[inline]
81    pub fn set_v(&mut self, v: bool) {
82        let mask = 1 << 28;
83        match v {
84            true => self.bits |= mask,
85            false => self.bits &= !mask,
86        }
87    }
88
89    /// Read the Alternative Half Precision bit
90    #[inline]
91    pub fn ahp(self) -> bool {
92        self.bits & (1 << 26) != 0
93    }
94
95    /// Sets the Alternative Half Precision bit
96    #[inline]
97    pub fn set_ahp(&mut self, ahp: bool) {
98        let mask = 1 << 26;
99        match ahp {
100            true => self.bits |= mask,
101            false => self.bits &= !mask,
102        }
103    }
104
105    /// Read the Default NaN mode bit
106    #[inline]
107    pub fn dn(self) -> bool {
108        self.bits & (1 << 25) != 0
109    }
110
111    /// Sets the Default NaN mode bit
112    #[inline]
113    pub fn set_dn(&mut self, dn: bool) {
114        let mask = 1 << 25;
115        match dn {
116            true => self.bits |= mask,
117            false => self.bits &= !mask,
118        }
119    }
120
121    /// Read the Flush to Zero mode bit
122    #[inline]
123    pub fn fz(self) -> bool {
124        self.bits & (1 << 24) != 0
125    }
126
127    /// Sets the Flush to Zero mode bit
128    #[inline]
129    pub fn set_fz(&mut self, fz: bool) {
130        let mask = 1 << 24;
131        match fz {
132            true => self.bits |= mask,
133            false => self.bits &= !mask,
134        }
135    }
136
137    /// Read the Rounding Mode control field
138    #[inline]
139    pub fn rmode(self) -> RMode {
140        match (self.bits & (3 << 22)) >> 22 {
141            0 => RMode::Nearest,
142            1 => RMode::PlusInfinity,
143            2 => RMode::MinusInfinity,
144            _ => RMode::Zero,
145        }
146    }
147
148    /// Sets the Rounding Mode control field
149    #[inline]
150    pub fn set_rmode(&mut self, rmode: RMode) {
151        let mask = 3 << 22;
152        match rmode {
153            RMode::Nearest => self.bits &= !mask,
154            RMode::PlusInfinity => self.bits = (self.bits & !mask) | (1 << 22),
155            RMode::MinusInfinity => self.bits = (self.bits & !mask) | (2 << 22),
156            RMode::Zero => self.bits |= mask,
157        }
158    }
159
160    /// Read the Input Denormal cumulative exception bit
161    #[inline]
162    pub fn idc(self) -> bool {
163        self.bits & (1 << 7) != 0
164    }
165
166    /// Sets the Input Denormal cumulative exception bit
167    #[inline]
168    pub fn set_idc(&mut self, idc: bool) {
169        let mask = 1 << 7;
170        match idc {
171            true => self.bits |= mask,
172            false => self.bits &= !mask,
173        }
174    }
175
176    /// Read the Inexact cumulative exception bit
177    #[inline]
178    pub fn ixc(self) -> bool {
179        self.bits & (1 << 4) != 0
180    }
181
182    /// Sets the Inexact cumulative exception bit
183    #[inline]
184    pub fn set_ixc(&mut self, ixc: bool) {
185        let mask = 1 << 4;
186        match ixc {
187            true => self.bits |= mask,
188            false => self.bits &= !mask,
189        }
190    }
191
192    /// Read the Underflow cumulative exception bit
193    #[inline]
194    pub fn ufc(self) -> bool {
195        self.bits & (1 << 3) != 0
196    }
197
198    /// Sets the Underflow cumulative exception bit
199    #[inline]
200    pub fn set_ufc(&mut self, ufc: bool) {
201        let mask = 1 << 3;
202        match ufc {
203            true => self.bits |= mask,
204            false => self.bits &= !mask,
205        }
206    }
207
208    /// Read the Overflow cumulative exception bit
209    #[inline]
210    pub fn ofc(self) -> bool {
211        self.bits & (1 << 2) != 0
212    }
213
214    /// Sets the Overflow cumulative exception bit
215    #[inline]
216    pub fn set_ofc(&mut self, ofc: bool) {
217        let mask = 1 << 2;
218        match ofc {
219            true => self.bits |= mask,
220            false => self.bits &= !mask,
221        }
222    }
223
224    /// Read the Division by Zero cumulative exception bit
225    #[inline]
226    pub fn dzc(self) -> bool {
227        self.bits & (1 << 1) != 0
228    }
229
230    /// Sets the Division by Zero cumulative exception bit
231    #[inline]
232    pub fn set_dzc(&mut self, dzc: bool) {
233        let mask = 1 << 1;
234        match dzc {
235            true => self.bits |= mask,
236            false => self.bits &= !mask,
237        }
238    }
239
240    /// Read the Invalid Operation cumulative exception bit
241    #[inline]
242    pub fn ioc(self) -> bool {
243        self.bits & (1 << 0) != 0
244    }
245
246    /// Sets the Invalid Operation cumulative exception bit
247    #[inline]
248    pub fn set_ioc(&mut self, ioc: bool) {
249        let mask = 1 << 0;
250        match ioc {
251            true => self.bits |= mask,
252            false => self.bits &= !mask,
253        }
254    }
255}
256
257/// Rounding mode
258#[derive(Clone, Copy, Debug, Eq, PartialEq)]
259pub enum RMode {
260    /// Round to Nearest (RN) mode. This is the reset value.
261    Nearest,
262    /// Round towards Plus Infinity (RP) mode.
263    PlusInfinity,
264    /// Round towards Minus Infinity (RM) mode.
265    MinusInfinity,
266    /// Round towards Zero (RZ) mode.
267    Zero,
268}
269
270impl RMode {
271    /// Is Nearest the current rounding mode?
272    #[inline]
273    pub fn is_nearest(self) -> bool {
274        self == RMode::Nearest
275    }
276
277    /// Is Plus Infinity the current rounding mode?
278    #[inline]
279    pub fn is_plus_infinity(self) -> bool {
280        self == RMode::PlusInfinity
281    }
282
283    /// Is Minus Infinity the current rounding mode?
284    #[inline]
285    pub fn is_minus_infinity(self) -> bool {
286        self == RMode::MinusInfinity
287    }
288
289    /// Is Zero the current rounding mode?
290    #[inline]
291    pub fn is_zero(self) -> bool {
292        self == RMode::Zero
293    }
294}
295
296/// Read the FPSCR register
297#[inline]
298#[cfg(has_fpu)]
299pub fn read() -> Fpscr {
300    let r;
301    unsafe { asm!("vmrs {}, fpscr", out(reg) r, options(nomem, nostack, preserves_flags)) };
302    Fpscr::from_bits(r)
303}
304
305/// Set the value of the FPSCR register
306#[inline]
307#[cfg(has_fpu)]
308pub unsafe fn write(fpscr: Fpscr) {
309    let fpscr = fpscr.bits();
310    unsafe { asm!("vmsr fpscr, {}", in(reg) fpscr, options(nomem, nostack)) };
311}