diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-11-15 20:41:36 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-11-15 20:41:36 +0000 |
commit | a264dff2442a60964cbf2c4585b92128a2ce3d97 (patch) | |
tree | 867de300c929711e0e052ca8d76d3e70d9da324e /lib/libm/arch | |
parent | 17af9534d85f69d406b6d05d5ecd1d3a866ccc38 (diff) |
Fix exp(3) for arg Inf and -Inf. From NetBSD; PR 4578. ok deraadt@
Diffstat (limited to 'lib/libm/arch')
-rw-r--r-- | lib/libm/arch/i387/e_exp.S | 118 |
1 files changed, 105 insertions, 13 deletions
diff --git a/lib/libm/arch/i387/e_exp.S b/lib/libm/arch/i387/e_exp.S index bc1b34652cb..e4ec1de95e1 100644 --- a/lib/libm/arch/i387/e_exp.S +++ b/lib/libm/arch/i387/e_exp.S @@ -1,35 +1,127 @@ -/* $OpenBSD: e_exp.S,v 1.5 2005/08/02 11:17:31 espie Exp $ */ +/* $OpenBSD: e_exp.S,v 1.6 2005/11/15 20:41:35 otto Exp $ */ +/* $NetBSD: e_exp.S,v 1.12 2002/02/27 16:32:46 christos Exp $ */ + /* - * Written by J.T. Conklin <jtc@netbsd.org>. - * Public domain. + * Copyright (c) 1993,94 Winning Strategies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Winning Strategies, Inc. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Written by: + * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. */ #include <machine/asm.h> /* e^x = 2^(x * log2(e)) */ ENTRY(__ieee754_exp) - subl $8,%esp - - fstcw 4(%esp) /* store fpu control word */ - movw 4(%esp),%dx +#ifndef __i386__ + /* + * XXX: This code is broken and needs to be merged with the i386 case. + */ + fstcw -12(%rsp) + movw -12(%rsp),%dx orw $0x0180,%dx - movw %dx,(%esp) - fldcw (%esp) /* load modfied control word */ + movw %dx,-16(%rsp) + fldcw -16(%rsp) + movsd %xmm0,-8(%rsp) + fldl -8(%rsp) - fldl 12(%esp) fldl2e fmulp /* x * log2(e) */ - fst %st(1) + fld %st(0) frndint /* int(x * log2(e)) */ fxch %st(1) fsub %st(1),%st /* fract(x * log2(e)) */ + f2xm1 /* 2^(fract(x * log2(e))) - 1 */ + fld1 + faddp /* 2^(fract(x * log2(e))) */ + fscale /* e^x */ + fstp %st(1) + + fstpl -8(%rsp) + movsd -8(%rsp),%xmm0 + fldcw -12(%rsp) + ret +#else + /* + * If x is +-Inf, then the subtraction would give Inf-Inf = NaN. + * Avoid this. Also avoid it if x is NaN for convenience. + */ + movl 8(%esp),%eax + andl $0x7fffffff,%eax + cmpl $0x7ff00000,%eax + jae x_Inf_or_NaN + + fldl 4(%esp) + + /* + * Ensure that the rounding mode is to nearest (to give the smallest + * possible fraction) and that the precision is as high as possible. + * We may as well mask interrupts if we switch the mode. + */ + fstcw 4(%esp) + movl 4(%esp),%eax + andl $0x0300,%eax + cmpl $0x0300,%eax /* RC == 0 && PC == 3? */ + je 1f /* jump if mode is good */ + movl $0x137f,8(%esp) + fldcw 8(%esp) +1: + fldl2e + fmulp /* x * log2(e) */ + fst %st(1) + frndint /* int(x * log2(e)) */ + fst %st(2) + fsubrp /* fract(x * log2(e)) */ f2xm1 /* 2^(fract(x * log2(e))) - 1 */ fld1 faddp /* 2^(fract(x * log2(e))) */ fscale /* e^x */ fstp %st(1) + je 1f + fldcw 4(%esp) +1: + ret - fldcw 4(%esp) /* restore original control word */ +x_Inf_or_NaN: + /* + * Return 0 if x is -Inf. Otherwise just return x, although the + * C version would return (x + x) (Real Indefinite) if x is a NaN. + */ + cmpl $0xfff00000,8(%esp) + jne x_not_minus_Inf + cmpl $0,4(%esp) + jne x_not_minus_Inf + fldz + ret - addl $8,%esp +x_not_minus_Inf: + fldl 4(%esp) ret +#endif |