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
//! Floating-point rounding modes and accrued exception flags (`fcsr`).
use std::ops::BitOr;
/// RISC-V rounding mode encoding.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum RoundingMode {
/// Round to Nearest, ties to Even (default IEEE mode).
Rne = 0b000,
/// Round towards Zero.
Rtz = 0b001,
/// Round Down (towards −∞).
Rdn = 0b010,
/// Round Up (towards +∞).
Rup = 0b011,
/// Round to Nearest, ties to Max Magnitude.
Rmm = 0b100,
}
impl RoundingMode {
/// Decodes a 3-bit rounding mode field from an instruction or `fcsr.frm`.
///
/// Returns `None` for reserved encodings (0b101, 0b110) and the dynamic
/// sentinel (0b111), which must be resolved to `fcsr.frm` by the caller.
pub const fn from_bits(bits: u8) -> Option<Self> {
match bits & 0x7 {
0b000 => Some(Self::Rne),
0b001 => Some(Self::Rtz),
0b010 => Some(Self::Rdn),
0b011 => Some(Self::Rup),
0b100 => Some(Self::Rmm),
_ => None, // 0b101, 0b110 reserved; 0b111 = dynamic
}
}
}
/// Floating-point exception flags (RISC-V `fcsr.fflags`).
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct FpFlags(u8);
impl FpFlags {
/// No exceptions raised.
pub const NONE: Self = Self(0);
/// Invalid Operation.
pub const NV: Self = Self(1 << 4);
/// Divide by Zero.
pub const DZ: Self = Self(1 << 3);
/// Overflow.
pub const OF: Self = Self(1 << 2);
/// Underflow.
pub const UF: Self = Self(1 << 1);
/// Inexact.
pub const NX: Self = Self(1 << 0);
/// Creates `FpFlags` from a raw 5-bit value.
pub const fn from_bits(val: u8) -> Self {
Self(val & 0x1F)
}
/// Returns the raw 5-bit flag value for writing into `fcsr`.
pub const fn bits(self) -> u8 {
self.0
}
/// Returns true if no flags are set.
pub const fn is_empty(self) -> bool {
self.0 == 0
}
/// Returns true if the specified flag is set.
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
}
impl BitOr for FpFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}