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