Skip to content

Commit

Permalink
Merge pull request #288 from Sizurka/rom-intrinsics
Browse files Browse the repository at this point in the history
Connect Bootrom Instrinsics
  • Loading branch information
9names authored Feb 13, 2022
2 parents 8bdecd2 + 80c84b1 commit f46c23d
Show file tree
Hide file tree
Showing 12 changed files with 1,358 additions and 69 deletions.
2 changes: 2 additions & 0 deletions rp2040-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ rt = ["rp2040-pac/rt"]
# embassy-traits = ["embassy_traits", "futures"]
alloc = []
rom-func-cache = []
disable-intrinsics = []
rom-v2-intrinsics = []
89 changes: 89 additions & 0 deletions rp2040-hal/src/float/add_sub.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use super::{Float, Int};
use crate::rom_data;

trait ROMAdd {
fn rom_add(self, b: Self) -> Self;
}

impl ROMAdd for f32 {
fn rom_add(self, b: Self) -> Self {
rom_data::float_funcs::fadd(self, b)
}
}

impl ROMAdd for f64 {
fn rom_add(self, b: Self) -> Self {
rom_data::double_funcs::dadd(self, b)
}
}

fn add<F: Float + ROMAdd>(a: F, b: F) -> F {
if a.is_not_finite() {
if b.is_not_finite() {
let class_a = a.repr() & (F::SIGNIFICAND_MASK | F::SIGN_MASK);
let class_b = b.repr() & (F::SIGNIFICAND_MASK | F::SIGN_MASK);

if class_a == F::Int::ZERO && class_b == F::Int::ZERO {
// inf + inf = inf
return a;
}
if class_a == F::SIGN_MASK && class_b == F::SIGN_MASK {
// -inf + (-inf) = -inf
return a;
}

// Sign mismatch, or either is NaN already
return F::NAN;
}

// [-]inf/NaN + X = [-]inf/NaN
return a;
}

if b.is_not_finite() {
// X + [-]inf/NaN = [-]inf/NaN
return b;
}

a.rom_add(b)
}

intrinsics! {
#[alias = __addsf3vfp]
#[aeabi = __aeabi_fadd]
extern "C" fn __addsf3(a: f32, b: f32) -> f32 {
add(a, b)
}

#[bootrom_v2]
#[alias = __adddf3vfp]
#[aeabi = __aeabi_dadd]
extern "C" fn __adddf3(a: f64, b: f64) -> f64 {
add(a, b)
}

// The ROM just implements subtraction the same way, so just do it here
// and save the work of implementing more complicated NaN/inf handling.

#[alias = __subsf3vfp]
#[aeabi = __aeabi_fsub]
extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
add(a, -b)
}

#[bootrom_v2]
#[alias = __subdf3vfp]
#[aeabi = __aeabi_dsub]
extern "C" fn __subdf3(a: f64, b: f64) -> f64 {
add(a, -b)
}

extern "aapcs" fn __aeabi_frsub(a: f32, b: f32) -> f32 {
add(b, -a)
}

#[bootrom_v2]
extern "aapcs" fn __aeabi_drsub(a: f64, b: f64) -> f64 {
add(b, -a)
}
}
198 changes: 198 additions & 0 deletions rp2040-hal/src/float/cmp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
use super::Float;
use crate::rom_data;

trait ROMCmp {
fn rom_cmp(self, b: Self) -> i32;
}

impl ROMCmp for f32 {
fn rom_cmp(self, b: Self) -> i32 {
rom_data::float_funcs::fcmp(self, b)
}
}

impl ROMCmp for f64 {
fn rom_cmp(self, b: Self) -> i32 {
rom_data::double_funcs::dcmp(self, b)
}
}

fn le_abi<F: Float + ROMCmp>(a: F, b: F) -> i32 {
if a.is_nan() || b.is_nan() {
1
} else {
a.rom_cmp(b)
}
}

fn ge_abi<F: Float + ROMCmp>(a: F, b: F) -> i32 {
if a.is_nan() || b.is_nan() {
-1
} else {
a.rom_cmp(b)
}
}

intrinsics! {
#[slower_than_default]
#[bootrom_v2]
#[alias = __eqsf2, __ltsf2, __nesf2]
extern "C" fn __lesf2(a: f32, b: f32) -> i32 {
le_abi(a, b)
}

#[slower_than_default]
#[bootrom_v2]
#[alias = __eqdf2, __ltdf2, __nedf2]
extern "C" fn __ledf2(a: f64, b: f64) -> i32 {
le_abi(a, b)
}

#[slower_than_default]
#[bootrom_v2]
#[alias = __gtsf2]
extern "C" fn __gesf2(a: f32, b: f32) -> i32 {
ge_abi(a, b)
}

#[slower_than_default]
#[bootrom_v2]
#[alias = __gtdf2]
extern "C" fn __gedf2(a: f64, b: f64) -> i32 {
ge_abi(a, b)
}


#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_fcmple(a: f32, b: f32) -> i32 {
(le_abi(a, b) <= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_fcmpge(a: f32, b: f32) -> i32 {
(ge_abi(a, b) >= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_fcmpeq(a: f32, b: f32) -> i32 {
(le_abi(a, b) == 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_fcmplt(a: f32, b: f32) -> i32 {
(le_abi(a, b) < 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_fcmpgt(a: f32, b: f32) -> i32 {
(ge_abi(a, b) > 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_dcmple(a: f64, b: f64) -> i32 {
(le_abi(a, b) <= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_dcmpge(a: f64, b: f64) -> i32 {
(ge_abi(a, b) >= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_dcmpeq(a: f64, b: f64) -> i32 {
(le_abi(a, b) == 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_dcmplt(a: f64, b: f64) -> i32 {
(le_abi(a, b) < 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "aapcs" fn __aeabi_dcmpgt(a: f64, b: f64) -> i32 {
(ge_abi(a, b) > 0) as i32
}


#[slower_than_default]
#[bootrom_v2]
extern "C" fn __gesf2vfp(a: f32, b: f32) -> i32 {
(ge_abi(a, b) >= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __gedf2vfp(a: f64, b: f64) -> i32 {
(ge_abi(a, b) >= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __gtsf2vfp(a: f32, b: f32) -> i32 {
(ge_abi(a, b) > 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __gtdf2vfp(a: f64, b: f64) -> i32 {
(ge_abi(a, b) > 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __ltsf2vfp(a: f32, b: f32) -> i32 {
(le_abi(a, b) < 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __ltdf2vfp(a: f64, b: f64) -> i32 {
(le_abi(a, b) < 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __lesf2vfp(a: f32, b: f32) -> i32 {
(le_abi(a, b) <= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __ledf2vfp(a: f64, b: f64) -> i32 {
(le_abi(a, b) <= 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __nesf2vfp(a: f32, b: f32) -> i32 {
(le_abi(a, b) != 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __nedf2vfp(a: f64, b: f64) -> i32 {
(le_abi(a, b) != 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __eqsf2vfp(a: f32, b: f32) -> i32 {
(le_abi(a, b) == 0) as i32
}

#[slower_than_default]
#[bootrom_v2]
extern "C" fn __eqdf2vfp(a: f64, b: f64) -> i32 {
(le_abi(a, b) == 0) as i32
}
}
Loading

0 comments on commit f46c23d

Please sign in to comment.