From 5bb969d8f5ba65aa74ab0b2804d9aebbd03614f0 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 8 Feb 2017 10:10:40 -0500 Subject: [PATCH] implement float subtraction as a + (-b) --- build.rs | 2 - compiler-rt/compiler-rt-cdylib/build.rs | 2 + compiler-rt/compiler-rt-cdylib/src/lib.rs | 4 ++ src/arm.rs | 12 +++++- src/float/mod.rs | 1 + src/float/sub.rs | 45 +++++++++++++++++++++++ 6 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/float/sub.rs diff --git a/build.rs b/build.rs index 79fbcf3..532e232 100644 --- a/build.rs +++ b/build.rs @@ -170,8 +170,6 @@ fn main() { "popcountdi2.c", "popcountsi2.c", "powixf2.c", - "subdf3.c", - "subsf3.c", "subvdi3.c", "subvsi3.c", "truncdfhf2.c", diff --git a/compiler-rt/compiler-rt-cdylib/build.rs b/compiler-rt/compiler-rt-cdylib/build.rs index 269070c..0f36143 100644 --- a/compiler-rt/compiler-rt-cdylib/build.rs +++ b/compiler-rt/compiler-rt-cdylib/build.rs @@ -60,6 +60,8 @@ fn main() { "addsf3.c", "powidf2.c", "powisf2.c", + "subdf3.c", + "subsf3.c", // 128 bit integers "lshrti3.c", "modti3.c", diff --git a/compiler-rt/compiler-rt-cdylib/src/lib.rs b/compiler-rt/compiler-rt-cdylib/src/lib.rs index a724614..b76e1fd 100644 --- a/compiler-rt/compiler-rt-cdylib/src/lib.rs +++ b/compiler-rt/compiler-rt-cdylib/src/lib.rs @@ -24,6 +24,8 @@ extern { fn __adddf3(); fn __powisf2(); fn __powidf2(); + fn __subsf3(); + fn __subdf3(); } macro_rules! declare { @@ -57,6 +59,8 @@ declare!(___addsf3, __addsf3); declare!(___adddf3, __adddf3); declare!(___powisf2, __powisf2); declare!(___powidf2, __powidf2); +declare!(___subsf3, __subsf3); +declare!(___subdf3, __subdf3); #[cfg(all(not(windows), not(target_arch = "mips64"), diff --git a/src/arm.rs b/src/arm.rs index 67947a1..f2027e7 100644 --- a/src/arm.rs +++ b/src/arm.rs @@ -60,7 +60,6 @@ pub unsafe fn __aeabi_ldivmod() { intrinsics::unreachable(); } -// TODO: These aeabi_* functions should be defined as aliases #[cfg_attr(not(test), no_mangle)] pub extern "aapcs" fn __aeabi_dadd(a: f64, b: f64) -> f64 { ::float::add::__adddf3(a, b) @@ -71,6 +70,16 @@ pub extern "aapcs" fn __aeabi_fadd(a: f32, b: f32) -> f32 { ::float::add::__addsf3(a, b) } +#[cfg_attr(not(test), no_mangle)] +pub extern "aapcs" fn __aeabi_dsub(a: f64, b: f64) -> f64 { + ::float::sub::__subdf3(a, b) +} + +#[cfg_attr(not(test), no_mangle)] +pub extern "aapcs" fn __aeabi_fsub(a: f32, b: f32) -> f32 { + ::float::sub::__subsf3(a, b) +} + #[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))] #[cfg_attr(not(test), no_mangle)] pub extern "aapcs" fn __aeabi_idiv(a: i32, b: i32) -> i32 { @@ -103,6 +112,7 @@ pub extern "aapcs" fn __aeabi_uidiv(a: u32, b: u32) -> u32 { ::int::udiv::__udivsi3(a, b) } +// TODO: These aeabi_* functions should be defined as aliases #[cfg(not(feature = "mem"))] extern "C" { fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; diff --git a/src/float/mod.rs b/src/float/mod.rs index 134c32d..08a1b6d 100644 --- a/src/float/mod.rs +++ b/src/float/mod.rs @@ -2,6 +2,7 @@ use core::mem; pub mod add; pub mod pow; +pub mod sub; /// Trait for some basic operations on floats pub trait Float: Sized + Copy { diff --git a/src/float/sub.rs b/src/float/sub.rs new file mode 100644 index 0000000..928d738 --- /dev/null +++ b/src/float/sub.rs @@ -0,0 +1,45 @@ +use float::Float; + +macro_rules! sub { + ($(#[$attr:meta])* + | $intrinsic:ident: $ty:ty) => { + /// Returns `a - b` + $(#[$attr])* + pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty { + a + <$ty>::from_repr(b.repr() ^ <$ty>::sign_mask()) + } + } +} + +sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] + | __subsf3: f32); + +sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] + #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] + | __subdf3: f64); + +// NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabi*, our implementation doesn't +// match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll +// just avoid testing against them on those targets. Do note that our implementation gives the +// correct answer; gcc_s and compiler-rt are incorrect in this case. +#[cfg(all(test, not(arm_linux)))] +mod tests { + use core::{f32, f64}; + use qc::{F32, F64}; + + check! { + fn __subsf3(f: extern "C" fn(f32, f32) -> f32, + a: F32, + b: F32) + -> Option { + Some(F32(f(a.0, b.0))) + } + + fn __subdf3(f: extern "C" fn(f64, f64) -> f64, + a: F64, + b: F64) -> Option { + Some(F64(f(a.0, b.0))) + } + } +}