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