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