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