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
//! Floating-point control and status.

use crate::system_register_access;
use tartan_bitfield::bitfield;
use tartan_c_enum::c_enum;


bitfield! {
    /// `FPCR`: Influences floating-point instruction execution.
    pub struct ControlRegister(u64) {
        /// `AHP`: Use an alternative format for half-precision floats when converting
        /// to/from other formats. Otherwise, use the IEEE half-precision format.
        [26] pub alternative_half_precision_format,
        /// `DN`: Always use the default encoding for NaN results. Otherwise, use the
        /// encoding from an input operand.
        [25] pub default_nan,
        /// `FZ`: When a result would be denormal, yield zero instead. Otherwise, use the
        /// IEEE 754 behavior.
        [24] pub flush_to_zero,
        /// `RMode`: The IEEE 754 rounding mode in use.
        [22..24] pub rounding_mode: u8 as RoundingMode,
        /// `FZ16`: Counterpart to [`flush_to_zero`](Self::flush_to_zero) for
        /// half-precision calculations.
        ///
        /// Requires `FEAT_FP16`.
        [19] pub flush_to_zero_half_precision,
        /// For each type of floating-point exception, defines whether the error will be
        /// trapped. If false, the corresponding flag in [`StatusRegister::exceptions`]
        /// will be set instead.
        [ 8..16] pub trapped_exceptions: u8 as Exceptions,
    }
}

system_register_access!(ControlRegister, "FPCR");


bitfield! {
    /// `FPSR`: Indicates non-trapped floating-point exceptions.
    pub struct StatusRegister(u64) {
        /// Indicates any non-trapped exceptions that have been detected since these flags
        /// were last reset.
        [ 0.. 8] pub exceptions: u8 as Exceptions,
    }
}

system_register_access!(StatusRegister, "FPSR");


c_enum! {
    /// Floating-point rounding mode, as defined by IEEE 754.
    pub enum RoundingMode(u8) {
        /// Round to the nearest number, with ties toward even numbers.
        Nearest,
        /// Round toward positive infinity.
        PlusInfinity,
        /// Round toward negative infinity.
        MinusInfinity,
        /// Round toward zero (truncate).
        Zero,
    }
}

bitfield! {
    /// Status/mask bits for each type of floating-point exception.
    pub struct Exceptions(u8) {
        /// `DN`: An operand was a denormal number.
        [7] denormal_input,
        /// `IX`: A result was rounded.
        [4] inexact,
        /// `UF`: A result was too small to be represented accurately.
        [3] underflow,
        /// `OF`: A result was too large to be represented accurately.
        [2] overflow,
        /// `DZ`: Attempted to divide a number by zero (other than zero or infinity, which
        /// raises an [`invalid_operation`] instead).
        [1] divide_by_zero,
        /// `IO`: Attempted a mathematically undefined operation, such as infinity minus
        /// infinity.
        [0] invalid_operation,
    }
}