summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libm/Makefile4
-rw-r--r--lib/libm/arch/amd64/e_exp.S101
2 files changed, 103 insertions, 2 deletions
diff --git a/lib/libm/Makefile b/lib/libm/Makefile
index fa0196ba871..cd0a0799563 100644
--- a/lib/libm/Makefile
+++ b/lib/libm/Makefile
@@ -1,5 +1,5 @@
# $NetBSD: Makefile,v 1.28 1995/11/20 22:06:19 jtc Exp $
-# $OpenBSD: Makefile,v 1.38 2006/03/18 20:13:24 brad Exp $
+# $OpenBSD: Makefile,v 1.39 2006/03/19 00:01:04 kettenis Exp $
#
# @(#)Makefile 5.1beta 93/09/24
#
@@ -66,7 +66,7 @@ ARCH_SRCS = e_acos.S e_asin.S e_atan2.S e_exp.S e_fmod.S e_log.S e_log10.S \
.elif (${MACHINE_ARCH} == "amd64")
.PATH: ${.CURDIR}/arch/amd64
CPPFLAGS+=-I${.CURDIR}/arch/amd64
-ARCH_SRCS = e_acos.S e_asin.S e_atan2.S e_fmod.S e_log.S e_log10.S \
+ARCH_SRCS = e_acos.S e_asin.S e_atan2.S e_exp.S e_fmod.S e_log.S e_log10.S \
e_remainder.S e_remainderf.S e_scalb.S e_sqrt.S e_sqrtf.S \
s_atan.S s_atanf.S s_ceil.S s_ceilf.S s_copysign.S s_copysignf.S \
s_cos.S s_cosf.S s_finite.S s_finitef.S s_floor.S s_floorf.S \
diff --git a/lib/libm/arch/amd64/e_exp.S b/lib/libm/arch/amd64/e_exp.S
new file mode 100644
index 00000000000..5ae6516e991
--- /dev/null
+++ b/lib/libm/arch/amd64/e_exp.S
@@ -0,0 +1,101 @@
+/* $OpenBSD: e_exp.S,v 1.4 2006/03/19 00:01:04 kettenis Exp $ */
+/* $NetBSD: e_exp.S,v 1.12 2002/02/27 16:32:46 christos Exp $ */
+
+/*
+ * 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"
+
+/* e^x = 2^(x * log2(e)) */
+ENTRY(__ieee754_exp)
+ XMM_ONE_ARG_DOUBLE_PROLOGUE
+ /*
+ * If x is +-Inf, then the subtraction would give Inf-Inf = NaN.
+ * Avoid this. Also avoid it if x is NaN for convenience.
+ */
+ movl -4(%rsp),%eax
+ andl $0x7fffffff,%eax
+ cmpl $0x7ff00000,%eax
+ jae x_Inf_or_NaN
+
+ fldl ARG_DOUBLE_ONE
+
+ /*
+ * 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 -8(%rsp)
+ movl -8(%rsp),%eax
+ andl $0x0300,%eax
+ cmpl $0x0300,%eax /* RC == 0 && PC == 3? */
+ je 1f /* jump if mode is good */
+ movl $0x137f,-4(%rsp)
+ fldcw -4(%rsp)
+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 -8(%rsp)
+1:
+ XMM_DOUBLE_EPILOGUE
+ 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,-4(%rsp)
+ jne x_not_minus_Inf
+ cmpl $0,-8(%rsp)
+ jne x_not_minus_Inf
+ xorpd %xmm0,%xmm0
+ ret
+
+x_not_minus_Inf:
+ movsd ARG_DOUBLE_ONE,%xmm0
+ ret