PR/15748: Ray Brownrigg: exp(log(0)) is broken.
Use FreeBSD's version. Handles inf/nan and rounding modes.
This commit is contained in:
parent
76fed8b638
commit
47c5991d7a
@ -1,28 +1,55 @@
|
||||
/* $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>
|
||||
|
||||
#include "abi.h"
|
||||
|
||||
RCSID("$NetBSD: e_exp.S,v 1.11 2001/06/19 17:49:36 fvdl Exp $")
|
||||
RCSID("$NetBSD: e_exp.S,v 1.12 2002/02/27 16:32:46 christos Exp $")
|
||||
#if 0
|
||||
RCSID("$FreeBSD: src/lib/msun/i387/e_exp.S,v 1.8.2.1 2000/07/10 09:16:28 obrien Exp $")
|
||||
#endif
|
||||
|
||||
/* e^x = 2^(x * log2(e)) */
|
||||
ENTRY(__ieee754_exp)
|
||||
#ifdef __i386__
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $8,%esp
|
||||
|
||||
fstcw -12(%ebp) /* store fpu control word */
|
||||
movw -12(%ebp),%dx
|
||||
orw $0x0180,%dx
|
||||
movw %dx,-16(%ebp)
|
||||
fldcw -16(%ebp) /* load modfied control word */
|
||||
fldl 8(%ebp)
|
||||
#else
|
||||
#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
|
||||
@ -30,7 +57,6 @@ ENTRY(__ieee754_exp)
|
||||
fldcw -16(%rsp)
|
||||
movsd %xmm0,-8(%rsp)
|
||||
fldl -8(%rsp)
|
||||
#endif
|
||||
|
||||
fldl2e
|
||||
fmulp /* x * log2(e) */
|
||||
@ -44,12 +70,64 @@ ENTRY(__ieee754_exp)
|
||||
fscale /* e^x */
|
||||
fstp %st(1)
|
||||
|
||||
#ifdef __i386__
|
||||
fldcw -12(%ebp) /* restore original control word */
|
||||
leave
|
||||
#else
|
||||
fstpl -8(%rsp)
|
||||
movsd -8(%rsp),%xmm0
|
||||
fldcw -12(%rsp)
|
||||
#endif
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
x_not_minus_Inf:
|
||||
fldl 4(%esp)
|
||||
ret
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user