aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/i386/fpu/e_pow.S
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-21 12:14:57 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-21 12:16:00 +0000
commit2460d3aa21f04cdf28497683bd3e29183189f779 (patch)
treed01d4f4002b56099e0f8959e39aa5eee7dc1db10 /sysdeps/i386/fpu/e_pow.S
parenteb96ffb07d0b1b23ecfaf9520d6757c7dbea0bd1 (diff)
downloadglibc-2460d3aa21f04cdf28497683bd3e29183189f779.tar
glibc-2460d3aa21f04cdf28497683bd3e29183189f779.tar.gz
glibc-2460d3aa21f04cdf28497683bd3e29183189f779.tar.bz2
glibc-2460d3aa21f04cdf28497683bd3e29183189f779.zip
Fix pow of zero and infinity to large powers.
Diffstat (limited to 'sysdeps/i386/fpu/e_pow.S')
-rw-r--r--sysdeps/i386/fpu/e_pow.S47
1 files changed, 31 insertions, 16 deletions
diff --git a/sysdeps/i386/fpu/e_pow.S b/sysdeps/i386/fpu/e_pow.S
index 63c44f1357..1abedf6284 100644
--- a/sysdeps/i386/fpu/e_pow.S
+++ b/sysdeps/i386/fpu/e_pow.S
@@ -230,6 +230,16 @@ ENTRY(__ieee754_pow)
testb $2, %dh
jz 16f // jump if x == +inf
+ // fistpll raises invalid exception for |y| >= 1L<<63, so test
+ // that (in which case y is certainly even) before testing
+ // whether y is odd.
+ fld %st // y : y
+ fabs // |y| : y
+ fcompl MO(p63) // y
+ fnstsw
+ sahf
+ jnc 16f
+
// We must find out whether y is an odd integer.
fld %st // y : y
fistpll (%esp) // y
@@ -239,20 +249,13 @@ ENTRY(__ieee754_pow)
sahf
jne 17f
- // OK, the value is an integer, but is the number of bits small
- // enough so that all are coming from the mantissa?
+ // OK, the value is an integer.
popl %eax
cfi_adjust_cfa_offset (-4)
popl %edx
cfi_adjust_cfa_offset (-4)
andb $1, %al
jz 18f // jump if not odd
- movl %edx, %eax
- orl %edx, %edx
- jns 155f
- negl %eax
-155: cmpl $0x00200000, %eax
- ja 18f // does not fit in mantissa bits
// It's an odd integer.
shrl $31, %edx
fldl MOX(minf_mzero, %edx, 8)
@@ -289,6 +292,16 @@ ENTRY(__ieee754_pow)
testb $2, %dh
jz 25f
+ // fistpll raises invalid exception for |y| >= 1L<<63, so test
+ // that (in which case y is certainly even) before testing
+ // whether y is odd.
+ fld %st // y : y
+ fabs // |y| : y
+ fcompl MO(p63) // y
+ fnstsw
+ sahf
+ jnc 25f
+
fld %st // y : y
fistpll (%esp) // y
fildll (%esp) // int(y) : y
@@ -297,16 +310,13 @@ ENTRY(__ieee754_pow)
sahf
jne 26f
- // OK, the value is an integer, but is the number of bits small
- // enough so that all are coming from the mantissa?
+ // OK, the value is an integer.
popl %eax
cfi_adjust_cfa_offset (-4)
popl %edx
cfi_adjust_cfa_offset (-4)
andb $1, %al
jz 27f // jump if not odd
- cmpl $0xffe00000, %edx
- jbe 27f // does not fit in mantissa bits
// It's an odd integer.
// Raise divide-by-zero exception and get minus infinity value.
fldl MO(one)
@@ -329,6 +339,14 @@ ENTRY(__ieee754_pow)
21: testb $2, %dh
jz 22f
+ // fistpll raises invalid exception for |y| >= 1L<<63, so test
+ // that (in which case y is certainly even) before testing
+ // whether y is odd.
+ fcoml MO(p63) // y
+ fnstsw
+ sahf
+ jnc 22f
+
fld %st // y : y
fistpll (%esp) // y
fildll (%esp) // int(y) : y
@@ -337,16 +355,13 @@ ENTRY(__ieee754_pow)
sahf
jne 23f
- // OK, the value is an integer, but is the number of bits small
- // enough so that all are coming from the mantissa?
+ // OK, the value is an integer.
popl %eax
cfi_adjust_cfa_offset (-4)
popl %edx
cfi_adjust_cfa_offset (-4)
andb $1, %al
jz 24f // jump if not odd
- cmpl $0xffe00000, %edx
- jae 24f // does not fit in mantissa bits
// It's an odd integer.
fldl MO(mzero)
ret