diff --git a/README.md b/README.md index 0810edf5..c52c4edf 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,8 @@ features = ["c"] - [x] adddf3.c - [x] addsf3.c -- [ ] arm/adddf3vfp.S -- [ ] arm/addsf3vfp.S +- [x] arm/adddf3vfp.S +- [x] arm/addsf3vfp.S - [ ] arm/aeabi_dcmp.S - [ ] arm/aeabi_fcmp.S - [x] arm/aeabi_idivmod.S @@ -92,9 +92,9 @@ features = ["c"] - [x] arm/aeabi_memset.S - [x] arm/aeabi_uidivmod.S - [x] arm/aeabi_uldivmod.S -- [ ] arm/divdf3vfp.S +- [x] arm/divdf3vfp.S - [ ] arm/divmodsi4.S (generic version is done) -- [ ] arm/divsf3vfp.S +- [x] arm/divsf3vfp.S - [ ] arm/divsi3.S (generic version is done) - [ ] arm/eqdf2vfp.S - [ ] arm/eqsf2vfp.S @@ -116,15 +116,15 @@ features = ["c"] - [ ] arm/ltdf2vfp.S - [ ] arm/ltsf2vfp.S - [ ] arm/modsi3.S (generic version is done) -- [ ] arm/muldf3vfp.S -- [ ] arm/mulsf3vfp.S +- [x] arm/muldf3vfp.S +- [x] arm/mulsf3vfp.S - [ ] arm/nedf2vfp.S -- [ ] arm/negdf2vfp.S -- [ ] arm/negsf2vfp.S +- [x] arm/negdf2vfp.S +- [x] arm/negsf2vfp.S - [ ] arm/nesf2vfp.S - [ ] arm/softfloat-alias.list -- [ ] arm/subdf3vfp.S -- [ ] arm/subsf3vfp.S +- [x] arm/subdf3vfp.S +- [x] arm/subsf3vfp.S - [ ] arm/truncdfsf2vfp.S - [ ] arm/udivmodsi4.S (generic version is done) - [ ] arm/udivsi3.S (generic version is done) diff --git a/build.rs b/build.rs index 6c962847..8bad0adc 100644 --- a/build.rs +++ b/build.rs @@ -314,11 +314,7 @@ fn main() { if llvm_target.last().unwrap().ends_with("eabihf") { if !llvm_target[0].starts_with("thumbv7em") { - sources.extend(&["arm/adddf3vfp.S", - "arm/addsf3vfp.S", - "arm/divdf3vfp.S", - "arm/divsf3vfp.S", - "arm/eqdf2vfp.S", + sources.extend(&["arm/eqdf2vfp.S", "arm/eqsf2vfp.S", "arm/extendsfdf2vfp.S", "arm/fixdfsivfp.S", @@ -337,18 +333,11 @@ fn main() { "arm/lesf2vfp.S", "arm/ltdf2vfp.S", "arm/ltsf2vfp.S", - "arm/muldf3vfp.S", - "arm/mulsf3vfp.S", "arm/nedf2vfp.S", "arm/nesf2vfp.S", "arm/restore_vfp_d8_d15_regs.S", - "arm/save_vfp_d8_d15_regs.S", - "arm/subdf3vfp.S", - "arm/subsf3vfp.S"]); + "arm/save_vfp_d8_d15_regs.S"]); } - - sources.extend(&["arm/negdf2vfp.S", "arm/negsf2vfp.S"]); - } if target_arch == "aarch64" { @@ -433,4 +422,10 @@ fn main() { if llvm_target[0] == "thumbv6m" { println!("cargo:rustc-cfg=thumbv6m") } + + // Needed for ARM VFP assembly functions + if llvm_target.last().unwrap().ends_with("hf") || + llvm_target[0] == "aarch64" { + println!("cargo:rustc-cfg=armhf") + } } diff --git a/src/arm.rs b/src/arm.rs index f2027e7b..9e06b1b6 100644 --- a/src/arm.rs +++ b/src/arm.rs @@ -3,6 +3,142 @@ use core::intrinsics; #[cfg(feature = "mem")] use mem::{memcpy, memmove, memset}; +// Thumb1 code can't encode hardware float operations, so some targets +// need functions that wrap the appropriate ARM instructions. +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __adddf3vfp() { + #[cfg(armhf)] + asm!("vadd.f64 d0, d0, d1"); + #[cfg(not(armhf))] + asm!("vmov d6, r0, r1 + vmov d7, r2, r3 + vadd.f64 d6, d6, d7 + vmov r0, r1, d6"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __addsf3vfp() { + #[cfg(armhf)] + asm!("vadd.f32 s0, s0, s1"); + #[cfg(not(armhf))] + asm!("vmov s14, r0 + vmov s15, r1 + vadd.f32 s14, s14, s15 + vmov r0, s14"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __divdf3vfp() { + #[cfg(armhf)] + asm!("vdiv.f64 d0, d0, d1"); + #[cfg(not(armhf))] + asm!("vmov d6, r0, r1 + vmov d7, r2, r3 + vdiv.f64 d5, d6, d7 + vmov r0, r1, d5"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __divsf3vfp() { + #[cfg(armhf)] + asm!("vdiv.f32 s0, s0, s1"); + #[cfg(not(armhf))] + asm!("vmov s14, r0 + vmov s15, r1 + vdiv.f32 s13, s14, s15 + vmov r0, s13"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __muldf3vfp() { + #[cfg(armhf)] + asm!("vmul.f64 d0, d0, d1"); + #[cfg(not(armhf))] + asm!("vmov d6, r0, r1 + vmov d7, r2, r3 + vmul.f64 d6, d6, d7 + vmov r0, r1, d6"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __mulsf3vfp() { + #[cfg(armhf)] + asm!("vmul.f32 s0, s0, s1"); + #[cfg(not(armhf))] + asm!("vmov s14, r0 + vmov s15, r1 + vmul.f32 s13, s14, s15 + vmov r0, s13"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __negdf2vfp() { + #[cfg(armhf)] + asm!("vneg.f64 d0, d0"); + #[cfg(not(armhf))] + asm!("eor r1, r1, #-2147483648"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __negsf2vfp() { + #[cfg(armhf)] + asm!("vneg.f32 s0, s0"); + #[cfg(not(armhf))] + asm!("eor r0, r0, #-2147483648"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __subdf3vfp() { + #[cfg(armhf)] + asm!("vsub.f64 d0, d0, d1"); + #[cfg(not(armhf))] + asm!("vmov d6, r0, r1 + vmov d7, r2, r3 + vsub.f64 d6, d6, d7 + vmov r0, r1, d6"); + asm!("bx lr"); + intrinsics::unreachable(); +} + +#[naked] +#[cfg_attr(not(test), no_mangle)] +pub unsafe fn __subsf3vfp() { + #[cfg(armhf)] + asm!("vsub.f32 s0, s0, s1"); + #[cfg(not(armhf))] + asm!("vmov s14, r0 + vmov s15, r1 + vsub.f32 s14, s14, s15 + vmov r0, s14"); + asm!("bx lr"); + intrinsics::unreachable(); +} + // NOTE This function and the ones below are implemented using assembly because they using a custom // calling convention which can't be implemented using a normal Rust function #[naked]