1/* ix87 specific implementation of exp(x)-1. 2 Copyright (C) 1996-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ 20 21#include <sysdep.h> 22#include <machine/asm.h> 23#include <i386-math-asm.h> 24#include <libm-alias-double.h> 25 26 .section .rodata 27 28 .align ALIGNARG(4) 29 .type minus1,@object 30minus1: .double -1.0 31 ASM_SIZE_DIRECTIVE(minus1) 32 .type one,@object 33one: .double 1.0 34 ASM_SIZE_DIRECTIVE(one) 35 .type l2e,@object 36l2e: .tfloat 1.442695040888963407359924681002 37 ASM_SIZE_DIRECTIVE(l2e) 38 39DEFINE_DBL_MIN 40 41#ifdef PIC 42#define MO(op) op##@GOTOFF(%edx) 43#else 44#define MO(op) op 45#endif 46 47 .text 48ENTRY(__expm1) 49 movzwl 4+6(%esp), %eax 50 xorb $0x80, %ah // invert sign bit (now 1 is "positive") 51 cmpl $0xc086, %eax // is num >= 704? 52 jae HIDDEN_JUMPTARGET (__exp) 53 54 fldl 4(%esp) // x 55 fxam // Is NaN, +-Inf or +-0? 56 xorb $0x80, %ah 57 cmpl $0xc043, %eax // is num <= -38.0? 58 fstsw %ax 59 movb $0x45, %ch 60 jb 4f 61 62 // Below -38.0 (may be -NaN or -Inf). 63 andb %ah, %ch 64#ifdef PIC 65 LOAD_PIC_REG (dx) 66#endif 67 cmpb $0x01, %ch 68 je 5f // If -NaN, jump. 69 jmp 2f // -large, possibly -Inf. 70 714: // In range -38.0 to 704.0 (may be +-0 but not NaN or +-Inf). 72 andb %ah, %ch 73 cmpb $0x40, %ch 74 je 3f // If +-0, jump. 75#ifdef PIC 76 LOAD_PIC_REG (dx) 77#endif 78 795: fldt MO(l2e) // log2(e) : x 80 fmulp // log2(e)*x 81 fld %st // log2(e)*x : log2(e)*x 82 // Set round-to-nearest temporarily. 83 subl $8, %esp 84 cfi_adjust_cfa_offset (8) 85 fstcw 4(%esp) 86 movl $0xf3ff, %ecx 87 andl 4(%esp), %ecx 88 movl %ecx, (%esp) 89 fldcw (%esp) 90 frndint // int(log2(e)*x) : log2(e)*x 91 fldcw 4(%esp) 92 addl $8, %esp 93 cfi_adjust_cfa_offset (-8) 94 fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x) 95 fxch // fract(log2(e)*x) : int(log2(e)*x) 96 f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x) 97 fscale // 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x) 98 fxch // int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) 99 fldl MO(one) // 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) 100 fscale // 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) 101 fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) 102 fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) 103 fsubrp %st, %st(1) // 2^(log2(e)*x) 104 DBL_CHECK_FORCE_UFLOW 105 ret 106 1072: fstp %st 108 fldl MO(minus1) // Set result to -1.0. 1093: ret 110END(__expm1) 111libm_alias_double (__expm1, expm1) 112