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