1 /* ix87 specific implementation of complex exponential function for double.
2 Copyright (C) 1997, 2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 ASM_TYPE_DIRECTIVE(huge_nan_null_null,@object)
31 .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
32 .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
36 .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
37 .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
39 .byte 0, 0, 0, 0, 0, 0, 0, 0x80
40 ASM_SIZE_DIRECTIVE(huge_nan_null_null)
42 ASM_TYPE_DIRECTIVE(twopi,@object)
44 .byte 0x35, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0xf, 0xc9, 0x1, 0x40
45 .byte 0, 0, 0, 0, 0, 0
46 ASM_SIZE_DIRECTIVE(twopi)
48 ASM_TYPE_DIRECTIVE(l2e,@object)
50 .byte 0xbc, 0xf0, 0x17, 0x5c, 0x29, 0x3b, 0xaa, 0xb8, 0xff, 0x3f
51 .byte 0, 0, 0, 0, 0, 0
52 ASM_SIZE_DIRECTIVE(l2e)
54 ASM_TYPE_DIRECTIVE(one,@object)
56 ASM_SIZE_DIRECTIVE(one)
60 #define MO(op) op##@GOTOFF(%ecx)
61 #define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
64 #define MOX(op,x,f) op(,x,f)
72 fldl 16(%esp) /* y : x */
79 je 1f /* Jump if real part is +-Inf */
81 je 2f /* Jump if real part is NaN */
85 /* If the imaginary part is not finite we return NaN+i NaN, as
86 for the case when the real part is NaN. A test for +-Inf and
87 NaN would be necessary. But since we know the stack register
88 we applied `fxam' to is not empty we can simply use one test.
89 Check your FPU manual for more information. */
94 /* We have finite numbers in the real and imaginary part. Do
97 fldt MO(l2e) /* log2(e) : x : y */
98 fmulp /* x * log2(e) : y */
99 fld %st /* x * log2(e) : x * log2(e) : y */
100 frndint /* int(x * log2(e)) : x * log2(e) : y */
101 fsubr %st, %st(1) /* int(x * log2(e)) : frac(x * log2(e)) : y */
102 fxch /* frac(x * log2(e)) : int(x * log2(e)) : y */
103 f2xm1 /* 2^frac(x * log2(e))-1 : int(x * log2(e)) : y */
104 faddl MO(one) /* 2^frac(x * log2(e)) : int(x * log2(e)) : y */
105 fscale /* e^x : int(x * log2(e)) : y */
106 fst %st(1) /* e^x : e^x : y */
107 fxch %st(2) /* y : e^x : e^x */
108 fsincos /* cos(y) : sin(y) : e^x : e^x */
112 fmulp %st, %st(3) /* sin(y) : e^x : e^x * cos(y) */
113 fmulp %st, %st(1) /* e^x * sin(y) : e^x * cos(y) */
114 movl 4(%esp), %eax /* Pointer to memory for result. */
119 /* We have to reduce the argument to fsincos. */
121 7: fldt MO(twopi) /* 2*pi : y : e^x : e^x */
122 fxch /* y : 2*pi : e^x : e^x */
123 8: fprem1 /* y%(2*pi) : 2*pi : e^x : e^x */
127 fstp %st(1) /* y%(2*pi) : e^x : e^x */
128 fsincos /* cos(y) : sin(y) : e^x : e^x */
131 movl 4(%esp), %eax /* Pointer to memory for result. */
136 /* The real part is +-inf. We must make further differences. */
141 testb $0x01, %ah /* See above why 0x01 is usable here. */
145 /* The real part is +-Inf and the imaginary part is finite. */
147 cmpb $0x40, %dl /* Imaginary part == 0? */
152 fstp %st(0) /* y */ /* Drop the real part. */
153 andl $16, %edx /* This puts the sign bit of the real part
154 in bit 4. So we can use it to index a
155 small array to select 0 or Inf. */
156 fsincos /* cos(y) : sin(y) */
160 fldl MOX(huge_nan_null_null,%edx,1)
161 movl 4(%esp), %edx /* Pointer to memory for result. */
167 andl $0x80000000, %eax
173 andl $0x80000000, %eax
177 /* We must reduce the argument to fsincos. */
187 fldl MOX(huge_nan_null_null,%edx,1)
188 movl 4(%esp), %edx /* Pointer to memory for result. */
194 andl $0x80000000, %eax
200 andl $0x80000000, %eax
205 /* The real part is +-Inf and the imaginary part is +-0. So return
208 4: movl 4(%esp), %eax /* Pointer to memory for result. */
213 fldl MOX(huge_nan_null_null,%edx,1)
217 /* The real part is +-Inf, the imaginary is also is not finite. */
220 fstp %st(0) /* <empty> */
225 fldl MO(infinity) /* Raise invalid exception. */
234 movl 4(%esp), %eax /* Pointer to memory for result. */
236 fldl MOX(huge_nan_null_null,%edx,1)
237 fldl MOX(huge_nan_null_null+8,%edx,1)
243 /* The real part is NaN. */
245 20: fldl MO(infinity) /* Raise invalid exception. */
250 movl 4(%esp), %eax /* Pointer to memory for result. */
251 fldl MO(huge_nan_null_null+8)
257 weak_alias (__cexp, cexp)