Skip to content

Commit 32eba6c

Browse files
bors[bot]Disasm
andcommitted
Merge #23
23: Add fcsr register r=dvc94ch a=Disasm Co-authored-by: Vadim Kaushan <[email protected]>
2 parents 037e8bd + 8222812 commit 32eba6c

File tree

7 files changed

+135
-0
lines changed

7 files changed

+135
-0
lines changed

asm.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ __sfence_vma:
2424
sfence.vma a0, a1
2525
ret
2626

27+
REG_READ_WRITE(fcsr, 0x003)
28+
REG_SET_CLEAR(fcsr, 0x003)
2729

2830
// M-mode registers
2931
REG_READ(mcause, 0x342)

bin/riscv32imac-unknown-none-elf.a

500 Bytes
Binary file not shown.

bin/riscv32imc-unknown-none-elf.a

500 Bytes
Binary file not shown.

bin/riscv64gc-unknown-none-elf.a

658 Bytes
Binary file not shown.

bin/riscv64imac-unknown-none-elf.a

658 Bytes
Binary file not shown.

src/register/fcsr.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//! Floating-point control and status register
2+
3+
use bit_field::BitField;
4+
5+
/// Floating-point control and status register
6+
#[derive(Clone, Copy, Debug)]
7+
pub struct FCSR {
8+
bits: u32,
9+
}
10+
11+
/// Accrued Exception Flags
12+
#[derive(Clone, Copy, Debug)]
13+
pub struct Flags(u32);
14+
15+
/// Accrued Exception Flag
16+
#[derive(Clone, Copy, Debug)]
17+
pub enum Flag {
18+
/// Inexact
19+
NX = 0b00001,
20+
21+
/// Underflow
22+
UF = 0b00010,
23+
24+
/// Overflow
25+
OF = 0b00100,
26+
27+
/// Divide by Zero
28+
DZ = 0b01000,
29+
30+
/// Invalid Operation
31+
NV = 0b10000,
32+
}
33+
34+
impl Flags {
35+
/// Inexact
36+
#[inline]
37+
pub fn nx(&self) -> bool {
38+
self.0.get_bit(0)
39+
}
40+
41+
/// Underflow
42+
#[inline]
43+
pub fn uf(&self) -> bool {
44+
self.0.get_bit(1)
45+
}
46+
47+
/// Overflow
48+
#[inline]
49+
pub fn of(&self) -> bool {
50+
self.0.get_bit(2)
51+
}
52+
53+
/// Divide by Zero
54+
#[inline]
55+
pub fn dz(&self) -> bool {
56+
self.0.get_bit(3)
57+
}
58+
59+
/// Invalid Operation
60+
#[inline]
61+
pub fn nv(&self) -> bool {
62+
self.0.get_bit(4)
63+
}
64+
}
65+
66+
/// Rounding Mode
67+
pub enum RoundingMode {
68+
RoundToNearestEven = 0b000,
69+
RoundTowardsZero = 0b001,
70+
RoundDown = 0b010,
71+
RoundUp = 0b011,
72+
RoundToNearestMaxMagnitude = 0b100,
73+
Invalid = 0b111,
74+
}
75+
76+
impl FCSR {
77+
/// Returns the contents of the register as raw bits
78+
pub fn bits(&self) -> u32 {
79+
self.bits
80+
}
81+
82+
/// Accrued Exception Flags
83+
#[inline]
84+
pub fn fflags(&self) -> Flags {
85+
Flags(self.bits.get_bits(0..5))
86+
}
87+
88+
/// Rounding Mode
89+
#[inline]
90+
pub fn frm(&self) -> RoundingMode {
91+
match self.bits.get_bits(5..8) {
92+
0b000 => RoundingMode::RoundToNearestEven,
93+
0b001 => RoundingMode::RoundTowardsZero,
94+
0b010 => RoundingMode::RoundDown,
95+
0b011 => RoundingMode::RoundUp,
96+
0b100 => RoundingMode::RoundToNearestMaxMagnitude,
97+
_ => RoundingMode::Invalid,
98+
}
99+
}
100+
}
101+
102+
read_csr!(0x003, __read_fcsr);
103+
write_csr!(0x003, __write_fcsr);
104+
clear!(0x003, __clear_fcsr);
105+
106+
/// Reads the CSR
107+
#[inline]
108+
pub fn read() -> FCSR {
109+
FCSR { bits: unsafe{ _read() as u32 } }
110+
}
111+
112+
/// Writes the CSR
113+
#[inline]
114+
pub unsafe fn set_rounding_mode(frm: RoundingMode) {
115+
let old = read();
116+
let bits = ((frm as u32) << 5) | old.fflags().0;
117+
_write(bits as usize);
118+
}
119+
120+
/// Resets `fflags` field bits
121+
#[inline]
122+
pub unsafe fn clear_flags() {
123+
let mask = 0b11111;
124+
_clear(mask);
125+
}
126+
127+
/// Resets `fflags` field bit
128+
#[inline]
129+
pub unsafe fn clear_flag(flag: Flag) {
130+
_clear(flag as usize);
131+
}

src/register/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#[macro_use]
1414
mod macros;
1515

16+
pub mod fcsr;
17+
1618
pub mod mcause;
1719
pub mod mcycle;
1820
pub mod mcycleh;

0 commit comments

Comments
 (0)