summaryrefslogtreecommitdiff
path: root/sysdeps/libm-i387
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/libm-i387')
-rw-r--r--sysdeps/libm-i387/e_acos.S14
-rw-r--r--sysdeps/libm-i387/e_acosf.S2
-rw-r--r--sysdeps/libm-i387/e_acosl.S2
-rw-r--r--sysdeps/libm-i387/e_asin.S2
-rw-r--r--sysdeps/libm-i387/e_asinf.S2
-rw-r--r--sysdeps/libm-i387/e_asinl.S2
-rw-r--r--sysdeps/libm-i387/e_exp.S3
-rw-r--r--sysdeps/libm-i387/e_expf.S3
-rw-r--r--sysdeps/libm-i387/e_expl.S3
-rw-r--r--sysdeps/libm-i387/e_log.S4
-rw-r--r--sysdeps/libm-i387/e_log10.S4
-rw-r--r--sysdeps/libm-i387/e_log10f.S4
-rw-r--r--sysdeps/libm-i387/e_log10l.S4
-rw-r--r--sysdeps/libm-i387/e_logf.S4
-rw-r--r--sysdeps/libm-i387/e_logl.S4
-rw-r--r--sysdeps/libm-i387/e_pow.S219
-rw-r--r--sysdeps/libm-i387/e_powf.S230
-rw-r--r--sysdeps/libm-i387/e_powl.S206
-rw-r--r--sysdeps/libm-i387/s_expm1.S9
-rw-r--r--sysdeps/libm-i387/s_expm1f.S9
-rw-r--r--sysdeps/libm-i387/s_expm1l.S9
-rw-r--r--sysdeps/libm-i387/s_isinfl.c12
-rw-r--r--sysdeps/libm-i387/s_logbl.S1
-rw-r--r--sysdeps/libm-i387/s_scalbn.S1
-rw-r--r--sysdeps/libm-i387/s_scalbnf.S1
-rw-r--r--sysdeps/libm-i387/s_scalbnl.S1
26 files changed, 673 insertions, 82 deletions
diff --git a/sysdeps/libm-i387/e_acos.S b/sysdeps/libm-i387/e_acos.S
index becae36d5e..b9d07b1091 100644
--- a/sysdeps/libm-i387/e_acos.S
+++ b/sysdeps/libm-i387/e_acos.S
@@ -10,12 +10,12 @@ RCSID("$NetBSD: e_acos.S,v 1.4 1995/05/08 23:44:37 jtc Exp $")
/* acos = atan (sqrt(1 - x^2) / x) */
ENTRY(__ieee754_acos)
fldl 4(%esp) /* x */
- fst %st(1)
- fmul %st(0) /* x^2 */
- fld1
- fsubp /* 1 - x^2 */
- fsqrt /* sqrt (1 - x^2) */
- fxch %st(1)
- fpatan
+ fld %st /* x : x */
+ fmul %st(0) /* x^2 : x */
+ fld1 /* 1 : x^2 : x */
+ fsubp /* 1 - x^2 : x */
+ fsqrt /* sqrt (1 - x^2) : x */
+ fxch %st(1) /* x : sqrt (1 - x^2) */
+ fpatan /* atan (sqrt(1 - x^2) / x) */
ret
END (__ieee754_acos)
diff --git a/sysdeps/libm-i387/e_acosf.S b/sysdeps/libm-i387/e_acosf.S
index 87ee2fb5bc..50b13fd1bd 100644
--- a/sysdeps/libm-i387/e_acosf.S
+++ b/sysdeps/libm-i387/e_acosf.S
@@ -11,7 +11,7 @@ RCSID("$NetBSD: $")
/* acos = atan (sqrt(1 - x^2) / x) */
ENTRY(__ieee754_acosf)
flds 4(%esp) /* x */
- fst %st(1)
+ fld %st
fmul %st(0) /* x^2 */
fld1
fsubp /* 1 - x^2 */
diff --git a/sysdeps/libm-i387/e_acosl.S b/sysdeps/libm-i387/e_acosl.S
index e8f97485de..d69f056556 100644
--- a/sysdeps/libm-i387/e_acosl.S
+++ b/sysdeps/libm-i387/e_acosl.S
@@ -11,7 +11,7 @@
/* acosl = atanl (sqrtl(1 - x^2) / x) */
ENTRY(__ieee754_acosl)
fldt 4(%esp) /* x */
- fst %st(1)
+ fld %st
fmul %st(0) /* x^2 */
fld1
fsubp /* 1 - x^2 */
diff --git a/sysdeps/libm-i387/e_asin.S b/sysdeps/libm-i387/e_asin.S
index 1202753d9b..945e308245 100644
--- a/sysdeps/libm-i387/e_asin.S
+++ b/sysdeps/libm-i387/e_asin.S
@@ -10,7 +10,7 @@ RCSID("$NetBSD: e_asin.S,v 1.4 1995/05/08 23:45:40 jtc Exp $")
/* asin = atan (x / sqrt(1 - x^2)) */
ENTRY(__ieee754_asin)
fldl 4(%esp) /* x */
- fst %st(1)
+ fld %st
fmul %st(0) /* x^2 */
fld1
fsubp /* 1 - x^2 */
diff --git a/sysdeps/libm-i387/e_asinf.S b/sysdeps/libm-i387/e_asinf.S
index d2159bac37..d450e9a740 100644
--- a/sysdeps/libm-i387/e_asinf.S
+++ b/sysdeps/libm-i387/e_asinf.S
@@ -11,7 +11,7 @@ RCSID("$NetBSD: $")
/* asin = atan (x / sqrt(1 - x^2)) */
ENTRY(__ieee754_asinf)
flds 4(%esp) /* x */
- fst %st(1)
+ fld %st
fmul %st(0) /* x^2 */
fld1
fsubp /* 1 - x^2 */
diff --git a/sysdeps/libm-i387/e_asinl.S b/sysdeps/libm-i387/e_asinl.S
index ab421f3189..3919fbcf58 100644
--- a/sysdeps/libm-i387/e_asinl.S
+++ b/sysdeps/libm-i387/e_asinl.S
@@ -12,7 +12,7 @@ RCSID("$NetBSD: $")
/* asinl = atanl (x / sqrtl(1 - x^2)) */
ENTRY(__ieee754_asinl)
fldt 4(%esp) /* x */
- fst %st(1)
+ fld %st
fmul %st(0) /* x^2 */
fld1
fsubp /* 1 - x^2 */
diff --git a/sysdeps/libm-i387/e_exp.S b/sysdeps/libm-i387/e_exp.S
index e76b9c63df..4a75fa1d1c 100644
--- a/sysdeps/libm-i387/e_exp.S
+++ b/sysdeps/libm-i387/e_exp.S
@@ -22,7 +22,7 @@ ENTRY(__ieee754_exp)
je 1f /* Is +-Inf, jump. */
fldl2e
fmulp /* x * log2(e) */
- fstl %st(1)
+ fld %st
frndint /* int(x * log2(e)) */
fsubr %st,%st(1) /* fract(x * log2(e)) */
fxch
@@ -35,6 +35,7 @@ ENTRY(__ieee754_exp)
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
+ fstp %st
fldz /* Set result to 0. */
2: ret
END (__ieee754_exp)
diff --git a/sysdeps/libm-i387/e_expf.S b/sysdeps/libm-i387/e_expf.S
index 9a669cf8d4..5fd49b89fd 100644
--- a/sysdeps/libm-i387/e_expf.S
+++ b/sysdeps/libm-i387/e_expf.S
@@ -23,7 +23,7 @@ ENTRY(__ieee754_expf)
je 1f /* Is +-Inf, jump. */
fldl2e
fmulp /* x * log2(e) */
- fstl %st(1)
+ fld %st
frndint /* int(x * log2(e)) */
fsubr %st,%st(1) /* fract(x * log2(e)) */
fxch
@@ -36,6 +36,7 @@ ENTRY(__ieee754_expf)
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
+ fstp %st
fldz /* Set result to 0. */
2: ret
END (__ieee754_expf)
diff --git a/sysdeps/libm-i387/e_expl.S b/sysdeps/libm-i387/e_expl.S
index e83d30640d..2bcdf58c58 100644
--- a/sysdeps/libm-i387/e_expl.S
+++ b/sysdeps/libm-i387/e_expl.S
@@ -24,7 +24,7 @@ ENTRY(__ieee754_expl)
je 1f /* Is +-Inf, jump. */
fldl2e
fmulp /* x * log2(e) */
- fstl %st(1)
+ fld %st
frndint /* int(x * log2(e)) */
fsubr %st,%st(1) /* fract(x * log2(e)) */
fxch
@@ -37,6 +37,7 @@ ENTRY(__ieee754_expl)
1: testl $0x200, %eax /* Test sign. */
jz 2f /* If positive, jump. */
+ fstp %st
fldz /* Set result to 0. */
2: ret
END (__ieee754_expl)
diff --git a/sysdeps/libm-i387/e_log.S b/sysdeps/libm-i387/e_log.S
index e7f567d950..c7cacdfb0a 100644
--- a/sysdeps/libm-i387/e_log.S
+++ b/sysdeps/libm-i387/e_log.S
@@ -47,8 +47,8 @@ ENTRY(__ieee754_log)
fabs // |x-1| : x-1 : x : log(2)
fcompl MO(limit) // x-1 : x : log(2)
fnstsw // x-1 : x : log(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log(2)
fyl2xp1 // log(x)
ret
diff --git a/sysdeps/libm-i387/e_log10.S b/sysdeps/libm-i387/e_log10.S
index ecb691b905..2c8488c3a9 100644
--- a/sysdeps/libm-i387/e_log10.S
+++ b/sysdeps/libm-i387/e_log10.S
@@ -47,8 +47,8 @@ ENTRY(__ieee754_log10)
fabs // |x-1| : x-1 : x : log10(2)
fcompl MO(limit) // x-1 : x : log10(2)
fnstsw // x-1 : x : log10(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log10(2)
fyl2xp1 // log10(x)
ret
diff --git a/sysdeps/libm-i387/e_log10f.S b/sysdeps/libm-i387/e_log10f.S
index aac58d0293..2c07161085 100644
--- a/sysdeps/libm-i387/e_log10f.S
+++ b/sysdeps/libm-i387/e_log10f.S
@@ -48,8 +48,8 @@ ENTRY(__ieee754_log10f)
fabs // |x-1| : x-1 : x : log10(2)
fcompl MO(limit) // x-1 : x : log10(2)
fnstsw // x-1 : x : log10(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log10(2)
fyl2xp1 // log10(x)
ret
diff --git a/sysdeps/libm-i387/e_log10l.S b/sysdeps/libm-i387/e_log10l.S
index 4f51818bdd..6fe7c5a6f7 100644
--- a/sysdeps/libm-i387/e_log10l.S
+++ b/sysdeps/libm-i387/e_log10l.S
@@ -49,8 +49,8 @@ ENTRY(__ieee754_log10l)
fabs // |x-1| : x-1 : x : log10(2)
fcompl MO(limit) // x-1 : x : log10(2)
fnstsw // x-1 : x : log10(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log10(2)
fyl2xp1 // log10(x)
ret
diff --git a/sysdeps/libm-i387/e_logf.S b/sysdeps/libm-i387/e_logf.S
index 4459b7fc08..bdba1d3225 100644
--- a/sysdeps/libm-i387/e_logf.S
+++ b/sysdeps/libm-i387/e_logf.S
@@ -48,8 +48,8 @@ ENTRY(__ieee754_logf)
fabs // |x-1| : x-1 : x : log(2)
fcompl MO(limit) // x-1 : x : log(2)
fnstsw // x-1 : x : log(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log(2)
fyl2xp1 // log(x)
ret
diff --git a/sysdeps/libm-i387/e_logl.S b/sysdeps/libm-i387/e_logl.S
index 08447a27e7..bda3ea508e 100644
--- a/sysdeps/libm-i387/e_logl.S
+++ b/sysdeps/libm-i387/e_logl.S
@@ -48,8 +48,8 @@ ENTRY(__ieee754_logl)
fabs // |x-1| : x-1 : x : log(2)
fcompl MO(limit) // x-1 : x : log(2)
fnstsw // x-1 : x : log(2)
- sahf
- ja 2f
+ andb $0x45, %ah
+ jz 2f
fstp %st(1) // x-1 : log(2)
fyl2xp1 // log(x)
ret
diff --git a/sysdeps/libm-i387/e_pow.S b/sysdeps/libm-i387/e_pow.S
index f6c7562d9c..efe184168b 100644
--- a/sysdeps/libm-i387/e_pow.S
+++ b/sysdeps/libm-i387/e_pow.S
@@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -27,31 +27,77 @@
#endif
.align ALIGNARG(4)
+ ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+ ASM_SIZE_DIRECTIVE(infinity)
+ ASM_TYPE_DIRECTIVE(zero,@object)
+zero: .double 0.0
+ ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0x80
+ ASM_SIZE_DIRECTIVE(minf_mzero)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
ASM_TYPE_DIRECTIVE(limit,@object)
limit: .double 0.29
ASM_SIZE_DIRECTIVE(limit)
+ ASM_TYPE_DIRECTIVE(nan,@object)
+nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+ ASM_SIZE_DIRECTIVE(nan)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__ieee754_pow)
- fldl 4(%esp) // x
- fldl 12(%esp) // y : x
+ fldl 12(%esp) // y
+ fxam
+ fnstsw
+ movb %ah, %dl
+ andb $0x45, %ah
+ cmpb $0x40, %ah // is y == 0 ?
+ je 11f
+
+ cmpb $0x05, %ah // is y == ±inf ?
+ je 12f
+
+ cmpb $0x01, %ah // is y == NaN ?
+ je 30f
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
+
+ fldl 4(%esp) // x : y
+
subl $8,%esp
+ fxam
+ fnstsw
+ movb %ah, %dh
+ andb $0x45, %ah
+ cmpb $0x40, %ah
+ je 20f // x is ±0
+
+ cmpb $0x05, %ah
+ je 15f // x is ±inf
+
+ fxch // y : x
+
/* First see whether `y' is a natural number. In this case we
can use a more precise algorithm. */
fld %st // y : y : x
@@ -63,13 +109,11 @@ ENTRY(__ieee754_pow)
jne 2f
/* OK, we have an integer value for y. */
- ftst // y : x
- fstp %st(0) // x
- fnstsw
- sahf
popl %eax
popl %edx
- jnc 4f // y >= 0, jump
+ orl $0, %edx
+ fstp %st(0) // x
+ jns 4f // y >= 0, jump
fdivrl MO(one) // 1/x (now referred to as x)
negl %eax
adcl $0, %edx
@@ -87,7 +131,7 @@ ENTRY(__ieee754_pow)
orl %edx, %ecx
jnz 6b
fstp %st(0) // ST*x
- ret
+30: ret
.align ALIGNARG(4)
2: /* y is a real number. */
@@ -117,4 +161,161 @@ ENTRY(__ieee754_pow)
addl $8, %esp
fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
ret
+
+
+ // pow(x,±0) = 1
+ .align ALIGNARG(4)
+11: fstp %st(0) // pop y
+ fldl MO(one)
+ ret
+
+ // y == ±inf
+ .align ALIGNARG(4)
+12: fstp %st(0) // pop y
+ fldl 4(%esp) // x
+ fabs
+ fcompl MO(one) // < 1, == 1, or > 1
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x45, %ah
+ je 13f // jump if x is NaN
+
+ cmpb $0x40, %ah
+ je 14f // jump if |x| == 1
+
+ shlb $1, %ah
+ xorb %ah, %dl
+ andl $2, %edx
+ fldl MOX(inf_zero, %edx, 4)
+ ret
+
+ .align ALIGNARG(4)
+14: fldl MO(nan)
+ faddl MO(zero) // raise invalid exception
+ ret
+
+ .align ALIGNARG(4)
+13: fldl 4(%esp) // load x == NaN
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±inf
+15: fstp %st(0) // y
+ testb $2, %dh
+ jz 16f // jump if x == +inf
+
+ // We must find out whether y is an odd integer.
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %eax
+ popl %edx
+ 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)
+ ret
+
+ .align ALIGNARG(4)
+16: fcompl MO(zero)
+ addl $8, %esp
+ fnstsw
+ shrl $5, %eax
+ andl $8, %eax
+ fldl MOX(inf_zero, %eax, 1)
+ ret
+
+ .align ALIGNARG(4)
+17: shll $30, %edx // sign bit for y in right position
+ addl $8, %esp
+18: shrl $31, %edx
+ fldl MOX(inf_zero, %edx, 8)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0
+20: fstp %st(0) // y
+ testb $2, %dl
+ jz 21f // y > 0
+
+ // x is ±0 and y is < 0. We must find out whether y is an odd integer.
+ testb $2, %dh
+ jz 25f
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %eax
+ popl %edx
+ 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)
+ fdivl MO(zero)
+ fchs
+ ret
+
+25: fstp %st(0)
+26: popl %eax
+ popl %edx
+27: // Raise divide-by-zero exception and get infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0 and y is > 0. We must find out whether y is an odd integer.
+21: testb $2, %dh
+ jz 22f
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %eax
+ popl %edx
+ andb $1, %al
+ jz 24f // jump if not odd
+ cmpl $0xffe00000, %edx
+ jbe 24f // does not fit in mantissa bits
+ // It's an odd integer.
+ fldl MO(mzero)
+ ret
+
+22: fstp %st(0)
+23: popl %eax
+ popl %edx
+24: fldl MO(zero)
+ ret
+
END(__ieee754_pow)
diff --git a/sysdeps/libm-i387/e_powf.S b/sysdeps/libm-i387/e_powf.S
index 9d6bc510b6..54af93c961 100644
--- a/sysdeps/libm-i387/e_powf.S
+++ b/sysdeps/libm-i387/e_powf.S
@@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -27,67 +27,107 @@
#endif
.align ALIGNARG(4)
+ ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+ ASM_SIZE_DIRECTIVE(infinity)
+ ASM_TYPE_DIRECTIVE(zero,@object)
+zero: .double 0.0
+ ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0x80
+ ASM_SIZE_DIRECTIVE(minf_mzero)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
ASM_TYPE_DIRECTIVE(limit,@object)
limit: .double 0.29
ASM_SIZE_DIRECTIVE(limit)
+ ASM_TYPE_DIRECTIVE(nan,@object)
+nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+ ASM_SIZE_DIRECTIVE(nan)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__ieee754_powf)
- flds 4(%esp) // x
- flds 8(%esp) // y : x
+ flds 8(%esp) // y
+ fxam
+ fnstsw
+ movb %ah, %dl
+ andb $0x45, %ah
+ cmpb $0x40, %ah // is y == 0 ?
+ je 11f
+
+ cmpb $0x05, %ah // is y == ±inf ?
+ je 12f
+
+ cmpb $0x01, %ah // is y == NaN ?
+ je 30f
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
- subl $8,%esp
+
+ flds 4(%esp) // x : y
+
+ subl $4, %esp
+
+ fxam
+ fnstsw
+ movb %ah, %dh
+ andb $0x45, %ah
+ cmpb $0x40, %ah
+ je 20f // x is ±0
+
+ cmpb $0x05, %ah
+ je 15f // x is ±inf
+
+ fxch // y : x
/* First see whether `y' is a natural number. In this case we
can use a more precise algorithm. */
fld %st // y : y : x
- fistpll (%esp) // y : x
- fildll (%esp) // int(y) : y : x
+ fistpl (%esp) // y : x
+ fildl (%esp) // int(y) : y : x
fucomp %st(1) // y : x
fnstsw
sahf
jne 2f
/* OK, we have an integer value for y. */
- ftst // y : x
- fstp %st(0) // x
- fnstsw
- sahf
- popl %eax
popl %edx
- jnc 4f // y >= 0, jump
+ orl $0, %edx
+ fstp %st(0) // x
+ jns 4f // y >= 0, jump
fdivrl MO(one) // 1/x (now referred to as x)
- negl %eax
- adcl $0, %edx
negl %edx
4: fldl MO(one) // 1 : x
fxch
-6: shrdl $1, %edx, %eax
+6: shrl $1, %edx
jnc 5f
fxch
fmul %st(1) // x : ST*x
fxch
5: fmul %st(0), %st // x*x : ST*x
- movl %eax, %ecx
- orl %edx, %ecx
+ testl %edx, %edx
jnz 6b
fstp %st(0) // ST*x
- ret
+30: ret
.align ALIGNARG(4)
2: /* y is a real number. */
@@ -114,7 +154,159 @@ ENTRY(__ieee754_powf)
f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x))
faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x))
fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
- addl $8, %esp
+ addl $4, %esp
fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
ret
+
+
+ // pow(x,±0) = 1
+ .align ALIGNARG(4)
+11: fstp %st(0) // pop y
+ fldl MO(one)
+ ret
+
+ // y == ±inf
+ .align ALIGNARG(4)
+12: fstp %st(0) // pop y
+ flds 4(%esp) // x
+ fabs
+ fcompl MO(one) // < 1, == 1, or > 1
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x45, %ah
+ je 13f // jump if x is NaN
+
+ cmpb $0x40, %ah
+ je 14f // jump if |x| == 1
+
+ shlb $1, %ah
+ xorb %ah, %dl
+ andl $2, %edx
+ fldl MOX(inf_zero, %edx, 4)
+ ret
+
+ .align ALIGNARG(4)
+14: fldl MO(nan)
+ faddl MO(zero) // raise invalid exception
+ ret
+
+ .align ALIGNARG(4)
+13: flds 4(%esp) // load x == NaN
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±inf
+15: fstp %st(0) // y
+ testb $2, %dh
+ jz 16f // jump if x == +inf
+
+ // We must find out whether y is an odd integer.
+ fld %st // y : y
+ fistpl (%esp) // y
+ fildl (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %edx
+ testb $1, %dl
+ jz 18f // jump if not odd
+ movl %edx, %eax
+ orl %edx, %edx
+ jns 155f
+ negl %eax
+155: cmpl $0x01000000, %eax
+ ja 18f // does not fit in mantissa bits
+ // It's an odd integer.
+ shrl $31, %edx
+ fldl MOX(minf_mzero, %edx, 8)
+ ret
+
+ .align ALIGNARG(4)
+16: fcompl MO(zero)
+ addl $4, %esp
+ fnstsw
+ shrl $5, %eax
+ andl $8, %eax
+ fldl MOX(inf_zero, %eax, 1)
+ ret
+
+ .align ALIGNARG(4)
+17: shll $30, %edx // sign bit for y in right position
+ addl $4, %esp
+18: shrl $31, %edx
+ fldl MOX(inf_zero, %edx, 8)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0
+20: fstp %st(0) // y
+ testb $2, %dl
+ jz 21f // y > 0
+
+ // x is ±0 and y is < 0. We must find out whether y is an odd integer.
+ testb $2, %dh
+ jz 25f
+
+ fld %st // y : y
+ fistpl (%esp) // y
+ fildl (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %edx
+ testb $1, %dl
+ jz 27f // jump if not odd
+ cmpl $0xff000000, %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)
+ fdivl MO(zero)
+ fchs
+ ret
+
+25: fstp %st(0)
+26: popl %eax
+27: // Raise divide-by-zero exception and get infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0 and y is > 0. We must find out whether y is an odd integer.
+21: testb $2, %dh
+ jz 22f
+
+ fld %st // y : y
+ fistpl (%esp) // y
+ fildl (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ 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?
+ popl %edx
+ testb $1, %dl
+ jz 24f // jump if not odd
+ cmpl $0xff000000, %edx
+ jbe 24f // does not fit in mantissa bits
+ // It's an odd integer.
+ fldl MO(mzero)
+ ret
+
+22: fstp %st(0)
+23: popl %eax
+24: fldl MO(zero)
+ ret
+
END(__ieee754_powf)
diff --git a/sysdeps/libm-i387/e_powl.S b/sysdeps/libm-i387/e_powl.S
index ea445804f0..3cfb96b213 100644
--- a/sysdeps/libm-i387/e_powl.S
+++ b/sysdeps/libm-i387/e_powl.S
@@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -27,31 +27,77 @@
#endif
.align ALIGNARG(4)
+ ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+ ASM_SIZE_DIRECTIVE(infinity)
+ ASM_TYPE_DIRECTIVE(zero,@object)
+zero: .double 0.0
+ ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0x80
+ ASM_SIZE_DIRECTIVE(minf_mzero)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
ASM_TYPE_DIRECTIVE(limit,@object)
limit: .double 0.29
ASM_SIZE_DIRECTIVE(limit)
+ ASM_TYPE_DIRECTIVE(nan,@object)
+nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
+ ASM_SIZE_DIRECTIVE(nan)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__ieee754_powl)
- fldt 4(%esp) // x
- fldt 16(%esp) // y : x
+ fldt 16(%esp) // y
+ fxam
+ fnstsw
+ movb %ah, %dl
+ andb $0x45, %ah
+ cmpb $0x40, %ah // is y == 0 ?
+ je 11f
+
+ cmpb $0x05, %ah // is y == ±inf ?
+ je 12f
+
+ cmpb $0x01, %ah // is y == NaN ?
+ je 30f
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
+
+ fldt 4(%esp) // x : y
+
subl $8,%esp
+ fxam
+ fnstsw
+ movb %ah, %dh
+ andb $0x45, %ah
+ cmpb $0x40, %ah
+ je 20f // x is ±0
+
+ cmpb $0x05, %ah
+ je 15f // x is ±inf
+
+ fxch // y : x
+
/* First see whether `y' is a natural number. In this case we
can use a more precise algorithm. */
fld %st // y : y : x
@@ -63,13 +109,11 @@ ENTRY(__ieee754_powl)
jne 2f
/* OK, we have an integer value for y. */
- ftst // y : x
- fstp %st(0) // x
- fnstsw
- sahf
popl %eax
popl %edx
- jnc 4f // y >= 0, jump
+ orl $0, %edx
+ fstp %st(0) // x
+ jns 4f // y >= 0, jump
fdivrl MO(one) // 1/x (now referred to as x)
negl %eax
adcl $0, %edx
@@ -87,7 +131,7 @@ ENTRY(__ieee754_powl)
orl %edx, %ecx
jnz 6b
fstp %st(0) // ST*x
- ret
+30: ret
.align ALIGNARG(4)
2: /* y is a real number. */
@@ -117,4 +161,148 @@ ENTRY(__ieee754_powl)
addl $8, %esp
fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
ret
+
+
+ // pow(x,±0) = 1
+ .align ALIGNARG(4)
+11: fstp %st(0) // pop y
+ fldl MO(one)
+ ret
+
+ // y == ±inf
+ .align ALIGNARG(4)
+12: fstp %st(0) // pop y
+ fldt 4(%esp) // x
+ fabs
+ fcompl MO(one) // < 1, == 1, or > 1
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x45, %ah
+ je 13f // jump if x is NaN
+
+ cmpb $0x40, %ah
+ je 14f // jump if |x| == 1
+
+ shlb $1, %ah
+ xorb %ah, %dl
+ andl $2, %edx
+ fldl MOX(inf_zero, %edx, 4)
+ ret
+
+ .align ALIGNARG(4)
+14: fldl MO(nan)
+ faddl MO(zero) // raise invalid exception
+ ret
+
+ .align ALIGNARG(4)
+13: fldt 4(%esp) // load x == NaN
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±inf
+15: fstp %st(0) // y
+ testb $2, %dh
+ jz 16f // jump if x == +inf
+
+ // We must find out whether y is an odd integer.
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne 17f
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ popl %edx
+ andb $1, %al
+ jz 18f // jump if not odd
+ // It's an odd integer.
+ shrl $31, %edx
+ fldl MOX(minf_mzero, %edx, 8)
+ ret
+
+ .align ALIGNARG(4)
+16: fcompl MO(zero)
+ addl $8, %esp
+ fnstsw
+ shrl $5, %eax
+ andl $8, %eax
+ fldl MOX(inf_zero, %eax, 1)
+ ret
+
+ .align ALIGNARG(4)
+17: shll $30, %edx // sign bit for y in right position
+ addl $8, %esp
+18: shrl $31, %edx
+ fldl MOX(inf_zero, %edx, 8)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0
+20: fstp %st(0) // y
+ testb $2, %dl
+ jz 21f // y > 0
+
+ // x is ±0 and y is < 0. We must find out whether y is an odd integer.
+ testb $2, %dh
+ jz 25f
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne 26f
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ popl %edx
+ andb $1, %al
+ jz 27f // jump if not odd
+ // It's an odd integer.
+ // Raise divide-by-zero exception and get minus infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ fchs
+ ret
+
+25: fstp %st(0)
+26: popl %eax
+ popl %edx
+27: // Raise divide-by-zero exception and get infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0 and y is > 0. We must find out whether y is an odd integer.
+21: testb $2, %dh
+ jz 22f
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne 23f
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ popl %edx
+ andb $1, %al
+ jz 24f // jump if not odd
+ // It's an odd integer.
+ fldl MO(mzero)
+ ret
+
+22: fstp %st(0)
+23: popl %eax
+ popl %edx
+24: fldl MO(zero)
+ ret
+
END(__ieee754_powl)
diff --git a/sysdeps/libm-i387/s_expm1.S b/sysdeps/libm-i387/s_expm1.S
index 78e8013b7e..e1b198d604 100644
--- a/sysdeps/libm-i387/s_expm1.S
+++ b/sysdeps/libm-i387/s_expm1.S
@@ -30,9 +30,9 @@
.text
#endif
.align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(zero,@object)
-zero: .double 0.0
- ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minus1,@object)
+minus1: .double -1.0
+ ASM_SIZE_DIRECTIVE(minus1)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
@@ -79,7 +79,8 @@ ENTRY(__expm1)
2: testl $0x200, %eax // Test sign.
jz 3f // If positive, jump.
- fldl MO(zero) // Set result to 0.
+ fstp %st
+ fldl MO(minus1) // Set result to -1.0.
3: ret
END(__expm1)
weak_alias (__expm1, expm1)
diff --git a/sysdeps/libm-i387/s_expm1f.S b/sysdeps/libm-i387/s_expm1f.S
index 00f1562e73..8626fee45d 100644
--- a/sysdeps/libm-i387/s_expm1f.S
+++ b/sysdeps/libm-i387/s_expm1f.S
@@ -30,9 +30,9 @@
.text
#endif
.align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(zero,@object)
-zero: .double 0.0
- ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minus1,@object)
+minus1: .double -1.0
+ ASM_SIZE_DIRECTIVE(minus1)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
@@ -79,7 +79,8 @@ ENTRY(__expm1f)
2: testl $0x200, %eax // Test sign.
jz 3f // If positive, jump.
- fldl MO(zero) // Set result to 0.
+ fstp %st
+ fldl MO(minus1) // Set result to -1.0.
3: ret
END(__expm1f)
weak_alias (__expm1f, expm1f)
diff --git a/sysdeps/libm-i387/s_expm1l.S b/sysdeps/libm-i387/s_expm1l.S
index b7e6b36d39..46290ca4a9 100644
--- a/sysdeps/libm-i387/s_expm1l.S
+++ b/sysdeps/libm-i387/s_expm1l.S
@@ -30,9 +30,9 @@
.text
#endif
.align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(zero,@object)
-zero: .double 0.0
- ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minus1,@object)
+minus1: .double -1.0
+ ASM_SIZE_DIRECTIVE(minus1)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
@@ -79,7 +79,8 @@ ENTRY(__expm1l)
2: testl $0x200, %eax // Test sign.
jz 3f // If positive, jump.
- fldl MO(zero) // Set result to 0.
+ fstp %st
+ fldl MO(minus1) // Set result to -1.0.
3: ret
END(__expm1l)
weak_alias (__expm1l, expm1l)
diff --git a/sysdeps/libm-i387/s_isinfl.c b/sysdeps/libm-i387/s_isinfl.c
index 3ee53d5ecc..f07898fd1b 100644
--- a/sysdeps/libm-i387/s_isinfl.c
+++ b/sysdeps/libm-i387/s_isinfl.c
@@ -10,7 +10,7 @@ static char rcsid[] = "$NetBSD: $";
#endif
/*
- * isinfl(x) returns 1 is x is inf, else 0;
+ * isinfl(x) returns 1 if x is inf, -1 if x is -inf, else 0;
* no branching!
*/
@@ -26,11 +26,11 @@ static char rcsid[] = "$NetBSD: $";
{
int32_t se,hx,lx;
GET_LDOUBLE_WORDS(se,hx,lx,x);
- se &= 0x7fff;
- se ^= 0x7fff;
/* This additional ^ 0x80000000 is necessary because in Intel's
- internal representation the implicit one is explicit. */
- se |= (hx ^ 0x80000000) | lx;
- return (se == 0);
+ internal representation of the implicit one is explicit. */
+ lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff);
+ lx |= -lx;
+ se &= 0x8000;
+ return ~(lx >> 31) & (1 - (se >> 14));
}
weak_alias (__isinfl, isinfl)
diff --git a/sysdeps/libm-i387/s_logbl.S b/sysdeps/libm-i387/s_logbl.S
index 6ce274c57c..5c9a9c1c9d 100644
--- a/sysdeps/libm-i387/s_logbl.S
+++ b/sysdeps/libm-i387/s_logbl.S
@@ -11,6 +11,7 @@ RCSID("$NetBSD: $")
ENTRY(__logbl)
fldt 4(%esp)
fxtract
+ fstp %st
ret
END (__logbl)
weak_alias (__logbl, logbl)
diff --git a/sysdeps/libm-i387/s_scalbn.S b/sysdeps/libm-i387/s_scalbn.S
index 3ec56d4523..709b7a47f5 100644
--- a/sysdeps/libm-i387/s_scalbn.S
+++ b/sysdeps/libm-i387/s_scalbn.S
@@ -11,6 +11,7 @@ ENTRY(__scalbn)
fildl 12(%esp)
fldl 4(%esp)
fscale
+ fstp %st(1)
ret
END (__scalbn)
weak_alias (__scalbn, scalbn)
diff --git a/sysdeps/libm-i387/s_scalbnf.S b/sysdeps/libm-i387/s_scalbnf.S
index b1a1c46b6c..ce92113844 100644
--- a/sysdeps/libm-i387/s_scalbnf.S
+++ b/sysdeps/libm-i387/s_scalbnf.S
@@ -11,6 +11,7 @@ ENTRY(__scalbnf)
fildl 8(%esp)
flds 4(%esp)
fscale
+ fstp %st(1)
ret
END (__scalbnf)
weak_alias (__scalbnf, scalbnf)
diff --git a/sysdeps/libm-i387/s_scalbnl.S b/sysdeps/libm-i387/s_scalbnl.S
index 0f3323803c..09e06457b8 100644
--- a/sysdeps/libm-i387/s_scalbnl.S
+++ b/sysdeps/libm-i387/s_scalbnl.S
@@ -12,6 +12,7 @@ ENTRY(__scalbnl)
fildl 16(%esp)
fldt 4(%esp)
fscale
+ fstp %st(1)
ret
END (__scalbnl)
weak_alias (__scalbnl, scalbnl)