Print this page
5261 libm should stop using synonyms.h
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libm/i386/src/pow.s
+++ new/usr/src/lib/libm/i386/src/pow.s
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
23 23 */
24 24 /*
25 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 26 * Use is subject to license terms.
27 27 */
28 28
29 29 .file "pow.s"
30 30
31 31 / Note: 0^NaN should not signal "invalid" but this implementation
32 32 / does because y is placed on the NPX stack.
33 33
34 34 / Special cases:
35 35 /
36 36 / x ** 0 is 1 _SVID_libm_err if x is 0 or NaN
37 37 / 1 ** y is 1 (C99)
38 38 / x ** NaN is NaN
39 39 / NaN ** y (except 0) is NaN
40 40 / x ** 1 is x
41 41 / +-(|x| > 1) ** +inf is +inf
42 42 / +-(|x| > 1) ** -inf is +0
43 43 / +-(|x| < 1) ** +inf is +0
44 44 / +-(|x| < 1) ** -inf is +inf
45 45 / (-1) ** +-inf is +1 (C99)
46 46 / +0 ** +y (except 0, NaN) is +0
47 47 / -0 ** +y (except 0, NaN, odd int) is +0
48 48 / -0 ** +y (odd int) is -0
49 49 / +-0 ** -y (except 0, NaN) _SVID_libm_err
50 50 / +inf ** +y (except 0, NaN) is +inf
51 51 / +inf ** -y (except 0, NaN) is +0
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
52 52 / -inf ** +-y (except 0, NaN) is -0 ** -+y (NO z flag)
53 53 / x ** -1 is 1/x
54 54 / x ** 2 is x*x
55 55 / -x ** y (an integer) is (-1)**(y) * (+x)**(y)
56 56 / x ** y (x negative & y not integer) _SVID_libm_err
57 57 / if x and y are finite and x**y = 0 _SVID_libm_err (underflow)
58 58 / if x and y are finite and x**y = inf _SVID_libm_err (overflow)
59 59
60 60 #include "libm.h"
61 61 LIBM_ANSI_PRAGMA_WEAK(pow,function)
62 -#include "libm_synonyms.h"
63 62 #include "libm_protos.h"
64 63 #include "xpg6.h"
65 64
66 65 #undef fabs
67 66
68 67 .data
69 68 .align 4
70 69 negzero:
71 70 .float -0.0
72 71 one:
73 72 .float 1.0
74 73 negone:
75 74 .float -1.0
76 75 two:
77 76 .float 2.0
78 77 Snan:
79 78 .long 0x7f800001
80 79 pinfinity:
81 80 .long 0x7f800000
82 81 ninfinity:
83 82 .long 0xff800000
84 83
85 84
86 85 ENTRY(pow)
87 86 pushl %ebp
88 87 movl %esp,%ebp
89 88 PIC_SETUP(1)
90 89
91 90 fldl 8(%ebp) / x
92 91 fxam / determine class of x
93 92 fnstsw %ax / store status in %ax
94 93 movb %ah,%dh / %dh <- condition code of x
95 94
96 95 fldl 16(%ebp) / y , x
97 96 fxam / determine class of y
98 97 fnstsw %ax / store status in %ax
99 98 movb %ah,%dl / %dl <- condition code of y
100 99
101 100 call .pow_main /// LOCAL
102 101 PIC_WRAPUP
103 102 leave
104 103 ret
105 104
106 105 .pow_main:
107 106 / x ** 0 is 1 unless x is 0 or a NaN
108 107 movb %dl,%cl
109 108 andb $0x45,%cl
110 109 cmpb $0x40,%cl / C3=1 C2=0 C1=? C0=0 when +-0
111 110 jne 1f
112 111 movb %dh,%cl
113 112 andb $0x45,%cl
114 113 cmpb $0x40,%cl / C3=1 C2=0 C1=? C0=0 when +-0
115 114 jne 2f
116 115 / 0^0
117 116 pushl $20
118 117 jmp .SVIDerr / SVID error handler
119 118 2:
120 119 cmpb $0x01,%cl /// C3=0 C2=0 C1=? C0=1 when +-NaN
121 120 jne 2f
122 121 / NaN^0
123 122 pushl $42
124 123 jmp .SVIDerr
125 124 2:
126 125 / (not 0 or NaN)^0
127 126 fstp %st(0) / x
128 127 fstp %st(0) / stack empty
129 128 fld1 / 1
130 129 ret
131 130
132 131 1: / y is not zero
133 132 PIC_G_LOAD(movzwl,__xpg6,eax)
134 133 andl $_C99SUSv3_pow_treats_Inf_as_an_even_int,%eax
135 134 cmpl $0,%eax
136 135 je 1f
137 136
138 137 / C99: 1 ** anything is 1
139 138 fld1 / 1, y, x
140 139 fucomp %st(2) / y, x
141 140 fnstsw %ax / store status in %ax
142 141 sahf / 80387 flags in %ax to 80386 flags
143 142 jp 1f / so that pow(NaN1,NaN2) returns NaN2
144 143 jne 1f
145 144 fstp %st(0) / x
146 145 ret
147 146
148 147 1:
149 148 / x ** NaN is NaN
150 149 movb %dl,%cl
151 150 andb $0x45,%cl
152 151 cmpb $0x01,%cl / C3=0 C2=0 C1=? C0=1 when +-NaN
153 152 jne 1f
154 153 fstp %st(1) / y
155 154 ret
156 155
157 156 1: / y is not NaN
158 157 / NaN ** y (except 0) is NaN
159 158 movb %dh,%cl
160 159 andb $0x45,%cl
161 160 cmpb $0x01,%cl / C3=0 C2=0 C1=? C0=1 when +-NaN
162 161 jne 1f
163 162 fstp %st(0) / x
164 163 ret
165 164
166 165 1: / x is not NaN
167 166 / x ** 1 is x
168 167 fcoms PIC_L(one) / y , x
169 168 fnstsw %ax / store status in %ax
170 169 sahf / 80387 flags in %ax to 80386 flags
171 170 jne 1f
172 171 fstp %st(0) / x
173 172 ret
174 173
175 174 1: / y is not 1
176 175 / +-(|x| > 1) ** +inf is +inf
177 176 / +-(|x| > 1) ** -inf is +0
178 177 / +-(|x| < 1) ** +inf is +0
179 178 / +-(|x| < 1) ** -inf is +inf
180 179 / +-(|x| = 1) ** +-inf is NaN
181 180 movb %dl,%cl
182 181 andb $0x47,%cl
183 182 cmpb $0x05,%cl / C3=0 C2=1 C1=0 C0=1 when +inf
184 183 je .yispinf
185 184 cmpb $0x07,%cl / C3=0 C2=1 C1=1 C0=1 when -inf
186 185 je .yisninf
187 186
188 187 / +0 ** +y (except 0, NaN) is +0
189 188 / -0 ** +y (except 0, NaN, odd int) is +0
190 189 / +0 ** -y (except 0, NaN) is +inf (z flag)
191 190 / -0 ** -y (except 0, NaN, odd int) is +inf (z flag)
192 191 / -0 ** y (odd int) is - (+0 ** x)
193 192 movb %dh,%cl
194 193 andb $0x47,%cl
195 194 cmpb $0x40,%cl / C3=1 C2=0 C1=0 C0=0 when +0
196 195 je .xispzero
197 196 cmpb $0x42,%cl / C3=1 C2=0 C1=1 C0=0 when -0
198 197 je .xisnzero
199 198
200 199 / +inf ** +y (except 0, NaN) is +inf
201 200 / +inf ** -y (except 0, NaN) is +0
202 201 / -inf ** +-y (except 0, NaN) is -0 ** -+y (NO z flag)
203 202 movb %dh,%cl
204 203 andb $0x47,%cl
205 204 cmpb $0x05,%cl / C3=0 C2=1 C1=0 C0=1 when +inf
206 205 je .xispinf
207 206 cmpb $0x07,%cl / C3=0 C2=1 C1=1 C0=1 when -inf
208 207 je .xisninf
209 208
210 209 / x ** -1 is 1/x
211 210 fcoms PIC_L(negone) / y , x
212 211 fnstsw %ax / store status in %ax
213 212 sahf / 80387 flags in %ax to 80386 flags
214 213 jne 1f
215 214 fld %st(1) / x , y , x
216 215 fdivrs PIC_L(one) / 1/x , y , x
217 216 jmp .signok / check for over/underflow
218 217
219 218 1: / y is not -1
220 219 / x ** 2 is x*x
221 220 fcoms PIC_L(two) / y , x
222 221 fnstsw %ax / store status in %ax
223 222 sahf / 80387 flags in %ax to 80386 flags
224 223 jne 1f
225 224 fld %st(1) / x , y , x
226 225 fld %st(0) / x , x , y , x
227 226 fmulp / x^2 , y , x
228 227 jmp .signok / check for over/underflow
229 228
230 229 1: / y is not 2
231 230 / make copies of x & y
232 231 fld %st(1) / x , y , x
233 232 fld %st(1) / y , x , y , x
234 233
235 234 / -x ** y (an integer) is (-1)**(y) * (+x)**(y)
236 235 / x ** y (x negative & y not integer) is NaN
237 236 movl $0,%ecx / track whether to flip sign of result
238 237 fld %st(1) / x , y , x , y , x
239 238 ftst / compare %st(0) with 0
240 239 fnstsw %ax / store status in %ax
241 240 sahf / 80387 flags in %ax to 80386 flags
242 241 fstp %st(0) / y , x , y , x
243 242 ja .merge / x > 0
244 243 / x < 0
245 244 call .y_is_int
246 245 cmpl $0,%ecx
247 246 jne 1f
248 247 / x < 0, y is non-integral
249 248 fstp %st(0) / x , y , x
250 249 fstp %st(0) / y , x
251 250 pushl $24
252 251 jmp .SVIDerr / SVID error handler
253 252
254 253 1: / x < 0 & y = int
255 254 fxch / x , y , y , x
256 255 fchs / px = -x , y , y , x
257 256 fxch / y , px , y , x
258 257 .merge:
259 258 / px > 0
260 259 fxch / px , y , y , x
261 260
262 261 / x**y = exp(y*ln(x))
263 262 fyl2x / t=y*log2(px) , y , x
264 263 fld %st(0) / t , t , y , x
265 264 frndint / [t] , t , y , x
266 265 fxch / t , [t] , y , x
267 266 fucom
268 267 fnstsw %ax / store status in %ax
269 268 sahf / 80387 flags in %ax to 80386 flags
270 269 je 1f / t is integral
271 270 fsub %st(1),%st / t-[t] , [t] , y , x
272 271 f2xm1 / 2**(t-[t])-1 , [t] , y , x
273 272 fadds PIC_L(one) / 2**(t-[t]) , [t] , y , x
274 273 fscale / 2**t = px**y , [t] , y , x
275 274 jmp 2f
276 275 1:
277 276 fstp %st(0) / t=[t] , y , x
278 277 fld1 / 1 , t , y , x
279 278 fscale / 1*2**t = x**y , t , y , x
280 279 2:
281 280 fstp %st(1) / x**y , y , x
282 281 cmpl $1,%ecx
283 282 jne .signok
284 283 fchs / change sign since x<0 & y=-int
285 284 .signok:
286 285 subl $8,%esp
287 286 fstpl (%esp) / round to double precision
288 287 fldl (%esp) / place result on NPX stack
289 288 addl $8,%esp
290 289
291 290 fxam / determine class of x**y
292 291 fnstsw %ax / store status in %ax
293 292 andw $0x4500,%ax
294 293 / check for overflow
295 294 cmpw $0x0500,%ax / C0=0 C1=1 C2=? C3=1 then +-inf
296 295 jne 1f
297 296 / x^y overflows
298 297 fstp %st(0) / y , x
299 298 pushl $21
300 299 jmp .SVIDerr
301 300 1:
302 301 / check for underflow
303 302 cmpw $0x4000,%ax / C0=1 C1=0 C2=? C3=0 then +-0
304 303 jne 1f
305 304 / x^y underflows
306 305 fstp %st(0) / y , x
307 306 pushl $22
308 307 jmp .SVIDerr
309 308 1:
310 309 fstp %st(2) / y , x**y
311 310 fstp %st(0) / x**y
312 311 ret
313 312
314 313 / ------------------------------------------------------------------------
315 314
316 315 .xispinf:
317 316 ftst / compare %st(0) with 0
318 317 fnstsw %ax / store status in %ax
319 318 sahf / 80387 flags in %ax to 80386 flags
320 319 ja .retpinf / y > 0
321 320 jmp .retpzero / y < 0
322 321
323 322 .xisninf:
324 323 / -inf ** +-y is -0 ** -+y
325 324 fchs / -y , x
326 325 flds PIC_L(negzero) / -0 , -y , x
327 326 fstp %st(2) / -y , -0
328 327 jmp .xisnzero
329 328
330 329 .yispinf:
331 330 fld %st(1) / x , y , x
332 331 fabs / |x| , y , x
333 332 fcomps PIC_L(one) / y , x
334 333 fnstsw %ax / store status in %ax
335 334 sahf / 80387 flags in %ax to 80386 flags
336 335 je .retponeorinvalid / x == -1 C99
337 336 ja .retpinf / |x| > 1
338 337 jmp .retpzero / |x| < 1
339 338
340 339 .yisninf:
341 340 fld %st(1) / x , y , x
342 341 fabs / |x| , y , x
343 342 fcomps PIC_L(one) / y , x
344 343 fnstsw %ax / store status in %ax
345 344 sahf / 80387 flags in %ax to 80386 flags
346 345 je .retponeorinvalid / x == -1 C99
347 346 ja .retpzero / |x| > 1
348 347 jmp .retpinf / |x| < 1
349 348
350 349 .xispzero:
351 350 / y cannot be 0 or NaN ; stack has y , x
352 351 ftst / compare %st(0) with 0
353 352 fnstsw %ax / store status in %ax
354 353 sahf / 80387 flags in %ax to 80386 flags
355 354 ja .retpzero / y > 0
356 355 / x = +0 & y < 0
357 356 jmp .SVIDzerotoneg
358 357
359 358 .xisnzero:
360 359 / y cannot be 0 or NaN ; stack has y , x
361 360 call .y_is_int
362 361 cmpl $1,%ecx
363 362 jne 1f / y is not an odd integer
364 363 / y is an odd integer
365 364 ftst / compare %st(0) with 0
366 365 fnstsw %ax / store status in %ax
367 366 sahf / 80387 flags in %ax to 80386 flags
368 367 ja .retnzero / y > 0
369 368 / x = -0 & y < 0 (odd int) return -inf (z flag)
370 369 / x = -inf & y != 0 or NaN return -inf (NO z flag)
371 370 movb %dh,%cl
372 371 andb $0x45,%cl
373 372 cmpb $0x05,%cl / C3=0 C2=1 C1=? C0=1 when +-inf
374 373 jne .SVIDzerotoneg
375 374 fstp %st(0) / x
376 375 fstp %st(0) / stack empty
377 376 flds PIC_L(ninfinity) / -inf
378 377 ret
379 378
380 379 1: / y is not an odd integer
381 380 ftst / compare %st(0) with 0
382 381 fnstsw %ax / store status in %ax
383 382 sahf / 80387 flags in %ax to 80386 flags
384 383 ja .retpzero / y > 0
385 384 / x = -0 & y < 0 (not odd int) return +inf (z flag)
386 385 / x = -inf & y not 0 or NaN return +inf (NO z flag)
387 386 movb %dh,%cl
388 387 andb $0x45,%cl
389 388 cmpb $0x05,%cl / C3=0 C2=1 C1=? C0=1 when +-inf
390 389 jne .SVIDzerotoneg
391 390 jmp .retpinf / return +inf (NO z flag)
392 391
393 392 .retpzero:
394 393 fstp %st(0) / x
395 394 fstp %st(0) / stack empty
396 395 fldz / +0
397 396 ret
398 397
399 398 .retnzero:
400 399 fstp %st(0) / x
401 400 fstp %st(0) / stack empty
402 401 flds PIC_L(negzero) / -0
403 402 ret
404 403
405 404 .retponeorinvalid:
406 405 PIC_G_LOAD(movzwl,__xpg6,eax)
407 406 andl $_C99SUSv3_pow_treats_Inf_as_an_even_int,%eax
408 407 cmpl $0,%eax
409 408 je 1f
410 409 fstp %st(0) / x
411 410 fstp %st(0) / stack empty
412 411 fld1 / 1
413 412 ret
414 413
415 414 1:
416 415 fstp %st(0) / x
417 416 fstp %st(0) / stack empty
418 417 flds PIC_L(Snan) / Q NaN (i flag)
419 418 fwait
420 419 ret
421 420
422 421 .retpinf:
423 422 fstp %st(0) / x
424 423 fstp %st(0) / stack empty
425 424 flds PIC_L(pinfinity) / +inf
426 425 ret
427 426
428 427 .SVIDzerotoneg:
429 428 pushl $23
430 429 .SVIDerr:
431 430 / At this point the fp stack contains y , x and the number
432 431 / of the error case has been pushed on the memory stack.
433 432 subl $16,%esp
434 433 fstpl 8(%esp) / push y
435 434 fstpl (%esp) / push x; NPX stack empty
436 435 call PIC_F(_SVID_libm_err) / report result/error according to SVID
437 436 addl $20,%esp
438 437 ret
439 438
440 439 / Set %ecx to 2 if y is an even integer, 1 if y is an odd integer,
441 440 / 0 otherwise. Assume y is not zero. Do not raise inexact or modify
442 441 / %edx.
443 442 .y_is_int:
444 443 movl 20(%ebp),%eax
445 444 andl $0x7fffffff,%eax / |y|
446 445 cmpl $0x43400000,%eax
447 446 jae 1f / |y| >= 2^53, an even int
448 447 cmpl $0x3ff00000,%eax
449 448 jb 2f / |y| < 1, can't be an int
450 449 movl %eax,%ecx
451 450 sarl $20,%ecx
452 451 subl $0x433,%ecx
453 452 negl %ecx / 52 - unbiased exponent of y
454 453 movl 16(%ebp),%eax
455 454 bsfl %eax,%eax / index of least sig. 1 bit
456 455 jne 3f / jump if 1 bit found
457 456 movl 20(%ebp),%eax
458 457 bsfl %eax,%eax
459 458 addl $32,%eax / 32 + index of least sig. 1 bit
460 459 3:
461 460 cmpl %ecx,%eax
462 461 jb 2f
463 462 ja 1f
464 463 movl $1,%ecx
465 464 ret
466 465 1:
467 466 movl $2,%ecx
468 467 ret
469 468 2:
470 469 xorl %ecx,%ecx
471 470 ret
472 471 .align 4
473 472 SET_SIZE(pow)
↓ open down ↓ |
401 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX