summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/math/exp2l.S
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/math/exp2l.S')
-rw-r--r--winsup/cygwin/math/exp2l.S92
1 files changed, 92 insertions, 0 deletions
diff --git a/winsup/cygwin/math/exp2l.S b/winsup/cygwin/math/exp2l.S
new file mode 100644
index 000000000..2e58c37b8
--- /dev/null
+++ b/winsup/cygwin/math/exp2l.S
@@ -0,0 +1,92 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <_mingw_mac.h>
+
+ .file "exp2l.S"
+ .text
+#ifdef __x86_64__
+ .align 8
+#else
+ .align 4
+#endif
+.globl __MINGW_USYMBOL(exp2l)
+ .def __MINGW_USYMBOL(exp2l); .scl 2; .type 32; .endef
+__MINGW_USYMBOL(exp2l):
+#ifdef __x86_64__
+ fldt (%rdx)
+ fxam /* Is NaN or +-Inf? */
+ fstsw %ax
+ movb $0x45, %dh
+ andb %ah, %dh
+ cmpb $0x05, %dh
+ je 1f /* Is +-Inf, jump. */
+ fld %st
+ subq $8, %rsp /* int(x) */
+ fnstcw 4(%rsp)
+ movzwl 4(%rsp), %eax
+ orb $12, %ah
+ movw %ax, (%rsp)
+ fldcw (%rsp)
+ frndint
+ fldcw 4(%rsp)
+ addq $8, %rsp
+ fsubr %st,%st(1) /* fract(x) */
+ fxch
+ f2xm1 /* 2^(fract(x)) - 1 */
+ fld1
+ faddp /* 2^(fract(x)) */
+ fscale /* e^x */
+ fstp %st(1)
+ movq %rcx,%rax
+ movq $0,8(%rcx)
+ fstpt (%rcx)
+ ret
+
+1: testl $0x200, %eax /* Test sign. */
+ jz 2f /* If positive, jump. */
+ fstp %st
+ fldz /* Set result to 0. */
+2: movq %rcx,%rax
+ movq $0,8(%rcx)
+ fstpt (%rcx)
+ ret
+#else
+ fldt 4(%esp)
+/* I added the following ugly construct because exp(+-Inf) resulted
+ in NaN. The ugliness results from the bright minds at Intel.
+ For the i686 the code can be written better.
+ -- drepper@cygnus.com. */
+ fxam /* Is NaN or +-Inf? */
+ fstsw %ax
+ movb $0x45, %dh
+ andb %ah, %dh
+ cmpb $0x05, %dh
+ je 1f /* Is +-Inf, jump. */
+ fld %st
+ subl $8, %esp /* int(x) */
+ fnstcw 4(%esp)
+ movzwl 4(%esp), %eax
+ orb $12, %ah
+ movw %ax, (%esp)
+ fldcw (%esp)
+ frndint
+ fldcw 4(%esp)
+ addl $8, %esp
+ fsubr %st,%st(1) /* fract(x) */
+ fxch
+ f2xm1 /* 2^(fract(x)) - 1 */
+ fld1
+ faddp /* 2^(fract(x)) */
+ fscale /* e^x */
+ fstp %st(1)
+ ret
+
+1: testl $0x200, %eax /* Test sign. */
+ jz 2f /* If positive, jump. */
+ fstp %st
+ fldz /* Set result to 0. */
+2: ret
+#endif