1/* ix87 specific implementation of arctanh function. 2 Copyright (C) 1996, 1999 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. 5 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. 10 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. 15 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 19 02111-1307 USA. */ 20 21#include <machine/asm.h> 22 23#ifdef __ELF__ 24 .section .rodata 25#else 26 .text 27#endif 28 29 .align ALIGNARG(4) 30 /* Please note that we use double values for 0.5 and 1.0. These 31 numbers have exact representations and so we don't get accuracy 32 problems. The advantage is that the code is simpler. */ 33 ASM_TYPE_DIRECTIVE(half,@object) 34half: .double 0.5 35 ASM_SIZE_DIRECTIVE(half) 36 ASM_TYPE_DIRECTIVE(one,@object) 37one: .double 1.0 38 ASM_SIZE_DIRECTIVE(one) 39 /* It is not important that this constant is precise. It is only 40 a value which is known to be on the safe side for using the 41 fyl2xp1 instruction. */ 42 ASM_TYPE_DIRECTIVE(limit,@object) 43limit: .double 0.29 44 ASM_SIZE_DIRECTIVE(limit) 45 .align ALIGNARG(4) 46 ASM_TYPE_DIRECTIVE(ln2_2,@object) 47ln2_2: .tfloat 0.3465735902799726547086160 48 ASM_SIZE_DIRECTIVE(ln2_2) 49 50#ifdef PIC 51#define MO(op) op##@GOTOFF(%edx) 52#else 53#define MO(op) op 54#endif 55 56 .text 57ENTRY(__ieee754_atanhl) 58 movl 12(%esp), %ecx 59 60 movl %ecx, %eax 61 andl $0x7fff, %eax 62 cmpl $0x7fff, %eax 63 je 5f 647: 65 66#ifdef PIC 67 call 1f 681: popl %edx 69 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %edx 70#endif 71 72 andl $0x8000, %ecx // ECX == 0 iff X >= 0 73 74 fldt MO(ln2_2) // 0.5*ln2 75 xorl %ecx, 12(%esp) 76 fldt 4(%esp) // |x| : 0.5*ln2 77 fcoml MO(half) // |x| : 0.5*ln2 78 fld %st(0) // |x| : |x| : 0.5*ln2 79 fnstsw // |x| : |x| : 0.5*ln2 80 sahf 81 jae 2f 82 fadd %st, %st(1) // |x| : 2*|x| : 0.5*ln2 83 fld %st // |x| : |x| : 2*|x| : 0.5*ln2 84 fsubrl MO(one) // 1-|x| : |x| : 2*|x| : 0.5*ln2 85 fxch // |x| : 1-|x| : 2*|x| : 0.5*ln2 86 fmul %st(2) // 2*|x|^2 : 1-|x| : 2*|x| : 0.5*ln2 87 fdivp // (2*|x|^2)/(1-|x|) : 2*|x| : 0.5*ln2 88 faddp // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 89 fcoml MO(limit) // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 90 fnstsw // 2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 91 sahf 92 jae 4f 93 fyl2xp1 // 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|)) 94 jecxz 3f 95 fchs // 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x)) 963: ret 97 98 .align ALIGNARG(4) 994: faddl MO(one) // 1+2*|x|+(2*|x|^2)/(1-|x|) : 0.5*ln2 100 fyl2x // 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|)) 101 jecxz 3f 102 fchs // 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x)) 1033: ret 104 105 .align ALIGNARG(4) 1062: faddl MO(one) // 1+|x| : |x| : 0.5*ln2 107 fxch // |x| : 1+|x| : 0.5*ln2 108 fsubrl MO(one) // 1-|x| : 1+|x| : 0.5*ln2 109 fdivrp // (1+|x|)/(1-|x|) : 0.5*ln2 110 fyl2x // 0.5*ln2*ld((1+|x|)/(1-|x|)) 111 jecxz 3f 112 fchs // 0.5*ln2*ld((1+x)/(1-x)) 1133: ret 114 115 // x == NaN or �Inf 1165: cmpl $0x80000000, 8(%esp) 117 ja 6f 118 cmpl $0, 4(%esp) 119 je 7b 1206: fldt 4(%esp) 121 ret 122END(__ieee754_atanhl) 123