Correctly round double precision sqrt (#256)

As discussed in https://github.com/JuliaLang/julia/pull/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).
This commit is contained in:
Keno Fischer 2022-01-19 18:43:52 -05:00 committed by GitHub
parent 81d5e1603a
commit ae2d916985
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,12 +8,29 @@
//__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrt.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
ENTRY(sqrt)
fldl 4(%esp)
pushl %ebp
movl %esp,%ebp
subl $8,%esp
fstcw -4(%ebp) /* store fpu control word */
movw -4(%ebp),%dx
andw $0xfeff,%dx /* Set precision field to 64 bits (53 bit mantissa).
We assume it's set to 0b11 (extended precision),
so zeroing out the low bit of the precision field,
will correctly set the precision */
movw %dx,-8(%ebp)
fldcw -8(%ebp) /* load modfied control word */
fldl 8(%ebp)
fsqrt
fldcw -4(%ebp) /* restore original control word */
leave
ret
END(sqrt)
/* Enable stack protection */
#if defined(__ELF__)
.section .note.GNU-stack,"",%progbits