aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/i386/fpu/e_powl.S
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-11-07 13:03:31 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-11-07 13:03:31 +0000
commit60e235ee2ae834bb9f7a884f1b192304b9fdcf33 (patch)
tree4053809680e9b6def9eab8272fc70ac6c6edb16c /sysdeps/i386/fpu/e_powl.S
parent0ab234b7db4991121eb572bf5c4971bfeb2d49a2 (diff)
downloadglibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.tar
glibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.tar.gz
glibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.tar.bz2
glibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.zip
Fix spurious underflows from pow with results close to 1 (bug 14811).
Diffstat (limited to 'sysdeps/i386/fpu/e_powl.S')
-rw-r--r--sysdeps/i386/fpu/e_powl.S23
1 files changed, 21 insertions, 2 deletions
diff --git a/sysdeps/i386/fpu/e_powl.S b/sysdeps/i386/fpu/e_powl.S
index 933418cf82..ac4842cf63 100644
--- a/sysdeps/i386/fpu/e_powl.S
+++ b/sysdeps/i386/fpu/e_powl.S
@@ -38,6 +38,9 @@ p64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43
.type p78,@object
p78: .byte 0, 0, 0, 0, 0, 0, 0xd0, 0x44
ASM_SIZE_DIRECTIVE(p78)
+ .type pm79,@object
+pm79: .byte 0, 0, 0, 0, 0, 0, 0, 0x3b
+ ASM_SIZE_DIRECTIVE(pm79)
.section .rodata.cst16,"aM",@progbits,16
@@ -120,9 +123,25 @@ ENTRY(__ieee754_powl)
fucomp %st(1) // y : x
fnstsw
sahf
- jne 3f
+ je 9f
- /* OK, we have an integer value for y. */
+ // If y has absolute value at most 0x1p-79, then any finite
+ // nonzero x will result in 1. Saturate y to those bounds to
+ // avoid underflow in the calculation of y*log2(x).
+ fld %st // y : y : x
+ fabs // |y| : y : x
+ fcompl MO(pm79) // y : x
+ fnstsw
+ sahf
+ jnc 3f
+ fstp %st(0) // pop y
+ fldl MO(pm79) // 0x1p-79 : x
+ testb $2, %dl
+ jnz 3f // y > 0
+ fchs // -0x1p-79 : x
+ jmp 3f
+
+9: /* OK, we have an integer value for y. */
popl %eax
cfi_adjust_cfa_offset (-4)
popl %edx