]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/fpu/s_asinhl.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / i386 / fpu / s_asinhl.S
1 /* ix87 specific implementation of arcsinh.
2 Copyright (C) 1996-2015 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, see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <machine/asm.h>
21
22 .section .rodata
23
24 .align ALIGNARG(4)
25 .type huge,@object
26 huge: .tfloat 1e+4930
27 ASM_SIZE_DIRECTIVE(huge)
28 .align ALIGNARG(4)
29 /* Please note that we use double value for 1.0. This number
30 has an exact representation and so we don't get accuracy
31 problems. The advantage is that the code is simpler. */
32 .type one,@object
33 one: .double 1.0
34 ASM_SIZE_DIRECTIVE(one)
35 /* It is not important that this constant is precise. It is only
36 a value which is known to be on the safe side for using the
37 fyl2xp1 instruction. */
38 .type limit,@object
39 limit: .double 0.29
40 ASM_SIZE_DIRECTIVE(limit)
41
42 #ifdef PIC
43 #define MO(op) op##@GOTOFF(%edx)
44 #else
45 #define MO(op) op
46 #endif
47
48 .text
49 ENTRY(__asinhl)
50 movl 12(%esp), %ecx
51 movl $0x7fff, %eax
52 andl %ecx, %eax
53 andl $0x8000, %ecx
54 movl %eax, %edx
55 orl $0xffff8000, %edx
56 incl %edx
57 jz 7f // x in ±Inf or NaN
58 xorl %ecx, 12(%esp)
59 fldt 4(%esp) // |x|
60 cmpl $0x3fde, %eax
61 jb 2f // |x| < 2^-34
62 fldln2 // log(2) : |x|
63 cmpl $0x4020, %eax
64 fxch // |x| : log(2)
65 ja 3f // |x| > 2^34
66 #ifdef PIC
67 LOAD_PIC_REG (dx)
68 #endif
69 cmpl $0x4000, %eax
70 ja 5f // |x| > 2
71
72 // 2^-34 <= |x| <= 2 => y = sign(x)*log1p(|x|+|x|^2/(1+sqrt(1+|x|^2)))
73 fld %st // |x| : |x| : log(2)
74 fmul %st(1) // |x|^2 : |x| : log(2)
75 fld %st // |x|^2 : |x|^2 : |x| : log(2)
76 faddl MO(one) // 1+|x|^2 : |x|^2 : |x| : log(2)
77 fsqrt // sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
78 faddl MO(one) // 1+sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
79 fdivrp // |x|^2/(1+sqrt(1+|x|^2)) : |x| : log(2)
80 faddp // |x|+|x|^2/(1+sqrt(1+|x|^2)) : log(2)
81 fcoml MO(limit)
82 fnstsw
83 sahf
84 ja 6f
85 fyl2xp1
86 jecxz 4f
87 fchs
88 4: ret
89
90 7: fldt 4(%esp)
91 ret
92
93 6: faddl MO(one)
94 fyl2x
95 jecxz 4f
96 fchs
97 4: ret
98
99 // |x| < 2^-34 => y = x (inexact iff |x| != 0.0)
100 .align ALIGNARG(4)
101 2:
102 #ifdef PIC
103 LOAD_PIC_REG (dx)
104 #endif
105 jecxz 4f
106 fchs // x
107 4: fld %st // x : x
108 fldt MO(huge) // huge : x : x
109 faddp // huge+x : x
110 fstp %st(0) // x
111 ret
112
113 // |x| > 2^34 => y = sign(x) * (log(|x|) + log(2))
114 .align ALIGNARG(4)
115 3: fyl2x // log(|x|)
116 fldln2 // log(2) : log(|x|)
117 faddp // log(|x|)+log(2)
118 jecxz 4f
119 fchs
120 4: ret
121
122 // |x| > 2 => y = sign(x) * log(2*|x| + 1/(|x|+sqrt(x*x+1)))
123 .align ALIGNARG(4)
124 5: fld %st // |x| : |x| : log(2)
125 fadd %st, %st(1) // |x| : 2*|x| : log(2)
126 fld %st // |x| : |x| : 2*|x| : log(2)
127 fmul %st(1) // |x|^2 : |x| : 2*|x| : log(2)
128 faddl MO(one) // 1+|x|^2 : |x| : 2*|x| : log(2)
129 fsqrt // sqrt(1+|x|^2) : |x| : 2*|x| : log(2)
130 faddp // |x|+sqrt(1+|x|^2) : 2*|x| : log(2)
131 fdivrl MO(one) // 1/(|x|+sqrt(1+|x|^2)) : 2*|x| : log(2)
132 faddp // 2*|x|+1/(|x|+sqrt(1+|x|^2)) : log(2)
133 fyl2x // log(2*|x|+1/(|x|+sqrt(1+|x|^2)))
134 jecxz 4f
135 fchs
136 4: ret
137 END(__asinhl)
138 weak_alias (__asinhl, asinhl)