diff --git a/etc/function-definitions.json b/etc/function-definitions.json index 88070abf0..3e2b14d31 100644 --- a/etc/function-definitions.json +++ b/etc/function-definitions.json @@ -985,6 +985,7 @@ "sqrt": { "sources": [ "libm/src/math/arch/aarch64/sqrt.rs", + "libm/src/math/arch/arm/sqrt.rs", "libm/src/math/arch/loongarch/sqrt.rs", "libm/src/math/arch/wasm32/sqrt.rs", "libm/src/math/arch/x86/sqrt.rs", @@ -996,6 +997,7 @@ "sqrtf": { "sources": [ "libm/src/math/arch/aarch64/sqrt.rs", + "libm/src/math/arch/arm/sqrt.rs", "libm/src/math/arch/loongarch/sqrt.rs", "libm/src/math/arch/wasm32/sqrt.rs", "libm/src/math/arch/x86/sqrt.rs", diff --git a/libm/configure.rs b/libm/configure.rs index ec4e46c39..21954cd1d 100644 --- a/libm/configure.rs +++ b/libm/configure.rs @@ -19,6 +19,7 @@ pub struct Config { pub target_triple: String, pub target_triple_split: Vec, pub target_arch: String, + pub target_abi: Option, pub target_env: String, pub target_families: Vec, pub target_os: String, @@ -63,6 +64,8 @@ impl Config { opt_level: env::var("OPT_LEVEL").unwrap(), cargo_features, target_arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(), + // FIXME(msrv): defined since 1.78. + target_abi: env::var("CARGO_CFG_TARGET_ABI").ok(), target_env: env::var("CARGO_CFG_TARGET_ENV").unwrap(), target_families, target_os: env::var("CARGO_CFG_TARGET_OS").unwrap(), @@ -114,6 +117,9 @@ pub fn emit(cfg: &Config) { // We have to cfg our code accordingly. let thumb_1 = split[0] == "thumbv6m" || split[0] == "thumbv8m.base"; + // FIXME(msrv): `cfg(target_abi)` is usable since 1.78. + let target_abi_eabihf = cfg.target_abi.as_deref() == Some("eabihf"); + // Shorthand to detect i586 targets let x86_no_sse2 = cfg.target_arch == "x86" && !cfg.target_features.iter().any(|f| f == "sse2"); @@ -123,7 +129,10 @@ pub fn emit(cfg: &Config) { // Arch shorthand config is used in most crates. set_cfg("thumb", thumb); set_cfg("thumb_1", thumb_1); + set_cfg("target_abi_eabihf", target_abi_eabihf); set_cfg("x86_no_sse2", x86_no_sse2); + // FIXME(arm_target_feature): the exact target features are not yet stable. + println!("cargo:rustc-check-cfg=cfg(target_feature, values(\"vfp2sp\", \"vfp2\"))"); match cfg.library { Library::CompilerBuiltins => { diff --git a/libm/src/math/arch/arm/mod.rs b/libm/src/math/arch/arm/mod.rs new file mode 100644 index 000000000..bcf4074f2 --- /dev/null +++ b/libm/src/math/arch/arm/mod.rs @@ -0,0 +1,8 @@ +//! Architecture-specific support for Arm32/Thumb with hard float ABI. + +mod sqrt; + +#[cfg(target_feature = "vfp2")] +pub use sqrt::sqrt; +#[cfg(target_feature = "vfp2sp")] +pub use sqrt::sqrtf; diff --git a/libm/src/math/arch/arm/sqrt.rs b/libm/src/math/arch/arm/sqrt.rs new file mode 100644 index 000000000..1003d3ff5 --- /dev/null +++ b/libm/src/math/arch/arm/sqrt.rs @@ -0,0 +1,29 @@ +#[cfg(target_feature = "vfp2sp")] +pub fn sqrtf(mut x: f32) -> f32 { + // SAFETY: vsqrt.f32 is available with `vfp2sp`. + unsafe { + core::arch::asm!( + "vsqrt.f32 {x}, {x}", + x = inout(sreg) x, + options(nostack, nomem, pure), + ); + } + x +} + +#[cfg(target_feature = "vfp2")] +pub fn sqrt(mut x: f64) -> f64 { + // SAFETY: vsqrt.f64 is available with `vfp2`. + // Can't just use plain old `dreg` because `vfp2` only provides a base + // level of FPU support with a non-specified amount of fp64 registers. + // It's fine to use `dreg_low16` here, but use `dreg_low8` instead to + // keep the requirements as minimal as possible. + unsafe { + core::arch::asm!( + "vsqrt.f64 {x}, {x}", + x = inout(dreg_low8) x, + options(nostack, nomem, pure), + ); + } + x +} diff --git a/libm/src/math/arch/mod.rs b/libm/src/math/arch/mod.rs index ab2c4a177..a9b95d0d4 100644 --- a/libm/src/math/arch/mod.rs +++ b/libm/src/math/arch/mod.rs @@ -41,6 +41,14 @@ cfg_select_nofmt! { sqrtf16, }; } + all(target_arch = "arm", target_abi_eabihf) => { + mod arm; + + #[cfg(target_feature = "vfp2sp")] + pub use arm::sqrtf; + #[cfg(target_feature = "vfp2")] + pub use arm::sqrt; + } any(target_arch = "loongarch32", target_arch = "loongarch64") => { mod loongarch; diff --git a/libm/src/math/sqrt.rs b/libm/src/math/sqrt.rs index a8e2a3876..5c8a32a1a 100644 --- a/libm/src/math/sqrt.rs +++ b/libm/src/math/sqrt.rs @@ -21,6 +21,7 @@ pub fn sqrtf(x: f32) -> f32 { name: sqrtf, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(target_arch = "arm", target_abi_eabihf, target_feature = "vfp2sp"), all(target_arch = "wasm32", intrinsics_enabled), all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "f"), target_feature = "sse2" @@ -38,6 +39,7 @@ pub fn sqrt(x: f64) -> f64 { name: sqrt, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(target_arch = "arm", target_abi_eabihf, target_feature = "vfp2"), all(target_arch = "wasm32", intrinsics_enabled), all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "d"), target_feature = "sse2"