Skip to content

Commit 1766d1e

Browse files
committed
implement floor and ceil with inline assembly on i586
1 parent ffe715a commit 1766d1e

File tree

1 file changed

+50
-50
lines changed

1 file changed

+50
-50
lines changed

libm/src/math/arch/i586.rs

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,31 @@
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_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 <[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
6767
}

0 commit comments

Comments
 (0)