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