66///
77/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_ceil.S
88/// (written by J.T. Conklin <jtc@NetBSD.org>).
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
3434}
3535
3636/// Use an alternative implementation on x86, because the
@@ -39,29 +39,29 @@ pub extern "C" fn ceil(_: f64) -> f64 {
3939///
4040/// Based on https://github.com/NetBSD/src/blob/trunk/lib/libm/arch/i387/s_floor.S
4141/// (written by J.T. Conklin <jtc@NetBSD.org>).
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
6767}
0 commit comments