| 
1 | 1 | //! Architecture-specific support for x86-32 without SSE2  | 
2 | 2 | 
  | 
3 |  | -use super::super::fabs;  | 
4 |  | - | 
5 | 3 | /// Use an alternative implementation on x86, because the  | 
6 | 4 | /// main implementation fails with the x87 FPU used by  | 
7 | 5 | /// debian i386, probably due to excess precision issues.  | 
8 |  | -/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.  | 
9 |  | -pub fn ceil(x: f64) -> f64 {  | 
10 |  | -    if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {  | 
11 |  | -        let truncated = x as i64 as f64;  | 
12 |  | -        if truncated < x {  | 
13 |  | -            return truncated + 1.0;  | 
14 |  | -        } else {  | 
15 |  | -            return truncated;  | 
16 |  | -        }  | 
17 |  | -    } else {  | 
18 |  | -        return x;  | 
19 |  | -    }  | 
 | 6 | +///  | 
 | 7 | +/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_ceil.S  | 
 | 8 | +/// (written by J.T. Conklin <[email protected]>).  | 
 | 9 | +#[unsafe(naked)]  | 
 | 10 | +pub extern "C" fn ceil(_: f64) -> f64 {  | 
 | 11 | +    core::arch::naked_asm!(  | 
 | 12 | +        "pushl  %ebp",  | 
 | 13 | +        "movl   %esp,%ebp",  | 
 | 14 | +        "subl   $8,%esp",  | 
 | 15 | +        // Store fpu control word.  | 
 | 16 | +        "fstcw   -4(%ebp)",  | 
 | 17 | +        "movw    -4(%ebp),%dx",  | 
 | 18 | +        // Round towards +oo.  | 
 | 19 | +        "orw $0x0800,%dx",  | 
 | 20 | +        "andw    $0xfbff,%dx",  | 
 | 21 | +        "movw    %dx,-8(%ebp)",  | 
 | 22 | +        // Load modified control word  | 
 | 23 | +        "fldcw   -8(%ebp)",  | 
 | 24 | +        // Round.  | 
 | 25 | +        "fldl    8(%ebp)",  | 
 | 26 | +        "frndint",  | 
 | 27 | +        // Restore original control word.  | 
 | 28 | +        "fldcw   -4(%ebp)",  | 
 | 29 | +        // Restore esp and ebp and return  | 
 | 30 | +        "leave",  | 
 | 31 | +        "ret",  | 
 | 32 | +        options(att_syntax)  | 
 | 33 | +    )  | 
20 | 34 | }  | 
21 | 35 | 
 
  | 
22 | 36 | /// Use an alternative implementation on x86, because the  | 
23 | 37 | /// main implementation fails with the x87 FPU used by  | 
24 | 38 | /// debian i386, probably due to excess precision issues.  | 
25 |  | -/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.  | 
26 |  | -pub fn floor(x: f64) -> f64 {  | 
27 |  | -    if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {  | 
28 |  | -        let truncated = x as i64 as f64;  | 
29 |  | -        if truncated > x {  | 
30 |  | -            return truncated - 1.0;  | 
31 |  | -        } else {  | 
32 |  | -            return truncated;  | 
33 |  | -        }  | 
34 |  | -    } else {  | 
35 |  | -        return x;  | 
36 |  | -    }  | 
 | 39 | +///  | 
 | 40 | +/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_floor.S  | 
 | 41 | +/// (written by J.T. Conklin <[email protected]>).  | 
 | 42 | +#[unsafe(naked)]  | 
 | 43 | +pub extern "C" fn floor(_: f64) -> f64 {  | 
 | 44 | +    core::arch::naked_asm!(  | 
 | 45 | +        "pushl  %ebp",  | 
 | 46 | +        "movl   %esp,%ebp",  | 
 | 47 | +        "subl   $8,%esp",  | 
 | 48 | +        // Store fpu control word.  | 
 | 49 | +        "fstcw   -4(%ebp)",  | 
 | 50 | +        "movw    -4(%ebp),%dx",  | 
 | 51 | +        // Round towards -oo.  | 
 | 52 | +        "orw	$0x0400,%dx",  | 
 | 53 | +        "andw	$0xf7ff,%dx",  | 
 | 54 | +        "movw   %dx,-8(%ebp)",  | 
 | 55 | +        // Load modified control word  | 
 | 56 | +        "fldcw   -8(%ebp)",  | 
 | 57 | +        // Round.  | 
 | 58 | +        "fldl    8(%ebp)",  | 
 | 59 | +        "frndint",  | 
 | 60 | +        // Restore original control word.  | 
 | 61 | +        "fldcw   -4(%ebp)",  | 
 | 62 | +        // Restore esp and ebp and return  | 
 | 63 | +        "leave",  | 
 | 64 | +        "ret",  | 
 | 65 | +        options(att_syntax)  | 
 | 66 | +    )  | 
37 | 67 | }  | 
0 commit comments