ARM: keep some non-aeabi symbols around

- multi3: there's no aeabi equivalent
- divmod{s,d}i4: these are directly called by __aeabi_{l,i}divmod
- add{s,d}f3: required by the C sub{s,d}f3 implementation

but make sure they also use the AAPCS calling convention
master
Jorge Aparicio 2017-02-07 12:51:18 -05:00
parent dfa7b161aa
commit 57085be2ea
4 changed files with 40 additions and 21 deletions

View File

@ -4,12 +4,11 @@ use core::num::Wrapping;
use float::Float;
macro_rules! add {
($intrinsic:ident: $ty:ty) => {
($abi:tt, $intrinsic:ident: $ty:ty) => {
/// Returns `a + b`
#[allow(unused_parens)]
#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
#[cfg_attr(not(test), no_mangle)]
pub extern $abi fn $intrinsic(a: $ty, b: $ty) -> $ty {
let one = Wrapping(1 as <$ty as Float>::Int);
let zero = Wrapping(0 as <$ty as Float>::Int);
@ -182,8 +181,17 @@ macro_rules! add {
}
}
add!(__addsf3: f32);
add!(__adddf3: f64);
#[cfg(target_arch = "arm")]
add!("aapcs", __addsf3: f32);
#[cfg(not(target_arch = "arm"))]
add!("C", __addsf3: f32);
#[cfg(target_arch = "arm")]
add!("aapcs", __adddf3: f64);
#[cfg(not(target_arch = "arm"))]
add!("C", __adddf3: 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

View File

@ -2,11 +2,11 @@ use int::LargeInt;
use int::Int;
macro_rules! mul {
($intrinsic:ident: $ty:ty) => {
($(#[$attr:meta])+ |
$abi:tt, $intrinsic:ident: $ty:ty) => {
/// Returns `a * b`
#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
$(#[$attr])+
pub extern $abi fn $intrinsic(a: $ty, b: $ty) -> $ty {
let half_bits = <$ty>::bits() / 4;
let lower_mask = !0 >> half_bits;
let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
@ -74,9 +74,17 @@ macro_rules! mulo {
}
#[cfg(not(all(feature = "c", target_arch = "x86")))]
mul!(__muldi3: u64);
mul!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
| "C", __muldi3: u64);
mul!(__multi3: i128);
#[cfg(not(target_arch = "arm"))]
mul!(#[cfg_attr(not(test), no_mangle)]
| "C", __multi3: i128);
#[cfg(target_arch = "arm")]
mul!(#[cfg_attr(not(test), no_mangle)]
| "aapcs", __multi3: i128);
mulo!(__mulosi4: i32);
mulo!(__mulodi4: i64);

View File

@ -40,11 +40,10 @@ macro_rules! mod_ {
}
macro_rules! divmod {
($intrinsic:ident, $div:ident: $ty:ty) => {
($abi:tt, $intrinsic:ident, $div:ident: $ty:ty) => {
/// Returns `a / b` and sets `*rem = n % d`
#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
pub extern "C" fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
#[cfg_attr(not(test), no_mangle)]
pub extern $abi fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
#[cfg(all(feature = "c", any(target_arch = "x86")))]
extern {
fn $div(a: $ty, b: $ty) -> $ty;
@ -87,9 +86,13 @@ mod_!(__modti3: i128, u128);
mod_!(__modti3: i128, u128, ::U64x2, ::sconv);
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
divmod!(__divmodsi4, __divsi3: i32);
divmod!("C", __divmodsi4, __divsi3: i32);
divmod!(__divmoddi4, __divdi3: i64);
#[cfg(target_arch = "arm")]
divmod!("aapcs", __divmoddi4, __divdi3: i64);
#[cfg(not(target_arch = "arm"))]
divmod!("C", __divmoddi4, __divdi3: i64);
#[cfg(test)]
mod tests {

View File

@ -80,15 +80,15 @@ pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 {
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
#[cfg_attr(not(test), no_mangle)]
pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
#[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios")))]
#[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m)))]
extern "C" {
fn __udivsi3(n: u32, d: u32) -> u32;
}
let q = match () {
#[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios")))]
#[cfg(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m)))]
() => unsafe { __udivsi3(n, d) },
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
() => __udivsi3(n, d),
};
if let Some(rem) = rem {