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