/* ix87 specific implementation of exp(x)-1.
- Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1996-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
Based on code by John C. Bowman <bowman@ipp-garching.mpg.de>.
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Using: e^x - 1 = 2^(x * log2(e)) - 1 */
#include <sysdep.h>
#include <machine/asm.h>
+#include <i386-math-asm.h>
+#include <libm-alias-float.h>
-#ifdef __ELF__
.section .rodata
-#else
- .text
-#endif
+
.align ALIGNARG(4)
- ASM_TYPE_DIRECTIVE(minus1,@object)
+ .type minus1,@object
minus1: .double -1.0
ASM_SIZE_DIRECTIVE(minus1)
- ASM_TYPE_DIRECTIVE(one,@object)
+ .type one,@object
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
- ASM_TYPE_DIRECTIVE(l2e,@object)
+ .type l2e,@object
l2e: .tfloat 1.442695040888963407359924681002
ASM_SIZE_DIRECTIVE(l2e)
+DEFINE_FLT_MIN
+
#ifdef PIC
#define MO(op) op##@GOTOFF(%edx)
#else
jae HIDDEN_JUMPTARGET (__expf)
flds 4(%esp) // x
- fxam // Is NaN or +-Inf?
+ fxam // Is NaN, +-Inf or +-0?
+ xorb $0x80, %ah
+ cmpl $0xc190, %eax // is num <= -18.0?
fstsw %ax
movb $0x45, %ch
+ jb 4f
+
+ // Below -18.0 (may be -NaN or -Inf).
+ andb %ah, %ch
+#ifdef PIC
+ LOAD_PIC_REG (dx)
+#endif
+ cmpb $0x01, %ch
+ je 5f // If -NaN, jump.
+ jmp 2f // -large, possibly -Inf.
+
+4: // In range -18.0 to 88.5 (may be +-0 but not NaN or +-Inf).
andb %ah, %ch
cmpb $0x40, %ch
je 3f // If +-0, jump.
#ifdef PIC
LOAD_PIC_REG (dx)
#endif
- cmpb $0x05, %ch
- je 2f // If +-Inf, jump.
- fldt MO(l2e) // log2(e) : x
+5: fldt MO(l2e) // log2(e) : x
fmulp // log2(e)*x
fld %st // log2(e)*x : log2(e)*x
+ // Set round-to-nearest temporarily.
+ subl $8, %esp
+ cfi_adjust_cfa_offset (8)
+ fstcw 4(%esp)
+ movl $0xf3ff, %ecx
+ andl 4(%esp), %ecx
+ movl %ecx, (%esp)
+ fldcw (%esp)
frndint // int(log2(e)*x) : log2(e)*x
+ fldcw 4(%esp)
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x)
fxch // fract(log2(e)*x) : int(log2(e)*x)
f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x)
fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x)
fsubrp %st, %st(1) // 2^(log2(e)*x)
+ FLT_CHECK_FORCE_UFLOW
ret
-2: testl $0x200, %eax // Test sign.
- jz 3f // If positive, jump.
- fstp %st
+2: fstp %st
fldl MO(minus1) // Set result to -1.0.
3: ret
END(__expm1f)
-weak_alias (__expm1f, expm1f)
+libm_alias_float (__expm1, expm1)