Update.
[glibc.git] / sysdeps / libm-i387 / e_pow.S
blobe665326438fcbadb8726e8d251184008809d85af
1 /* ix87 specific implementation of pow function.
2    Copyright (C) 1996, 1997 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 Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    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    Library General Public License for more details.
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
21 #include <machine/asm.h>
23 #ifdef __ELF__
24         .section .rodata
25 #else
26         .text
27 #endif
29         .align ALIGNARG(4)
30         ASM_TYPE_DIRECTIVE(infinity,@object)
31 inf_zero:
32 infinity:
33         .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
34         ASM_SIZE_DIRECTIVE(infinity)
35         ASM_TYPE_DIRECTIVE(zero,@object)
36 zero:   .double 0.0
37         ASM_SIZE_DIRECTIVE(zero)
38         ASM_TYPE_DIRECTIVE(minf_mzero,@object)
39 minf_mzero:
40 minfinity:
41         .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
42 mzero:
43         .byte 0, 0, 0, 0, 0, 0, 0, 0x80
44         ASM_SIZE_DIRECTIVE(minf_mzero)
45         ASM_TYPE_DIRECTIVE(one,@object)
46 one:    .double 1.0
47         ASM_SIZE_DIRECTIVE(one)
48         ASM_TYPE_DIRECTIVE(limit,@object)
49 limit:  .double 0.29
50         ASM_SIZE_DIRECTIVE(limit)
51         ASM_TYPE_DIRECTIVE(nan,@object)
52 nan:    .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
53         ASM_SIZE_DIRECTIVE(nan)
55 #ifdef PIC
56 #define MO(op) op##@GOTOFF(%ecx)
57 #define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
58 #else
59 #define MO(op) op
60 #define MOX(op,x,f) op(,x,f)
61 #endif
63         .text
64 ENTRY(__ieee754_pow)
65         fldl    12(%esp)        // y
66         fxam
68 #ifdef  PIC
69         call    1f
70 1:      popl    %ecx
71         addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
72 #endif
74         fnstsw
75         movb    %ah, %dl
76         andb    $0x45, %ah
77         cmpb    $0x40, %ah      // is y == 0 ?
78         je      11f
80         cmpb    $0x05, %ah      // is y == ±inf ?
81         je      12f
83         cmpb    $0x01, %ah      // is y == NaN ?
84         je      30f
86         fldl    4(%esp)         // x : y
88         subl    $8,%esp
90         fxam
91         fnstsw
92         movb    %ah, %dh
93         andb    $0x45, %ah
94         cmpb    $0x40, %ah
95         je      20f             // x is ±0
97         cmpb    $0x05, %ah
98         je      15f             // x is ±inf
100         fxch                    // y : x
102         /* First see whether `y' is a natural number.  In this case we
103            can use a more precise algorithm.  */
104         fld     %st             // y : y : x
105         fistpll (%esp)          // y : x
106         fildll  (%esp)          // int(y) : y : x
107         fucomp  %st(1)          // y : x
108         fnstsw
109         sahf
110         jne     2f
112         /* OK, we have an integer value for y.  */
113         popl    %eax
114         popl    %edx
115         orl     $0, %edx
116         fstp    %st(0)          // x
117         jns     4f              // y >= 0, jump
118         fdivrl  MO(one)         // 1/x          (now referred to as x)
119         negl    %eax
120         adcl    $0, %edx
121         negl    %edx
122 4:      fldl    MO(one)         // 1 : x
123         fxch
125 6:      shrdl   $1, %edx, %eax
126         jnc     5f
127         fxch
128         fmul    %st(1)          // x : ST*x
129         fxch
130 5:      fmul    %st(0), %st     // x*x : ST*x
131         movl    %eax, %ecx
132         orl     %edx, %ecx
133         jnz     6b
134         fstp    %st(0)          // ST*x
135 30:     ret
137         .align ALIGNARG(4)
138 2:      /* y is a real number.  */
139         fxch                    // x : y
140         fldl    MO(one)         // 1.0 : x : y
141         fld     %st(1)          // x : 1.0 : x : y
142         fsub    %st(1)          // x-1 : 1.0 : x : y
143         fabs                    // |x-1| : 1.0 : x : y
144         fcompl  MO(limit)       // 1.0 : x : y
145         fnstsw
146         fxch                    // x : 1.0 : y
147         sahf
148         ja      7f
149         fsub    %st(1)          // x-1 : 1.0 : y
150         fyl2xp1                 // log2(x) : y
151         jmp     8f
153 7:      fyl2x                   // log2(x) : y
154 8:      fmul    %st(1)          // y*log2(x) : y
155         fst     %st(1)          // y*log2(x) : y*log2(x)
156         frndint                 // int(y*log2(x)) : y*log2(x)
157         fsubr   %st, %st(1)     // int(y*log2(x)) : fract(y*log2(x))
158         fxch                    // fract(y*log2(x)) : int(y*log2(x))
159         f2xm1                   // 2^fract(y*log2(x))-1 : int(y*log2(x))
160         faddl   MO(one)         // 2^fract(y*log2(x)) : int(y*log2(x))
161         fscale                  // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
162         addl    $8, %esp
163         fstp    %st(1)          // 2^fract(y*log2(x))*2^int(y*log2(x))
164         ret
167         // pow(x,±0) = 1
168         .align ALIGNARG(4)
169 11:     fstp    %st(0)          // pop y
170         fldl    MO(one)
171         ret
173         // y == ±inf
174         .align ALIGNARG(4)
175 12:     fstp    %st(0)          // pop y
176         fldl    4(%esp)         // x
177         fabs
178         fcompl  MO(one)         // < 1, == 1, or > 1
179         fnstsw
180         andb    $0x45, %ah
181         cmpb    $0x45, %ah
182         je      13f             // jump if x is NaN
184         cmpb    $0x40, %ah
185         je      14f             // jump if |x| == 1
187         shlb    $1, %ah
188         xorb    %ah, %dl
189         andl    $2, %edx
190         fldl    MOX(inf_zero, %edx, 4)
191         ret
193         .align ALIGNARG(4)
194 14:     fldl    MO(nan)
195         faddl   MO(zero)        // raise invalid exception
196         ret
198         .align ALIGNARG(4)
199 13:     fldl    4(%esp)         // load x == NaN
200         ret
202         .align ALIGNARG(4)
203         // x is ±inf
204 15:     fstp    %st(0)          // y
205         testb   $2, %dh
206         jz      16f             // jump if x == +inf
208         // We must find out whether y is an odd integer.
209         fld     %st             // y : y
210         fistpll (%esp)          // y
211         fildll  (%esp)          // int(y) : y
212         fucompp                 // <empty>
213         fnstsw
214         sahf
215         jne     17f
217         // OK, the value is an integer, but is the number of bits small
218         // enough so that all are coming from the mantissa?
219         popl    %eax
220         popl    %edx
221         andb    $1, %al
222         jz      18f             // jump if not odd
223         movl    %edx, %eax
224         orl     %edx, %edx
225         jns     155f
226         negl    %eax
227 155:    cmpl    $0x00200000, %eax
228         ja      18f             // does not fit in mantissa bits
229         // It's an odd integer.
230         shrl    $31, %edx
231         fldl    MOX(minf_mzero, %edx, 8)
232         ret
234         .align ALIGNARG(4)
235 16:     fcompl  MO(zero)
236         addl    $8, %esp
237         fnstsw
238         shrl    $5, %eax
239         andl    $8, %eax
240         fldl    MOX(inf_zero, %eax, 1)
241         ret
243         .align ALIGNARG(4)
244 17:     shll    $30, %edx       // sign bit for y in right position
245         addl    $8, %esp
246 18:     shrl    $31, %edx
247         fldl    MOX(inf_zero, %edx, 8)
248         ret
250         .align ALIGNARG(4)
251         // x is ±0
252 20:     fstp    %st(0)          // y
253         testb   $2, %dl
254         jz      21f             // y > 0
256         // x is ±0 and y is < 0.  We must find out whether y is an odd integer.
257         testb   $2, %dh
258         jz      25f
260         fld     %st             // y : y
261         fistpll (%esp)          // y
262         fildll  (%esp)          // int(y) : y
263         fucompp                 // <empty>
264         fnstsw
265         sahf
266         jne     26f
268         // OK, the value is an integer, but is the number of bits small
269         // enough so that all are coming from the mantissa?
270         popl    %eax
271         popl    %edx
272         andb    $1, %al
273         jz      27f             // jump if not odd
274         cmpl    $0xffe00000, %edx
275         jbe     27f             // does not fit in mantissa bits
276         // It's an odd integer.
277         // Raise divide-by-zero exception and get minus infinity value.
278         fldl    MO(one)
279         fdivl   MO(zero)
280         fchs
281         ret
283 25:     fstp    %st(0)
284 26:     popl    %eax
285         popl    %edx
286 27:     // Raise divide-by-zero exception and get infinity value.
287         fldl    MO(one)
288         fdivl   MO(zero)
289         ret
291         .align ALIGNARG(4)
292         // x is ±0 and y is > 0.  We must find out whether y is an odd integer.
293 21:     testb   $2, %dh
294         jz      22f
296         fld     %st             // y : y
297         fistpll (%esp)          // y
298         fildll  (%esp)          // int(y) : y
299         fucompp                 // <empty>
300         fnstsw
301         sahf
302         jne     23f
304         // OK, the value is an integer, but is the number of bits small
305         // enough so that all are coming from the mantissa?
306         popl    %eax
307         popl    %edx
308         andb    $1, %al
309         jz      24f             // jump if not odd
310         cmpl    $0xffe00000, %edx
311         jae     24f             // does not fit in mantissa bits
312         // It's an odd integer.
313         fldl    MO(mzero)
314         ret
316 22:     fstp    %st(0)
317 23:     popl    %eax
318         popl    %edx
319 24:     fldl    MO(zero)
320         ret
322 END(__ieee754_pow)