diff options
Diffstat (limited to 'sysdeps/libm-i387')
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) |