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