Rev 27910 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/* ix87 specific implementation of pow function.Copyright (C) 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.This file is part of the GNU C Library.Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with the GNU C Library; if not, write to the FreeSoftware Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA. */.file "e_pow.S".text.align 4inf_zero:infinity:.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7fzero: .double 0.0minf_mzero:minfinity:.byte 0, 0, 0, 0, 0, 0, 0xf0, 0xffmzero:.byte 0, 0, 0, 0, 0, 0, 0, 0x80one: .double 1.0limit: .double 0.29#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.align 4.globl _pow.def _pow; .scl 2; .type 32; .endef_pow:fldl 12(%esp) // yfxam#ifdef PICcall 1f1: popl %ecxaddl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx#endiffnstswmovb %ah, %dlandb $0x45, %ahcmpb $0x40, %ah // is y == 0 ?je 11fcmpb $0x05, %ah // is y == ±inf ?je 12fcmpb $0x01, %ah // is y == NaN ?je 30ffldl 4(%esp) // x : ysubl $8,%espfxamfnstswmovb %ah, %dhandb $0x45, %ahcmpb $0x40, %ahje 20f // x is ±0cmpb $0x05, %ahje 15f // x is ±inffxch // y : x/* First see whether `y' is a natural number. In this case wecan use a more precise algorithm. */fld %st // y : y : xfistpll (%esp) // y : xfildll (%esp) // int(y) : y : xfucomp %st(1) // y : xfnstswsahfjne 2f/* OK, we have an integer value for y. */popl %eaxpopl %edxorl $0, %edxfstp %st(0) // xjns 4f // y >= 0, jumpfdivrl MO(one) // 1/x (now referred to as x)negl %eaxadcl $0, %edxnegl %edx4: fldl MO(one) // 1 : xfxch6: shrdl $1, %edx, %eaxjnc 5ffxchfmul %st(1) // x : ST*xfxch5: fmul %st(0), %st // x*x : ST*xshrl $1, %edxmovl %eax, %ecxorl %edx, %ecxjnz 6bfstp %st(0) // ST*xret/* y is ±NAN */30: fldl 4(%esp) // x : yfldl MO(one) // 1.0 : x : yfucomp %st(1) // x : yfnstswsahfje 31ffxch // y : x31: fstp %st(1)ret.align 42: /* y is a real number. */fxch // x : yfldl MO(one) // 1.0 : x : yfld %st(1) // x : 1.0 : x : yfsub %st(1) // x-1 : 1.0 : x : yfabs // |x-1| : 1.0 : x : yfcompl MO(limit) // 1.0 : x : yfnstswfxch // x : 1.0 : ysahfja 7ffsub %st(1) // x-1 : 1.0 : yfyl2xp1 // log2(x) : yjmp 8f7: fyl2x // log2(x) : y8: fmul %st(1) // y*log2(x) : yfst %st(1) // y*log2(x) : y*log2(x)frndint // int(y*log2(x)) : y*log2(x)fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x))fxch // fract(y*log2(x)) : int(y*log2(x))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, %espfstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))ret// pow(x,±0) = 1.align 411: fstp %st(0) // pop yfldl MO(one)ret// y == ±inf.align 412: fstp %st(0) // pop yfldl 4(%esp) // xfabsfcompl MO(one) // < 1, == 1, or > 1fnstswandb $0x45, %ahcmpb $0x45, %ahje 13f // jump if x is NaNcmpb $0x40, %ahje 14f // jump if |x| == 1shlb $1, %ahxorb %ah, %dlandl $2, %edxfldl MOX(inf_zero, %edx, 4)ret.align 414: fldl MO(one)ret.align 413: fldl 4(%esp) // load x == NaNret.align 4// x is ±inf15: fstp %st(0) // ytestb $2, %dhjz 16f // jump if x == +inf// We must find out whether y is an odd integer.fld %st // y : yfistpll (%esp) // yfildll (%esp) // int(y) : yfucompp // <empty>fnstswsahfjne 17f// OK, the value is an integer, but is the number of bits small// enough so that all are coming from the mantissa?popl %eaxpopl %edxandb $1, %aljz 18f // jump if not oddmovl %edx, %eaxorl %edx, %edxjns 155fnegl %eax155: cmpl $0x00200000, %eaxja 18f // does not fit in mantissa bits// It's an odd integer.shrl $31, %edxfldl MOX(minf_mzero, %edx, 8)ret.align 416: fcompl MO(zero)addl $8, %espfnstswshrl $5, %eaxandl $8, %eaxfldl MOX(inf_zero, %eax, 1)ret.align 417: shll $30, %edx // sign bit for y in right positionaddl $8, %esp18: shrl $31, %edxfldl MOX(inf_zero, %edx, 8)ret.align 4// x is ±020: fstp %st(0) // ytestb $2, %dljz 21f // y > 0// x is ±0 and y is < 0. We must find out whether y is an odd integer.testb $2, %dhjz 25ffld %st // y : yfistpll (%esp) // yfildll (%esp) // int(y) : yfucompp // <empty>fnstswsahfjne 26f// OK, the value is an integer, but is the number of bits small// enough so that all are coming from the mantissa?popl %eaxpopl %edxandb $1, %aljz 27f // jump if not oddcmpl $0xffe00000, %edxjbe 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)fchsret25: fstp %st(0)26: addl $8, %esp27: // Raise divide-by-zero exception and get infinity value.fldl MO(one)fdivl MO(zero)ret.align 4// x is ±0 and y is > 0. We must find out whether y is an odd integer.21: testb $2, %dhjz 22ffld %st // y : yfistpll (%esp) // yfildll (%esp) // int(y) : yfucompp // <empty>fnstswsahfjne 23f// OK, the value is an integer, but is the number of bits small// enough so that all are coming from the mantissa?popl %eaxpopl %edxandb $1, %aljz 24f // jump if not oddcmpl $0xffe00000, %edxjae 24f // does not fit in mantissa bits// It's an odd integer.fldl MO(mzero)ret22: fstp %st(0)23: addl $8, %esp // Don't use 2 x pop24: fldl MO(zero)ret