1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 .file "powl.s" 30 31 / Special cases: 32 / 33 / x ** 0 is 1 34 / 1 ** y is 1 (C99) 35 / x ** NaN is NaN 36 / NaN ** y (except 0) is NaN 37 / x ** 1 is x 38 / +-(|x| > 1) ** +inf is +inf 39 / +-(|x| > 1) ** -inf is +0 40 / +-(|x| < 1) ** +inf is +0 41 / +-(|x| < 1) ** -inf is +inf 42 / (-1) ** +-inf is +1 (C99) 43 / +0 ** +y (except 0, NaN) is +0 44 / -0 ** +y (except 0, NaN, odd int) is +0 45 / +0 ** -y (except 0, NaN) is +inf (z flag) 46 / -0 ** -y (except 0, NaN, odd int) is +inf (z flag) 47 / -0 ** y (odd int) is - (+0 ** x) 48 / +inf ** +y (except 0, NaN) is +inf 49 / +inf ** -y (except 0, NaN) is +0 50 / -inf ** +-y (except 0, NaN) is -0 ** -+y (NO z flag) 51 / x ** -1 is 1/x 52 / x ** 2 is x*x 53 / -x ** y (an integer) is (-1)**(y) * (+x)**(y) 54 / x ** y (x negative & y not integer) is NaN (i flag) 55 56 #include "libm.h" 57 LIBM_ANSI_PRAGMA_WEAK(powl,function) 58 #include "xpg6.h" 59 60 #undef fabs 61 62 .data 63 .align 4 64 negzero: 65 .float -0.0 66 half: 67 .float 0.5 68 one: 69 .float 1.0 70 negone: 71 .float -1.0 72 two: 73 .float 2.0 74 Snan: 75 .long 0x7f800001 76 pinfinity: 77 .long 0x7f800000 78 ninfinity: 79 .long 0xff800000 80 81 82 ENTRY(powl) 83 pushl %ebp 84 movl %esp,%ebp 85 PIC_SETUP(1) 86 87 fldt 8(%ebp) / x 88 fxam / determine class of x 89 fnstsw %ax / store status in %ax 90 movb %ah,%dh / %dh <- condition code of x 91 92 fldt 20(%ebp) / y , x 93 fxam / determine class of y 94 fnstsw %ax / store status in %ax 95 movb %ah,%dl / %dl <- condition code of y 96 97 call .pow_main /// LOCAL 98 PIC_WRAPUP 99 leave 100 ret 101 102 .pow_main: 103 / x ** 0 is 1 104 movb %dl,%cl 105 andb $0x45,%cl 106 cmpb $0x40,%cl / C3=1 C2=0 C1=? C0=0 when +-0 107 jne 1f 108 fstp %st(0) / x 109 fstp %st(0) / stack empty 110 fld1 / 1 111 ret 112 113 1: / y is not zero 114 PIC_G_LOAD(movzwl,__xpg6,eax) 115 andl $_C99SUSv3_pow_treats_Inf_as_an_even_int,%eax 116 cmpl $0,%eax 117 je 1f 118 119 / C99: 1 ** anything is 1 120 fld1 / 1, y, x 121 fucomp %st(2) / y, x 122 fnstsw %ax / store status in %ax 123 sahf / 80387 flags in %ax to 80386 flags 124 jp 1f / so that pow(NaN1,NaN2) returns NaN2 125 jne 1f 126 fstp %st(0) / x 127 ret 128 129 1: 130 / x ** NaN is NaN 131 movb %dl,%cl 132 andb $0x45,%cl 133 cmpb $0x01,%cl / C3=0 C2=0 C1=? C0=1 when +-NaN 134 jne 1f 135 fstp %st(1) / y 136 ret 137 138 1: / y is not NaN 139 / NaN ** y (except 0) is NaN 140 movb %dh,%cl 141 andb $0x45,%cl 142 cmpb $0x01,%cl / C3=0 C2=0 C1=? C0=1 when +-NaN 143 jne 1f 144 fstp %st(0) / x 145 ret 146 147 1: / x is not NaN 148 / x ** 1 is x 149 fcoms PIC_L(one) / y , x 150 fnstsw %ax / store status in %ax 151 sahf / 80387 flags in %ax to 80386 flags 152 jne 1f 153 fstp %st(0) / x 154 ret 155 156 1: / y is not 1 157 / +-(|x| > 1) ** +inf is +inf 158 / +-(|x| > 1) ** -inf is +0 159 / +-(|x| < 1) ** +inf is +0 160 / +-(|x| < 1) ** -inf is +inf 161 / +-(|x| = 1) ** +-inf is NaN 162 movb %dl,%cl 163 andb $0x47,%cl 164 cmpb $0x05,%cl / C3=0 C2=1 C1=0 C0=1 when +inf 165 je .yispinf 166 cmpb $0x07,%cl / C3=0 C2=1 C1=1 C0=1 when -inf 167 je .yisninf 168 169 / +0 ** +y (except 0, NaN) is +0 170 / -0 ** +y (except 0, NaN, odd int) is +0 171 / +0 ** -y (except 0, NaN) is +inf (z flag) 172 / -0 ** -y (except 0, NaN, odd int) is +inf (z flag) 173 / -0 ** y (odd int) is - (+0 ** x) 174 movb %dh,%cl 175 andb $0x47,%cl 176 cmpb $0x40,%cl / C3=1 C2=0 C1=0 C0=0 when +0 177 je .xispzero 178 cmpb $0x42,%cl / C3=1 C2=0 C1=1 C0=0 when -0 179 je .xisnzero 180 181 / +inf ** +y (except 0, NaN) is +inf 182 / +inf ** -y (except 0, NaN) is +0 183 / -inf ** +-y (except 0, NaN) is -0 ** -+y (NO z flag) 184 movb %dh,%cl 185 andb $0x47,%cl 186 cmpb $0x05,%cl / C3=0 C2=1 C1=0 C0=1 when +inf 187 je .xispinf 188 cmpb $0x07,%cl / C3=0 C2=1 C1=1 C0=1 when -inf 189 je .xisninf 190 191 / x ** -1 is 1/x 192 fcoms PIC_L(negone) / y , x 193 fnstsw %ax / store status in %ax 194 sahf / 80387 flags in %ax to 80386 flags 195 jne 1f 196 fld %st(1) / x , y , x 197 fdivrs PIC_L(one) / 1/x , y , x 198 jmp .signok / check for over/underflow 199 200 1: / y is not -1 201 / x ** 2 is x*x 202 fcoms PIC_L(two) / y , x 203 fnstsw %ax / store status in %ax 204 sahf / 80387 flags in %ax to 80386 flags 205 jne 1f 206 fld %st(1) / x , y , x 207 fld %st(0) / x , x , y , x 208 fmulp / x^2 , y , x 209 jmp .signok / check for over/underflow 210 211 1: / y is not 2 212 / x ** 1/2 is sqrt(x) 213 fcoms PIC_L(half) / y , x 214 fnstsw %ax / store status in %ax 215 sahf / 80387 flags in %ax to 80386 flags 216 jne 1f 217 fld %st(1) / x , y , x 218 fsqrt / sqrt(x) , y , x 219 jmp .signok / check for over/underflow 220 221 1: / y is not 1/2 222 / make copies of x & y 223 fld %st(1) / x , y , x 224 fld %st(1) / y , x , y , x 225 226 / -x ** y (an integer) is (-1)**(y) * (+x)**(y) 227 / x ** y (x negative & y not integer) is NaN 228 movl $0,%ecx / track whether to flip sign of result 229 fld %st(1) / x , y , x , y , x 230 ftst / compare %st(0) with 0 231 fnstsw %ax / store status in %ax 232 sahf / 80387 flags in %ax to 80386 flags 233 fstp %st(0) / y , x , y , x 234 ja .merge / x > 0 235 / x < 0 236 call .y_is_int 237 cmpl $0,%ecx 238 jne 1f 239 / x < 0 & y != int so x**y = NaN (i flag) 240 fstp %st(0) / x , y , x 241 fstp %st(0) / y , x 242 fstp %st(0) / x 243 fstp %st(0) / stack empty 244 fldz 245 fdiv %st,%st(0) / 0/0 246 ret 247 248 1: / x < 0 & y = int 249 fxch / x , y , y , x 250 fchs / px = -x , y , y , x 251 fxch / y , px , y , x 252 .merge: 253 / px > 0 254 fxch / px , y , y , x 255 256 / x**y = exp(y*ln(x)) 257 fyl2x / t=y*log2(px) , y , x 258 fld %st(0) / t , t , y , x 259 frndint / [t] , t , y , x 260 fxch / t , [t] , y , x 261 fucom 262 fnstsw %ax / store status in %ax 263 sahf / 80387 flags in %ax to 80386 flags 264 je 1f / t is integral 265 fsub %st(1),%st / t-[t] , [t] , y , x 266 f2xm1 / 2**(t-[t])-1 , [t] , y , x 267 fadds PIC_L(one) / 2**(t-[t]) , [t] , y , x 268 fscale / 2**t = px**y , [t] , y , x 269 jmp 2f 270 1: 271 fstp %st(0) / t=[t] , y , x 272 fld1 / 1 , t , y , x 273 fscale / 1*2**t = x**y , t , y , x 274 2: 275 fstp %st(1) / x**y , y , x 276 cmpl $1,%ecx 277 jne .signok 278 fchs / change sign since x<0 & y=-int 279 .signok: 280 fstp %st(2) / y , x**y 281 fstp %st(0) / x**y 282 ret 283 284 / ------------------------------------------------------------------------ 285 286 .xispinf: 287 ftst / compare %st(0) with 0 288 fnstsw %ax / store status in %ax 289 sahf / 80387 flags in %ax to 80386 flags 290 ja .retpinf / y > 0 291 jmp .retpzero / y < 0 292 293 .xisninf: 294 / -inf ** +-y is -0 ** -+y 295 fchs / -y , x 296 flds PIC_L(negzero) / -0 , -y , x 297 fstp %st(2) / -y , -0 298 jmp .xisnzero 299 300 .yispinf: 301 fld %st(1) / x , y , x 302 fabs / |x| , y , x 303 fcomps PIC_L(one) / y , x 304 fnstsw %ax / store status in %ax 305 sahf / 80387 flags in %ax to 80386 flags 306 je .retponeorinvalid / x == -1 C99 307 ja .retpinf / |x| > 1 308 jmp .retpzero / |x| < 1 309 310 .yisninf: 311 fld %st(1) / x , y , x 312 fabs / |x| , y , x 313 fcomps PIC_L(one) / y , x 314 fnstsw %ax / store status in %ax 315 sahf / 80387 flags in %ax to 80386 flags 316 je .retponeorinvalid / x == -1 C99 317 ja .retpzero / |x| > 1 318 jmp .retpinf / |x| < 1 319 320 .xispzero: 321 / y cannot be 0 or NaN ; stack has y , x 322 ftst / compare %st(0) with 0 323 fnstsw %ax / store status in %ax 324 sahf / 80387 flags in %ax to 80386 flags 325 ja .retpzero / y > 0 326 / x = +0 & y < 0 so x**y = +inf 327 jmp .retpinfzflag / ret +inf & z flag 328 329 .xisnzero: 330 / y cannot be 0 or NaN ; stack has y , x 331 call .y_is_int 332 cmpl $1,%ecx 333 jne 1f / y is not an odd integer 334 / y is an odd integer 335 ftst / compare %st(0) with 0 336 fnstsw %ax / store status in %ax 337 sahf / 80387 flags in %ax to 80386 flags 338 ja .retnzero / y > 0 339 / x = -0 & y < 0 (odd int) return -inf (z flag) 340 / x = -inf & y != 0 or NaN return -inf (NO z flag) 341 movb %dh,%cl 342 andb $0x45,%cl 343 cmpb $0x05,%cl / C3=0 C2=1 C1=? C0=1 when +-inf 344 je 2f 345 fdiv %st,%st(1) / y / x, x (raise z flag) 346 2: 347 fstp %st(0) / x 348 fstp %st(0) / stack empty 349 flds PIC_L(ninfinity) / -inf 350 ret 351 352 1: / y is not an odd integer 353 ftst / compare %st(0) with 0 354 fnstsw %ax / store status in %ax 355 sahf / 80387 flags in %ax to 80386 flags 356 ja .retpzero / y > 0 357 / x = -0 & y < 0 (not odd int) return +inf (z flag) 358 / x = -inf & y not 0 or NaN return +inf (NO z flag) 359 movb %dh,%cl 360 andb $0x45,%cl 361 cmpb $0x05,%cl / C3=0 C2=1 C1=? C0=1 when +-inf 362 jne .retpinfzflag / ret +inf & divide-by-0 flag 363 jmp .retpinf / return +inf (NO z flag) 364 365 .retpzero: 366 fstp %st(0) / x 367 fstp %st(0) / stack empty 368 fldz / +0 369 ret 370 371 .retnzero: 372 fstp %st(0) / x 373 fstp %st(0) / stack empty 374 flds PIC_L(negzero) / -0 375 ret 376 377 .retponeorinvalid: 378 PIC_G_LOAD(movzwl,__xpg6,eax) 379 andl $_C99SUSv3_pow_treats_Inf_as_an_even_int,%eax 380 cmpl $0,%eax 381 je 1f 382 fstp %st(0) / x 383 fstp %st(0) / stack empty 384 fld1 / 1 385 ret 386 387 1: 388 fstp %st(0) / x 389 fstp %st(0) / stack empty 390 flds PIC_L(Snan) / Q NaN (i flag) 391 fwait 392 ret 393 394 .retpinf: 395 fstp %st(0) / x 396 fstp %st(0) / stack empty 397 flds PIC_L(pinfinity) / +inf 398 ret 399 400 .retpinfzflag: 401 fstp %st(0) / x 402 fstp %st(0) / stack empty 403 fldz 404 fdivrs PIC_L(one) / 1/0 405 ret 406 407 / Set %ecx to 2 if y is an even integer, 1 if y is an odd integer, 408 / 0 otherwise. Assume y is not zero. Do not raise inexact or modify 409 / %edx. 410 .y_is_int: 411 movl 28(%ebp),%eax 412 andl $0x7fff,%eax / exponent of y 413 cmpl $0x403f,%eax 414 jae 1f / |y| >= 2^64, an even int 415 cmpl $0x3fff,%eax 416 jb 2f / |y| < 1, can't be an int 417 movl %eax,%ecx 418 subl $0x403e,%ecx 419 negl %ecx / 63 - unbiased exponent of y 420 movl 20(%ebp),%eax 421 bsfl %eax,%eax / index of least sig. 1 bit 422 jne 3f / jump if 1 bit found 423 movl 24(%ebp),%eax 424 bsfl %eax,%eax 425 addl $32,%eax / 32 + index of least sig. 1 bit 426 3: 427 cmpl %ecx,%eax 428 jb 2f 429 ja 1f 430 movl $1,%ecx 431 ret 432 1: 433 movl $2,%ecx 434 ret 435 2: 436 xorl %ecx,%ecx 437 ret 438 .align 4 439 SET_SIZE(powl)