VirtualBox

source: vbox/trunk/src/recompiler/InnoTek/e_powl-x86.S@ 4071

Last change on this file since 4071 was 3727, checked in by vboxsync, 17 years ago

Double underscore cleanup.

File size: 8.6 KB
Line 
1/* ix87 specific implementation of pow function.
2 Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
21
22/*#include <machine/asm.h>*/
23#include <iprt/cdefs.h>
24
25#ifdef __MINGW32__
26# define ASM_TYPE_DIRECTIVE(name,typearg)
27# define ASM_SIZE_DIRECTIVE(name)
28# define cfi_adjust_cfa_offset(a)
29# define C_LABEL(name) _ ## name:
30# define C_SYMBOL_NAME(name) _ ## name
31# define ASM_GLOBAL_DIRECTIVE .global
32# define ALIGNARG(log2) 1<<log2
33#elif __APPLE__
34# define ASM_TYPE_DIRECTIVE(name,typearg)
35# define ASM_SIZE_DIRECTIVE(name)
36# define cfi_adjust_cfa_offset(a)
37# define C_LABEL(name) _ ## name:
38# define C_SYMBOL_NAME(name) _ ## name
39# define ASM_GLOBAL_DIRECTIVE .globl
40# define ALIGNARG(log2) log2
41#else
42# define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
43# define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
44# define C_LABEL(name) name:
45# define C_SYMBOL_NAME(name) name
46# /* figure this one out. */
47# define cfi_adjust_cfa_offset(a)
48# define ASM_GLOBAL_DIRECTIVE .global
49# define ALIGNARG(log2) 1<<log2
50#endif
51
52#define ENTRY(name) \
53 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
54 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
55 .align ALIGNARG(4); \
56 C_LABEL(name)
57
58#undef END
59#define END(name) \
60 ASM_SIZE_DIRECTIVE(name)
61
62#ifdef __ELF__
63 .section .rodata
64#else
65 .text
66#endif
67
68 .align ALIGNARG(4)
69 ASM_TYPE_DIRECTIVE(infinity,@object)
70inf_zero:
71infinity:
72 .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
73 ASM_SIZE_DIRECTIVE(infinity)
74 ASM_TYPE_DIRECTIVE(zero,@object)
75zero: .double 0.0
76 ASM_SIZE_DIRECTIVE(zero)
77 ASM_TYPE_DIRECTIVE(minf_mzero,@object)
78minf_mzero:
79minfinity:
80 .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
81mzero:
82 .byte 0, 0, 0, 0, 0, 0, 0, 0x80
83 ASM_SIZE_DIRECTIVE(minf_mzero)
84 ASM_TYPE_DIRECTIVE(one,@object)
85one: .double 1.0
86 ASM_SIZE_DIRECTIVE(one)
87 ASM_TYPE_DIRECTIVE(limit,@object)
88limit: .double 0.29
89 ASM_SIZE_DIRECTIVE(limit)
90 ASM_TYPE_DIRECTIVE(p63,@object)
91p63: .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
92 ASM_SIZE_DIRECTIVE(p63)
93
94#ifdef PIC
95#define MO(op) op##@GOTOFF(%ecx)
96#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
97#else
98#define MO(op) op
99#define MOX(op,x,f) op(,x,f)
100#endif
101
102 .text
103//ENTRY(__ieee754_powl)
104ENTRY(RT_NOCRT(powl))
105#ifdef RT_OS_DARWIN /* 16-byte long double with 8 byte alignment requirements */
106 fldt 20(%esp) // y
107#else
108 fldt 16(%esp) // y
109#endif
110 fxam
111
112#ifdef PIC
113 LOAD_PIC_REG (cx)
114#endif
115
116 fnstsw
117 movb %ah, %dl
118 andb $0x45, %ah
119 cmpb $0x40, %ah // is y == 0 ?
120 je .L11
121
122 cmpb $0x05, %ah // is y == ±inf ?
123 je .L12
124
125 cmpb $0x01, %ah // is y == NaN ?
126 je .L30
127
128 fldt 4(%esp) // x : y
129
130 subl $8,%esp
131 cfi_adjust_cfa_offset (8)
132
133 fxam
134 fnstsw
135 movb %ah, %dh
136 andb $0x45, %ah
137 cmpb $0x40, %ah
138 je .L20 // x is ±0
139
140 cmpb $0x05, %ah
141 je .L15 // x is ±inf
142
143 fxch // y : x
144
145 /* fistpll raises invalid exception for |y| >= 1L<<63. */
146 fld %st // y : y : x
147 fabs // |y| : y : x
148 fcompl MO(p63) // y : x
149 fnstsw
150 sahf
151 jnc .L2
152
153 /* First see whether `y' is a natural number. In this case we
154 can use a more precise algorithm. */
155 fld %st // y : y : x
156 fistpll (%esp) // y : x
157 fildll (%esp) // int(y) : y : x
158 fucomp %st(1) // y : x
159 fnstsw
160 sahf
161 jne .L2
162
163 /* OK, we have an integer value for y. */
164 popl %eax
165 cfi_adjust_cfa_offset (-4)
166 popl %edx
167 cfi_adjust_cfa_offset (-4)
168 orl $0, %edx
169 fstp %st(0) // x
170 jns .L4 // y >= 0, jump
171 fdivrl MO(one) // 1/x (now referred to as x)
172 negl %eax
173 adcl $0, %edx
174 negl %edx
175.L4: fldl MO(one) // 1 : x
176 fxch
177
178.L6: shrdl $1, %edx, %eax
179 jnc .L5
180 fxch
181 fmul %st(1) // x : ST*x
182 fxch
183.L5: fmul %st(0), %st // x*x : ST*x
184 shrl $1, %edx
185 movl %eax, %ecx
186 orl %edx, %ecx
187 jnz .L6
188 fstp %st(0) // ST*x
189 ret
190
191 /* y is ±NAN */
192.L30: fldt 4(%esp) // x : y
193 fldl MO(one) // 1.0 : x : y
194 fucomp %st(1) // x : y
195 fnstsw
196 sahf
197 je .L31
198 fxch // y : x
199.L31: fstp %st(1)
200 ret
201
202 cfi_adjust_cfa_offset (8)
203 .align ALIGNARG(4)
204.L2: /* y is a real number. */
205 fxch // x : y
206 fldl MO(one) // 1.0 : x : y
207 fld %st(1) // x : 1.0 : x : y
208 fsub %st(1) // x-1 : 1.0 : x : y
209 fabs // |x-1| : 1.0 : x : y
210 fcompl MO(limit) // 1.0 : x : y
211 fnstsw
212 fxch // x : 1.0 : y
213 sahf
214 ja .L7
215 fsub %st(1) // x-1 : 1.0 : y
216 fyl2xp1 // log2(x) : y
217 jmp .L8
218
219.L7: fyl2x // log2(x) : y
220.L8: fmul %st(1) // y*log2(x) : y
221 fxam
222 fnstsw
223 andb $0x45, %ah
224 cmpb $0x05, %ah // is y*log2(x) == ±inf ?
225 je .L28
226 fst %st(1) // y*log2(x) : y*log2(x)
227 frndint // int(y*log2(x)) : y*log2(x)
228 fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x))
229 fxch // fract(y*log2(x)) : int(y*log2(x))
230 f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x))
231 faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x))
232 fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
233 addl $8, %esp
234 cfi_adjust_cfa_offset (-8)
235 fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
236 ret
237
238 cfi_adjust_cfa_offset (8)
239.L28: fstp %st(1) // y*log2(x)
240 fldl MO(one) // 1 : y*log2(x)
241 fscale // 2^(y*log2(x)) : y*log2(x)
242 addl $8, %esp
243 cfi_adjust_cfa_offset (-8)
244 fstp %st(1) // 2^(y*log2(x))
245 ret
246
247 // pow(x,±0) = 1
248 .align ALIGNARG(4)
249.L11: fstp %st(0) // pop y
250 fldl MO(one)
251 ret
252
253 // y == ±inf
254 .align ALIGNARG(4)
255.L12: fstp %st(0) // pop y
256 fldt 4(%esp) // x
257 fabs
258 fcompl MO(one) // < 1, == 1, or > 1
259 fnstsw
260 andb $0x45, %ah
261 cmpb $0x45, %ah
262 je .L13 // jump if x is NaN
263
264 cmpb $0x40, %ah
265 je .L14 // jump if |x| == 1
266
267 shlb $1, %ah
268 xorb %ah, %dl
269 andl $2, %edx
270 fldl MOX(inf_zero, %edx, 4)
271 ret
272
273 .align ALIGNARG(4)
274.L14: fldl MO(one)
275 ret
276
277 .align ALIGNARG(4)
278.L13: fldt 4(%esp) // load x == NaN
279 ret
280
281 cfi_adjust_cfa_offset (8)
282 .align ALIGNARG(4)
283 // x is ±inf
284.L15: fstp %st(0) // y
285 testb $2, %dh
286 jz .L16 // jump if x == +inf
287
288 // We must find out whether y is an odd integer.
289 fld %st // y : y
290 fistpll (%esp) // y
291 fildll (%esp) // int(y) : y
292 fucompp // <empty>
293 fnstsw
294 sahf
295 jne .L17
296
297 // OK, the value is an integer, but is it odd?
298 popl %eax
299 cfi_adjust_cfa_offset (-4)
300 popl %edx
301 cfi_adjust_cfa_offset (-4)
302 andb $1, %al
303 jz .L18 // jump if not odd
304 // It's an odd integer.
305 shrl $31, %edx
306 fldl MOX(minf_mzero, %edx, 8)
307 ret
308
309 cfi_adjust_cfa_offset (8)
310 .align ALIGNARG(4)
311.L16: fcompl MO(zero)
312 addl $8, %esp
313 cfi_adjust_cfa_offset (-8)
314 fnstsw
315 shrl $5, %eax
316 andl $8, %eax
317 fldl MOX(inf_zero, %eax, 1)
318 ret
319
320 cfi_adjust_cfa_offset (8)
321 .align ALIGNARG(4)
322.L17: shll $30, %edx // sign bit for y in right position
323 addl $8, %esp
324 cfi_adjust_cfa_offset (-8)
325.L18: shrl $31, %edx
326 fldl MOX(inf_zero, %edx, 8)
327 ret
328
329 cfi_adjust_cfa_offset (8)
330 .align ALIGNARG(4)
331 // x is ±0
332.L20: fstp %st(0) // y
333 testb $2, %dl
334 jz .L21 // y > 0
335
336 // x is ±0 and y is < 0. We must find out whether y is an odd integer.
337 testb $2, %dh
338 jz .L25
339
340 fld %st // y : y
341 fistpll (%esp) // y
342 fildll (%esp) // int(y) : y
343 fucompp // <empty>
344 fnstsw
345 sahf
346 jne .L26
347
348 // OK, the value is an integer, but is it odd?
349 popl %eax
350 cfi_adjust_cfa_offset (-4)
351 popl %edx
352 cfi_adjust_cfa_offset (-4)
353 andb $1, %al
354 jz .L27 // jump if not odd
355 // It's an odd integer.
356 // Raise divide-by-zero exception and get minus infinity value.
357 fldl MO(one)
358 fdivl MO(zero)
359 fchs
360 ret
361
362 cfi_adjust_cfa_offset (8)
363.L25: fstp %st(0)
364.L26: addl $8, %esp
365 cfi_adjust_cfa_offset (-8)
366.L27: // Raise divide-by-zero exception and get infinity value.
367 fldl MO(one)
368 fdivl MO(zero)
369 ret
370
371 cfi_adjust_cfa_offset (8)
372 .align ALIGNARG(4)
373 // x is ±0 and y is > 0. We must find out whether y is an odd integer.
374.L21: testb $2, %dh
375 jz .L22
376
377 fld %st // y : y
378 fistpll (%esp) // y
379 fildll (%esp) // int(y) : y
380 fucompp // <empty>
381 fnstsw
382 sahf
383 jne .L23
384
385 // OK, the value is an integer, but is it odd?
386 popl %eax
387 cfi_adjust_cfa_offset (-4)
388 popl %edx
389 cfi_adjust_cfa_offset (-4)
390 andb $1, %al
391 jz .L24 // jump if not odd
392 // It's an odd integer.
393 fldl MO(mzero)
394 ret
395
396 cfi_adjust_cfa_offset (8)
397.L22: fstp %st(0)
398.L23: addl $8, %esp // Don't use 2 x pop
399 cfi_adjust_cfa_offset (-8)
400.L24: fldl MO(zero)
401 ret
402
403END(RT_NOCRT(powl))
404//END(__ieee754_powl)
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette