6
6
///
7
7
/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_ceil.S
8
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
- )
9
+ pub fn ceil ( mut x : f64 ) -> f64 {
10
+ // We save and later restore the FPU control word.
11
+ let mut cw_orig : u16 = 0 ;
12
+ unsafe {
13
+ core :: arch :: asm! (
14
+ "fstcw ({cw_ptr})" , // Save the cw
15
+ "movw ({cw_ptr}), %dx" , // .. .
16
+ "orw $0x0800, %dx" , // Set rounding control to 0b10 (+∞) ,
17
+ "andw $0xfbff, %dx", // preserving other controls
18
+ "movw %dx, ({cw_ptr})" , // Apply cw
19
+ "fldcw ({cw_ptr})" , // ...
20
+ "fldl ({x_ptr})" , // Push x to the stack
21
+ "frndint" , // Round
22
+ "fldcw ({cw_ptr})" , // Restore cw
23
+ "fstpl ({x_ptr} )", // Save rounded x to mem
24
+ cw_ptr = in ( reg ) & mut cw_orig ,
25
+ x_ptr = in ( reg ) & mut x ,
26
+ out ( "dx" ) _ , // Cw scratch
27
+ // All the x87 FPU stack is used, all registers must be clobbered
28
+ out ( "st(0)" ) _ , out ( "st(1)" ) _ , out ( "st(2)" ) _ , out ( "st(3)" ) _ ,
29
+ out ( "st(4)" ) _ , out ( "st(5)" ) _ , out ( "st(6)" ) _ , out ( "st(7)" ) _ ,
30
+ options ( att_syntax )
31
+ )
32
+ }
33
+ x
34
34
}
35
35
36
36
/// Use an alternative implementation on x86, because the
@@ -39,29 +39,29 @@ pub extern "C" fn ceil(_: f64) -> f64 {
39
39
///
40
40
/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_floor.S
41
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
- )
42
+ pub fn floor ( mut x : f64 ) -> f64 {
43
+ // We save and later restore the FPU control word.
44
+ let mut cw_orig : u16 = 0 ;
45
+ unsafe {
46
+ core :: arch :: asm! (
47
+ "fstcw ({cw_ptr})" , // Save the cw
48
+ "movw ({cw_ptr}), %dx" , // .. .
49
+ "orw $0x0400, %dx" , // Set rounding control to 0b01 (-∞) ,
50
+ "andw $0xf7ff, %dx", // preserving other controls
51
+ "movw %dx, ({cw_ptr})" , // Apply cw
52
+ "fldcw ({cw_ptr})" , // ...
53
+ "fldl ({x_ptr})" , // Push x to the stack
54
+ "frndint" , // Round
55
+ "fldcw ({cw_ptr})" , // Restore cw
56
+ "fstpl ({x_ptr} )", // Save rounded x to mem
57
+ cw_ptr = in ( reg ) & mut cw_orig ,
58
+ x_ptr = in ( reg ) & mut x ,
59
+ out ( "dx" ) _ , // Cw scratch
60
+ // All the x87 FPU stack is used, all registers must be clobbered
61
+ out ( "st(0)" ) _ , out ( "st(1)" ) _ , out ( "st(2)" ) _ , out ( "st(3)" ) _ ,
62
+ out ( "st(4)" ) _ , out ( "st(5)" ) _ , out ( "st(6)" ) _ , out ( "st(7)" ) _ ,
63
+ options ( att_syntax )
64
+ )
65
+ }
66
+ x
67
67
}
0 commit comments