diff --git a/library/compiler-builtins/etc/function-definitions.json b/library/compiler-builtins/etc/function-definitions.json index 39f789704779..38d609da3fcf 100644 --- a/library/compiler-builtins/etc/function-definitions.json +++ b/library/compiler-builtins/etc/function-definitions.json @@ -824,6 +824,7 @@ "rint": { "sources": [ "libm/src/math/arch/aarch64/rounding.rs", + "libm/src/math/arch/i586/rounding.rs", "libm/src/math/arch/wasm32/rounding.rs", "libm/src/math/generic/rint.rs", "libm/src/math/rint.rs" diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index bc28d970e764..2034e89c71e4 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -297,15 +297,6 @@ fn check_int(input: (f32,), actual: I, expected: I, ctx: &CheckCtx) -> C impl MaybeOverride<(f64,)> for SpecialCase { fn check_float(input: (f64,), actual: F, expected: F, ctx: &CheckCtx) -> CheckAction { - if cfg!(x86_no_sse2) - && (ctx.base_name == BaseName::Rint || ctx.base_name == BaseName::Roundeven) - && (expected - actual).abs() <= F::ONE - && (expected - actual).abs() > F::ZERO - { - // Our rounding mode is incorrect. - return XFAIL("i586 rint rounding mode"); - } - if ctx.base_name == BaseName::J0 && input.0 < -1e300 { // Errors get huge close to -inf return XFAIL_NOCHECK; diff --git a/library/compiler-builtins/libm/src/math/arch/i586/mod.rs b/library/compiler-builtins/libm/src/math/arch/i586/mod.rs index fa8b79875764..f80be49fc4b3 100644 --- a/library/compiler-builtins/libm/src/math/arch/i586/mod.rs +++ b/library/compiler-builtins/libm/src/math/arch/i586/mod.rs @@ -11,4 +11,4 @@ mod rounding; pub use exp_all::{x87_exp, x87_exp2, x87_exp2f, x87_exp10, x87_exp10f, x87_expf}; -pub use rounding::{ceil, floor}; +pub use rounding::{ceil, floor, rint}; diff --git a/library/compiler-builtins/libm/src/math/arch/i586/rounding.rs b/library/compiler-builtins/libm/src/math/arch/i586/rounding.rs index 3981e3d109ff..45bf0adafd30 100644 --- a/library/compiler-builtins/libm/src/math/arch/i586/rounding.rs +++ b/library/compiler-builtins/libm/src/math/arch/i586/rounding.rs @@ -51,3 +51,53 @@ pub fn floor(mut x: f64) -> f64 { } x } + +/// Note that this respects rounding mode. Because it is UB to have a non-default rounding +/// mode in Rust, this acts as roundeven. +pub fn rint(mut x: f64) -> f64 { + unsafe { + core::arch::asm!( + "fld qword ptr [{x}]", + "frndint", + "fstp qword ptr [{x}]", + x = in(reg) &mut x, + // All the x87 FPU stack is used, all registers must be clobbered + out("st(0)") _, out("st(1)") _, + out("st(2)") _, out("st(3)") _, + out("st(4)") _, out("st(5)") _, + out("st(6)") _, out("st(7)") _, + options(nostack), + ); + } + x +} + +/* FIXME(msrv): after 1.82, the below can be used to compute control words using `asm_const`: + +#[derive(Clone, Copy, Debug, PartialEq)] +enum Precision { + Single, + Double, + Extended, +} + +/// See: IntelĀ® 64 and IA-32 Architectures Software Developer's Manual Volume 1: +/// Basic Architecture, section 8.1.5 x87 FPU Control Word. +const fn make_fpcw(round: Round, prec: Precision) -> u16 { + let exceptions = 0b111111; // Disable all 6 exceptions + let misc = 0b1000000; // reserved field usually set by default + let pc = match prec { + Precision::Single => 0b00, + Precision::Double => 0b10, + Precision::Extended => 0b11, + }; + let rc = match round { + Round::Nearest => 0b00, + Round::Negative => 0b01, + Round::Positive => 0b10, + Round::Zero => 0b11, + }; + (rc << 10) | (pc << 8) | misc | exceptions +} + +*/ diff --git a/library/compiler-builtins/libm/src/math/arch/mod.rs b/library/compiler-builtins/libm/src/math/arch/mod.rs index bcca0ff8073c..1bed464cfa7d 100644 --- a/library/compiler-builtins/libm/src/math/arch/mod.rs +++ b/library/compiler-builtins/libm/src/math/arch/mod.rs @@ -48,6 +48,7 @@ pub use i586::{ ceil, floor, + rint, x87_exp, x87_exp10, x87_exp10f, diff --git a/library/compiler-builtins/libm/src/math/rint.rs b/library/compiler-builtins/libm/src/math/rint.rs index 0cb0e2d3637d..75c46acc0e85 100644 --- a/library/compiler-builtins/libm/src/math/rint.rs +++ b/library/compiler-builtins/libm/src/math/rint.rs @@ -37,6 +37,7 @@ pub fn rint(x: f64) -> f64 { all(target_arch = "aarch64", target_feature = "neon"), all(target_arch = "wasm32", intrinsics_enabled), ), + use_arch_required: x86_no_sse2, args: x, }