Skip to content

Commit ae2d916

Browse files
authored
Correctly round double precision sqrt (#256)
As discussed in JuliaLang/julia#43786, openlibm's sqrt function is incorrectly rounded for i387. IEEE requires correct rounding for these functions and LLVM relies on it. Fix that by setting the precision in the FPU control word (see e.g. e_ceil.S for similar FPU modifications).
1 parent 81d5e16 commit ae2d916

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

i387/e_sqrt.S

+19-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,29 @@
88
//__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrt.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
99

1010
ENTRY(sqrt)
11-
fldl 4(%esp)
11+
pushl %ebp
12+
movl %esp,%ebp
13+
subl $8,%esp
14+
15+
fstcw -4(%ebp) /* store fpu control word */
16+
movw -4(%ebp),%dx
17+
andw $0xfeff,%dx /* Set precision field to 64 bits (53 bit mantissa).
18+
We assume it's set to 0b11 (extended precision),
19+
so zeroing out the low bit of the precision field,
20+
will correctly set the precision */
21+
movw %dx,-8(%ebp)
22+
fldcw -8(%ebp) /* load modfied control word */
23+
24+
fldl 8(%ebp)
1225
fsqrt
26+
27+
fldcw -4(%ebp) /* restore original control word */
28+
29+
leave
1330
ret
1431
END(sqrt)
1532

16-
33+
1734
/* Enable stack protection */
1835
#if defined(__ELF__)
1936
.section .note.GNU-stack,"",%progbits

0 commit comments

Comments
 (0)