| //! Architecture-specific support for x86-32 without SSE2 |
| //! |
| //! We use an alternative implementation on x86, because the |
| //! main implementation fails with the x87 FPU used by |
| //! debian i386, probably due to excess precision issues. |
| //! |
| //! See https://github.com/rust-lang/compiler-builtins/pull/976 for discussion on why these |
| //! functions are implemented in this way. |
| |
| pub fn ceil(mut x: f64) -> f64 { |
| unsafe { |
| core::arch::asm!( |
| "fld qword ptr [{x}]", |
| // Save the FPU control word, using `x` as scratch space. |
| "fstcw [{x}]", |
| // Set rounding control to 0b10 (+∞). |
| "mov word ptr [{x} + 2], 0x0b7f", |
| "fldcw [{x} + 2]", |
| // Round. |
| "frndint", |
| // Restore FPU control word. |
| "fldcw [{x}]", |
| // Save rounded value to memory. |
| "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 |
| } |
| |
| pub fn floor(mut x: f64) -> f64 { |
| unsafe { |
| core::arch::asm!( |
| "fld qword ptr [{x}]", |
| // Save the FPU control word, using `x` as scratch space. |
| "fstcw [{x}]", |
| // Set rounding control to 0b01 (-∞). |
| "mov word ptr [{x} + 2], 0x077f", |
| "fldcw [{x} + 2]", |
| // Round. |
| "frndint", |
| // Restore FPU control word. |
| "fldcw [{x}]", |
| // Save rounded value to memory. |
| "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 |
| } |