-
Notifications
You must be signed in to change notification settings - Fork 168
Implement accessing FPSCR #220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 16 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
653a440
Implement accessing FPSCR
bugadani 088972a
Add doc comments
ff2bce3
Add new assembly file to assembler script
376e42e
Add missing EOL
3e3213b
Fix store instructions
808aa0c
Update blobs
bc0db25
Fix doc comments
53b79bd
Where did those ifs come from...
513ffd4
Fix remaining compiler sadness
3cb2102
Stylistic updates, add from_bits
7767dac
Implement bit manipulation methods
0d8723e
Add methods to RMode
3d7648f
Oops. Fix pattern matching
37e6543
Add missing #[inline]s
7c9afcc
Make RMode methods actually accessible
4f22ee1
Add #[allow(clippy::missing_inline_in_public_items)] for consistency
9062f34
Update assemble.sh
bugadani File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
.cfi_sections .debug_frame | ||
|
||
.section .text.__get_FPSCR | ||
.global __get_FPSCR | ||
.thumb_func | ||
.cfi_startproc | ||
__get_FPSCR: | ||
vmrs r0, fpscr | ||
bx lr | ||
.cfi_endproc | ||
.size __get_FPSCR, . - __get_FPSCR | ||
|
||
.section .text.__set_FPSCR | ||
.global __set_FPSCR | ||
.thumb_func | ||
.cfi_startproc | ||
__set_FPSCR: | ||
vmsr fpscr, r0 | ||
bx lr | ||
.cfi_endproc | ||
.size __set_FPSCR, . - __set_FPSCR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,343 @@ | ||
//! Floating-point Status Control Register | ||
|
||
/// Floating-point Status Control Register | ||
#[allow(clippy::missing_inline_in_public_items)] | ||
#[derive(Clone, Copy, Debug)] | ||
pub struct Fpscr { | ||
bits: u32, | ||
} | ||
|
||
impl Fpscr { | ||
/// Creates a `Fspcr` value from raw bits. | ||
#[inline] | ||
pub fn from_bits(bits: u32) -> Self { | ||
Self { bits } | ||
} | ||
|
||
/// Returns the contents of the register as raw bits | ||
#[inline] | ||
pub fn bits(self) -> u32 { | ||
self.bits | ||
} | ||
|
||
/// Read the Negative condition code flag | ||
#[inline] | ||
pub fn n(self) -> bool { | ||
self.bits & (1 << 31) != 0 | ||
} | ||
|
||
/// Sets the Negative condition code flag | ||
#[inline] | ||
pub fn set_n(&mut self, n: bool) { | ||
let mask = 1 << 31; | ||
match n { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Zero condition code flag | ||
#[inline] | ||
pub fn z(self) -> bool { | ||
self.bits & (1 << 30) != 0 | ||
} | ||
|
||
/// Sets the Zero condition code flag | ||
#[inline] | ||
pub fn set_z(&mut self, z: bool) { | ||
let mask = 1 << 30; | ||
match z { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Carry condition code flag | ||
#[inline] | ||
pub fn c(self) -> bool { | ||
self.bits & (1 << 29) != 0 | ||
} | ||
|
||
/// Sets the Carry condition code flag | ||
#[inline] | ||
pub fn set_c(&mut self, c: bool) { | ||
let mask = 1 << 29; | ||
match c { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Overflow condition code flag | ||
#[inline] | ||
pub fn v(self) -> bool { | ||
self.bits & (1 << 28) != 0 | ||
} | ||
|
||
/// Sets the Zero condition code flag | ||
#[inline] | ||
pub fn set_v(&mut self, v: bool) { | ||
let mask = 1 << 28; | ||
match v { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Alternative Half Precision bit | ||
#[inline] | ||
pub fn ahp(self) -> bool { | ||
self.bits & (1 << 26) != 0 | ||
} | ||
|
||
/// Sets the Alternative Half Precision bit | ||
#[inline] | ||
pub fn set_ahp(&mut self, ahp: bool) { | ||
let mask = 1 << 26; | ||
match ahp { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Default NaN mode bit | ||
#[inline] | ||
pub fn dn(self) -> bool { | ||
self.bits & (1 << 25) != 0 | ||
} | ||
|
||
/// Sets the Default NaN mode bit | ||
#[inline] | ||
pub fn set_dn(&mut self, dn: bool) { | ||
let mask = 1 << 25; | ||
match dn { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Flush to Zero mode bit | ||
#[inline] | ||
pub fn fz(self) -> bool { | ||
self.bits & (1 << 24) != 0 | ||
} | ||
|
||
/// Sets the Flush to Zero mode bit | ||
#[inline] | ||
pub fn set_fz(&mut self, fz: bool) { | ||
let mask = 1 << 24; | ||
match fz { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Rounding Mode control field | ||
#[inline] | ||
pub fn rmode(self) -> RMode { | ||
match (self.bits & (3 << 22)) >> 22 { | ||
0 => RMode::Nearest, | ||
1 => RMode::PlusInfinity, | ||
2 => RMode::MinusInfinity, | ||
_ => RMode::Zero, | ||
} | ||
} | ||
|
||
/// Sets the Rounding Mode control field | ||
#[inline] | ||
pub fn set_rmode(&mut self, rmode: RMode) { | ||
let mask = 3 << 22; | ||
match rmode { | ||
RMode::Nearest => self.bits = self.bits & !mask, | ||
RMode::PlusInfinity => self.bits = (self.bits & !mask) | (1 << 22), | ||
RMode::MinusInfinity => self.bits = (self.bits & !mask) | (2 << 22), | ||
RMode::Zero => self.bits = self.bits | mask, | ||
} | ||
} | ||
|
||
/// Read the Input Denormal cumulative exception bit | ||
#[inline] | ||
pub fn idc(self) -> bool { | ||
self.bits & (1 << 7) != 0 | ||
} | ||
|
||
/// Sets the Input Denormal cumulative exception bit | ||
#[inline] | ||
pub fn set_idc(&mut self, idc: bool) { | ||
let mask = 1 << 7; | ||
match idc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Inexact cumulative exception bit | ||
#[inline] | ||
pub fn ixc(self) -> bool { | ||
self.bits & (1 << 4) != 0 | ||
} | ||
|
||
/// Sets the Inexact cumulative exception bit | ||
#[inline] | ||
pub fn set_ixc(&mut self, ixc: bool) { | ||
let mask = 1 << 4; | ||
match ixc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Underflow cumulative exception bit | ||
#[inline] | ||
pub fn ufc(self) -> bool { | ||
self.bits & (1 << 3) != 0 | ||
} | ||
|
||
/// Sets the Underflow cumulative exception bit | ||
#[inline] | ||
pub fn set_ufc(&mut self, ufc: bool) { | ||
let mask = 1 << 3; | ||
match ufc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Overflow cumulative exception bit | ||
#[inline] | ||
pub fn ofc(self) -> bool { | ||
self.bits & (1 << 2) != 0 | ||
} | ||
|
||
/// Sets the Overflow cumulative exception bit | ||
#[inline] | ||
pub fn set_ofc(&mut self, ofc: bool) { | ||
let mask = 1 << 2; | ||
match ofc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Division by Zero cumulative exception bit | ||
#[inline] | ||
pub fn dzc(self) -> bool { | ||
self.bits & (1 << 1) != 0 | ||
} | ||
|
||
/// Sets the Division by Zero cumulative exception bit | ||
#[inline] | ||
pub fn set_dzc(&mut self, dzc: bool) { | ||
let mask = 1 << 1; | ||
match dzc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
|
||
/// Read the Invalid Operation cumulative exception bit | ||
#[inline] | ||
pub fn ioc(self) -> bool { | ||
self.bits & (1 << 0) != 0 | ||
} | ||
|
||
/// Sets the Invalid Operation cumulative exception bit | ||
#[inline] | ||
pub fn set_ioc(&mut self, ioc: bool) { | ||
let mask = 1 << 0; | ||
match ioc { | ||
true => self.bits |= mask, | ||
false => self.bits &= !mask, | ||
} | ||
} | ||
} | ||
|
||
/// Rounding mode | ||
#[allow(clippy::missing_inline_in_public_items)] | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
pub enum RMode { | ||
/// Round to Nearest (RN) mode. This is the reset value. | ||
Nearest, | ||
/// Round towards Plus Infinity (RP) mode. | ||
PlusInfinity, | ||
/// Round towards Minus Infinity (RM) mode. | ||
MinusInfinity, | ||
/// Round towards Zero (RZ) mode. | ||
Zero, | ||
} | ||
|
||
impl RMode { | ||
/// Is Nearest the current rounding mode? | ||
#[inline] | ||
pub fn is_nearest(self) -> bool { | ||
self == RMode::Nearest | ||
} | ||
|
||
/// Is Plus Infinity the current rounding mode? | ||
#[inline] | ||
pub fn is_plus_infinity(self) -> bool { | ||
self == RMode::PlusInfinity | ||
} | ||
|
||
/// Is Minus Infinity the current rounding mode? | ||
#[inline] | ||
pub fn is_minus_infinity(self) -> bool { | ||
self == RMode::MinusInfinity | ||
} | ||
|
||
/// Is Zero the current rounding mode? | ||
#[inline] | ||
pub fn is_zero(self) -> bool { | ||
self == RMode::Zero | ||
} | ||
} | ||
|
||
/// Read the FPSCR register | ||
#[inline] | ||
pub fn read() -> Fpscr { | ||
match () { | ||
#[cfg(all(cortex_m, feature = "inline-asm"))] | ||
() => { | ||
let r: u32; | ||
unsafe { | ||
llvm_asm!("vmrs $0, fpscr" : "=r"(r) ::: "volatile"); | ||
} | ||
Fpscr::from_bits(r) | ||
} | ||
|
||
#[cfg(all(cortex_m, not(feature = "inline-asm")))] | ||
() => unsafe { | ||
extern "C" { | ||
fn __get_FPSCR() -> u32; | ||
} | ||
Fpscr::from_bits(__get_FPSCR()) | ||
}, | ||
|
||
#[cfg(not(cortex_m))] | ||
() => unimplemented!(), | ||
} | ||
} | ||
|
||
/// Set the value of the FPSCR register | ||
#[inline] | ||
pub unsafe fn write(_fspcr: Fpscr) { | ||
match () { | ||
#[cfg(all(cortex_m, feature = "inline-asm"))] | ||
() => { | ||
let bits = _fspcr.bits(); | ||
llvm_asm!("vmsr fpscr, $0" :: "r"(bits) :: "volatile"); | ||
} | ||
|
||
#[cfg(all(cortex_m, not(feature = "inline-asm")))] | ||
() => { | ||
extern "C" { | ||
fn __set_FPSCR(bits: u32); | ||
} | ||
|
||
__set_FPSCR(_fspcr.bits()); | ||
} | ||
|
||
#[cfg(not(cortex_m))] | ||
() => unimplemented!(), | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.