Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / x86_64 / fpu / e_powl.S
blob358abb8dcbc8aa494286dbf24e6898a74c575461
1 /* ix87 specific implementation of pow function.
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.
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.
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.
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/>.  */
20 #include <machine/asm.h>
22         .section .rodata.cst8,"aM",@progbits,8
24         .p2align 3
25         .type one,@object
26 one:    .double 1.0
27         ASM_SIZE_DIRECTIVE(one)
28         .type p3,@object
29 p3:     .byte 0, 0, 0, 0, 0, 0, 0x20, 0x40
30         ASM_SIZE_DIRECTIVE(p3)
31         .type p63,@object
32 p63:    .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
33         ASM_SIZE_DIRECTIVE(p63)
34         .type p64,@object
35 p64:    .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43
36         ASM_SIZE_DIRECTIVE(p64)
37         .type p78,@object
38 p78:    .byte 0, 0, 0, 0, 0, 0, 0xd0, 0x44
39         ASM_SIZE_DIRECTIVE(p78)
40         .type pm79,@object
41 pm79:   .byte 0, 0, 0, 0, 0, 0, 0, 0x3b
42         ASM_SIZE_DIRECTIVE(pm79)
44         .section .rodata.cst16,"aM",@progbits,16
46         .p2align 3
47         .type infinity,@object
48 inf_zero:
49 infinity:
50         .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
51         ASM_SIZE_DIRECTIVE(infinity)
52         .type zero,@object
53 zero:   .double 0.0
54         ASM_SIZE_DIRECTIVE(zero)
55         .type minf_mzero,@object
56 minf_mzero:
57 minfinity:
58         .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
59 mzero:
60         .byte 0, 0, 0, 0, 0, 0, 0, 0x80
61         ASM_SIZE_DIRECTIVE(minf_mzero)
63 #ifdef PIC
64 # define MO(op) op##(%rip)
65 #else
66 # define MO(op) op
67 #endif
69         .text
70 ENTRY(__ieee754_powl)
71         fldt    24(%rsp)        // y
72         fxam
75         fnstsw
76         movb    %ah, %dl
77         andb    $0x45, %ah
78         cmpb    $0x40, %ah      // is y == 0 ?
79         je      11f
81         cmpb    $0x05, %ah      // is y == ±inf ?
82         je      12f
84         cmpb    $0x01, %ah      // is y == NaN ?
85         je      30f
87         fldt    8(%rsp)         // x : y
89         fxam
90         fnstsw
91         movb    %ah, %dh
92         andb    $0x45, %ah
93         cmpb    $0x40, %ah
94         je      20f             // x is ±0
96         cmpb    $0x05, %ah
97         je      15f             // x is ±inf
99         cmpb    $0x01, %ah
100         je      31f             // x is NaN
102         fxch                    // y : x
104         /* fistpll raises invalid exception for |y| >= 1L<<63.  */
105         fldl    MO(p63)         // 1L<<63 : y : x
106         fld     %st(1)          // y : 1L<<63 : y : x
107         fabs                    // |y| : 1L<<63 : y : x
108         fcomip  %st(1), %st     // 1L<<63 : y : x
109         fstp    %st(0)          // y : x
110         jnc     2f
112         /* First see whether `y' is a natural number.  In this case we
113            can use a more precise algorithm.  */
114         fld     %st             // y : y : x
115         fistpll -8(%rsp)        // y : x
116         fildll  -8(%rsp)        // int(y) : y : x
117         fucomip %st(1),%st      // y : x
118         je      9f
120         // If y has absolute value at most 0x1p-79, then any finite
121         // nonzero x will result in 1.  Saturate y to those bounds to
122         // avoid underflow in the calculation of y*log2(x).
123         fldl    MO(pm79)        // 0x1p-79 : y : x
124         fld     %st(1)          // y : 0x1p-79 : y : x
125         fabs                    // |y| : 0x1p-79 : y : x
126         fcomip  %st(1), %st     // 0x1p-79 : y : x
127         fstp    %st(0)          // y : x
128         jnc     3f
129         fstp    %st(0)          // pop y
130         fldl    MO(pm79)        // 0x1p-79 : x
131         testb   $2, %dl
132         jnz     3f              // y > 0
133         fchs                    // -0x1p-79 : x
134         jmp     3f
136 9:      /* OK, we have an integer value for y.  Unless very small
137            (we use < 8), use the algorithm for real exponent to avoid
138            accumulation of errors.  */
139         fldl    MO(p3)          // 8 : y : x
140         fld     %st(1)          // y : 8 : y : x
141         fabs                    // |y| : 8 : y : x
142         fcomip  %st(1), %st     // 8 : y : x
143         fstp    %st(0)          // y : x
144         jnc     3f
145         mov     -8(%rsp),%eax
146         mov     -4(%rsp),%edx
147         orl     $0, %edx
148         fstp    %st(0)          // x
149         jns     4f              // y >= 0, jump
150         fdivrl  MO(one)         // 1/x          (now referred to as x)
151         negl    %eax
152         adcl    $0, %edx
153         negl    %edx
154 4:      fldl    MO(one)         // 1 : x
155         fxch
157         /* If y is even, take the absolute value of x.  Otherwise,
158            ensure all intermediate values that might overflow have the
159            sign of x.  */
160         testb   $1, %al
161         jnz     6f
162         fabs
164 6:      shrdl   $1, %edx, %eax
165         jnc     5f
166         fxch
167         fabs
168         fmul    %st(1)          // x : ST*x
169         fxch
170 5:      fld     %st             // x : x : ST*x
171         fabs                    // |x| : x : ST*x
172         fmulp                   // |x|*x : ST*x
173         shrl    $1, %edx
174         movl    %eax, %ecx
175         orl     %edx, %ecx
176         jnz     6b
177         fstp    %st(0)          // ST*x
178         ret
180         /* y is ±NAN */
181 30:     fldt    8(%rsp)         // x : y
182         fldl    MO(one)         // 1.0 : x : y
183         fucomip %st(1),%st      // x : y
184         je      31f
185         fxch                    // y : x
186 31:     fstp    %st(1)
187         ret
189         .align ALIGNARG(4)
190 2:      // y is a large integer (absolute value at least 1L<<63).
191         // If y has absolute value at least 1L<<78, then any finite
192         // nonzero x will result in 0 (underflow), 1 or infinity (overflow).
193         // Saturate y to those bounds to avoid overflow in the calculation
194         // of y*log2(x).
195         fldl    MO(p78)         // 1L<<78 : y : x
196         fld     %st(1)          // y : 1L<<78 : y : x
197         fabs                    // |y| : 1L<<78 : y : x
198         fcomip  %st(1), %st     // 1L<<78 : y : x
199         fstp    %st(0)          // y : x
200         jc      3f
201         fstp    %st(0)          // pop y
202         fldl    MO(p78)         // 1L<<78 : x
203         testb   $2, %dl
204         jz      3f              // y > 0
205         fchs                    // -(1L<<78) : x
206         .align ALIGNARG(4)
207 3:      /* y is a real number.  */
208         subq    $40, %rsp
209         cfi_adjust_cfa_offset (40)
210         fstpt   16(%rsp)        // x
211         fstpt   (%rsp)          // <empty>
212         call    HIDDEN_JUMPTARGET (__powl_helper)       // <result>
213         addq    $40, %rsp
214         cfi_adjust_cfa_offset (-40)
215         ret
217         // pow(x,±0) = 1
218         .align ALIGNARG(4)
219 11:     fstp    %st(0)          // pop y
220         fldl    MO(one)
221         ret
223         // y == ±inf
224         .align ALIGNARG(4)
225 12:     fstp    %st(0)          // pop y
226         fldl    MO(one)         // 1
227         fldt    8(%rsp)         // x : 1
228         fabs                    // abs(x) : 1
229         fucompp                 // < 1, == 1, or > 1
230         fnstsw
231         andb    $0x45, %ah
232         cmpb    $0x45, %ah
233         je      13f             // jump if x is NaN
235         cmpb    $0x40, %ah
236         je      14f             // jump if |x| == 1
238         shlb    $1, %ah
239         xorb    %ah, %dl
240         andl    $2, %edx
241 #ifdef PIC
242         lea     inf_zero(%rip),%rcx
243         fldl    (%rcx, %rdx, 4)
244 #else
245         fldl    inf_zero(,%rdx, 4)
246 #endif
247         ret
249         .align ALIGNARG(4)
250 14:     fldl    MO(one)
251         ret
253         .align ALIGNARG(4)
254 13:     fldt    8(%rsp)         // load x == NaN
255         ret
257         .align ALIGNARG(4)
258         // x is ±inf
259 15:     fstp    %st(0)          // y
260         testb   $2, %dh
261         jz      16f             // jump if x == +inf
263         // fistpll raises invalid exception for |y| >= 1L<<63, but y
264         // may be odd unless we know |y| >= 1L<<64.
265         fldl    MO(p64)         // 1L<<64 : y
266         fld     %st(1)          // y : 1L<<64 : y
267         fabs                    // |y| : 1L<<64 : y
268         fcomip  %st(1), %st     // 1L<<64 : y
269         fstp    %st(0)          // y
270         jnc     16f
271         fldl    MO(p63)         // p63 : y
272         fxch                    // y : p63
273         fprem                   // y%p63 : p63
274         fstp    %st(1)          // y%p63
276         // We must find out whether y is an odd integer.
277         fld     %st             // y : y
278         fistpll -8(%rsp)        // y
279         fildll  -8(%rsp)        // int(y) : y
280         fucomip %st(1),%st
281         ffreep  %st             // <empty>
282         jne     17f
284         // OK, the value is an integer, but is it odd?
285         mov     -8(%rsp), %eax
286         mov     -4(%rsp), %edx
287         andb    $1, %al
288         jz      18f             // jump if not odd
289         // It's an odd integer.
290         shrl    $31, %edx
291 #ifdef PIC
292         lea     minf_mzero(%rip),%rcx
293         fldl    (%rcx, %rdx, 8)
294 #else
295         fldl    minf_mzero(,%rdx, 8)
296 #endif
297         ret
299         .align ALIGNARG(4)
300 16:     fcompl  MO(zero)
301         fnstsw
302         shrl    $5, %eax
303         andl    $8, %eax
304 #ifdef PIC
305         lea     inf_zero(%rip),%rcx
306         fldl    (%rcx, %rax, 1)
307 #else
308         fldl    inf_zero(,%rax, 1)
309 #endif
310         ret
312         .align ALIGNARG(4)
313 17:     shll    $30, %edx       // sign bit for y in right position
314 18:     shrl    $31, %edx
315 #ifdef PIC
316         lea     inf_zero(%rip),%rcx
317         fldl    (%rcx, %rdx, 8)
318 #else
319         fldl    inf_zero(,%rdx, 8)
320 #endif
321         ret
323         .align ALIGNARG(4)
324         // x is ±0
325 20:     fstp    %st(0)          // y
326         testb   $2, %dl
327         jz      21f             // y > 0
329         // x is ±0 and y is < 0.  We must find out whether y is an odd integer.
330         testb   $2, %dh
331         jz      25f
333         // fistpll raises invalid exception for |y| >= 1L<<63, but y
334         // may be odd unless we know |y| >= 1L<<64.
335         fldl    MO(p64)         // 1L<<64 : y
336         fld     %st(1)          // y : 1L<<64 : y
337         fabs                    // |y| : 1L<<64 : y
338         fcomip  %st(1), %st     // 1L<<64 : y
339         fstp    %st(0)          // y
340         jnc     25f
341         fldl    MO(p63)         // p63 : y
342         fxch                    // y : p63
343         fprem                   // y%p63 : p63
344         fstp    %st(1)          // y%p63
346         fld     %st             // y : y
347         fistpll -8(%rsp)        // y
348         fildll  -8(%rsp)        // int(y) : y
349         fucomip %st(1),%st
350         ffreep  %st             // <empty>
351         jne     26f
353         // OK, the value is an integer, but is it odd?
354         mov     -8(%rsp),%eax
355         mov     -4(%rsp),%edx
356         andb    $1, %al
357         jz      27f             // jump if not odd
358         // It's an odd integer.
359         // Raise divide-by-zero exception and get minus infinity value.
360         fldl    MO(one)
361         fdivl   MO(zero)
362         fchs
363         ret
365 25:     fstp    %st(0)
367 27:     // Raise divide-by-zero exception and get infinity value.
368         fldl    MO(one)
369         fdivl   MO(zero)
370         ret
372         .align ALIGNARG(4)
373         // x is ±0 and y is > 0.  We must find out whether y is an odd integer.
374 21:     testb   $2, %dh
375         jz      22f
377         // fistpll raises invalid exception for |y| >= 1L<<63, but y
378         // may be odd unless we know |y| >= 1L<<64.
379         fldl    MO(p64)         // 1L<<64 : y
380         fxch                    // y : 1L<<64
381         fcomi   %st(1), %st     // y : 1L<<64
382         fstp    %st(1)          // y
383         jnc     22f
384         fldl    MO(p63)         // p63 : y
385         fxch                    // y : p63
386         fprem                   // y%p63 : p63
387         fstp    %st(1)          // y%p63
389         fld     %st             // y : y
390         fistpll -8(%rsp)        // y
391         fildll  -8(%rsp)        // int(y) : y
392         fucomip %st(1),%st
393         ffreep  %st             // <empty>
394         jne     23f
396         // OK, the value is an integer, but is it odd?
397         mov     -8(%rsp),%eax
398         mov     -4(%rsp),%edx
399         andb    $1, %al
400         jz      24f             // jump if not odd
401         // It's an odd integer.
402         fldl    MO(mzero)
403         ret
405 22:     fstp    %st(0)
407 24:     fldl    MO(zero)
408         ret
410 END(__ieee754_powl)
411 strong_alias (__ieee754_powl, __powl_finite)