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