1/* ix87 specific implementation of arctanh function. 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#include <machine/asm.h> 20#include <libm-alias-finite.h> 21 22 .section .rodata 23 24 .align ALIGNARG(4) 25 /* Please note that we use double values for 0.5 and 1.0. These 26 numbers have exact representations and so we don't get accuracy 27 problems. The advantage is that the code is simpler. */ 28 .type half,@object 29half: .double 0.5 30 ASM_SIZE_DIRECTIVE(half) 31 .type one,@object 32one: .double 1.0 33 ASM_SIZE_DIRECTIVE(one) 34 /* It is not important that this constant is precise. It is only 35 a value which is known to be on the safe side for using the 36 fyl2xp1 instruction. */ 37 .type limit,@object 38limit: .double 0.29 39 ASM_SIZE_DIRECTIVE(limit) 40 .align ALIGNARG(4) 41 .type ln2_2,@object 42ln2_2: .tfloat 0.3465735902799726547086160 43 ASM_SIZE_DIRECTIVE(ln2_2) 44 45#ifdef PIC 46#define MO(op) op##@GOTOFF(%edx) 47#else 48#define MO(op) op 49#endif 50 51 .text 52ENTRY(__ieee754_atanhl) 53 movl 12(%esp), %ecx 54 55 movl %ecx, %eax 56 andl $0x7fff, %eax 57 cmpl $0x7fff, %eax 58 je 5f 59 cmpl $0x3fdf, %eax 60 jge 7f 61 // Exponent below -32; return x, with underflow if subnormal. 62 fldt 4(%esp) 63 cmpl $0, %eax 64 jne 8f 65 fld %st(0) 66 fmul %st(0) 67 fstp %st(0) 688: ret 697: 70 71#ifdef PIC 72 LOAD_PIC_REG (dx) 73#endif 74 75 andl $0x8000, %ecx // ECX == 0 iff X >= 0 76 77 fldt MO(ln2_2) // 0.5*ln2 78 xorl %ecx, 12(%esp) 79 fldt 4(%esp) // |x| : 0.5*ln2 80 fcoml MO(half) // |x| : 0.5*ln2 81 fld %st(0) // |x| : |x| : 0.5*ln2 82 fnstsw // |x| : |x| : 0.5*ln2 83 sahf 84 jae 2f 85 fadd %st, %st(1) // |x| : 2*|x| : 0.5*ln2 86 fld %st // |x| : |x| : 2*|x| : 0.5*ln2 87 fsubrl MO(one) // 1-|x| : |x| : 2*|x| : 0.5*ln2 88 fxch // |x| : 1-|x| : 2*|x| : 0.5*ln2 89 fmul %st(2) // 2*|x|^2 : 1-|x| : 2*|x| : 0.5*ln2 90 fdivp // (2*|x|^2)/(1-|x|) : 2*|x| : 0.5*ln2 91 faddp // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 92 fcoml MO(limit) // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 93 fnstsw // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 94 sahf 95 jae 4f 96 fyl2xp1 // 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|)) 97 jecxz 3f 98 fchs // 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x)) 993: ret 100 101 .align ALIGNARG(4) 1024: faddl MO(one) // 1+2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 103 fyl2x // 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|)) 104 jecxz 3f 105 fchs // 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x)) 1063: ret 107 108 .align ALIGNARG(4) 1092: faddl MO(one) // 1+|x| : |x| : 0.5*ln2 110 fxch // |x| : 1+|x| : 0.5*ln2 111 fsubrl MO(one) // 1-|x| : 1+|x| : 0.5*ln2 112 fdivrp // (1+|x|)/(1-|x|) : 0.5*ln2 113 fyl2x // 0.5*ln2*ld((1+|x|)/(1-|x|)) 114 jecxz 3f 115 fchs // 0.5*ln2*ld((1+x)/(1-x)) 1163: ret 117 118 // x == NaN or �Inf 1195: cmpl $0x80000000, 8(%esp) 120 ja 6f 121 cmpl $0, 4(%esp) 122 je 7b 1236: fldt 4(%esp) 124 fadd %st(0) 125 ret 126END(__ieee754_atanhl) 127libm_alias_finite (__ieee754_atanhl, __atanhl) 128