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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2011, Richard Lowe 29 */ 30 31 /* Functions in this file are duplicated in libm.m4. Keep them in sync */ 32 33 #ifndef _LIBM_INLINES_H 34 #define _LIBM_INLINES_H 35 36 #ifdef __GNUC__ 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 #include <sys/types.h> 43 #include <sys/ieeefp.h> 44 45 #define _LO_WORD(x) ((uint32_t *)&x)[0] 46 #define _HI_WORD(x) ((uint32_t *)&x)[1] 47 #define _HIER_WORD(x) ((uint32_t *)&x)[2] 48 49 extern __inline__ double 50 __ieee754_sqrt(double a) 51 { 52 double ret; 53 54 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a)); 55 return (ret); 56 } 57 58 extern __inline__ double 59 __inline_sqrt(double a) 60 { 61 double ret; 62 63 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a)); 64 return (ret); 65 } 66 67 extern __inline__ double 68 __d_sqrt_(double *a) 69 { 70 double ret; 71 72 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (*a)); 73 return (ret); 74 } 75 76 extern __inline__ float 77 __inline_sqrtf(float a) 78 { 79 float ret; 80 81 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a)); 82 return (ret); 83 } 84 85 extern __inline__ double 86 __inline_rint(double a) 87 { 88 double ret; 89 90 __asm__ __volatile__( 91 "andl $0x7fffffff,%2\n\t" 92 "cmpl $0x43300000,%2\n\t" 93 "jae 1f\n\t" 94 "frndint\n\t" 95 "1: fwait\n\t" 96 : "=t" (ret) 97 : "0" (a), "r" (_HI_WORD(a))); 98 99 return (ret); 100 } 101 102 extern __inline__ short 103 __inline_fstsw(void) 104 { 105 short ret; 106 107 __asm__ __volatile__("fstsw %0\n\t" : "=r" (ret)); 108 return (ret); 109 } 110 111 /* 112 * 00 - 24 bits 113 * 01 - reserved 114 * 10 - 53 bits 115 * 11 - 64 bits 116 */ 117 extern __inline__ int 118 __swapRP(int i) 119 { 120 int ret; 121 uint16_t cw; 122 123 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 124 125 ret = (cw >> 8) & 0x3; 126 cw = (cw & 0xfcff) | ((i & 0x3) << 8); 127 128 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 138 */ 139 extern __inline__ enum fp_direction_type 140 __swap87RD(enum fp_direction_type i) 141 { 142 int ret; 143 uint16_t cw; 144 145 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 146 147 ret = (cw >> 10) & 0x3; 148 cw = (cw & 0xf3ff) | ((i & 0x3) << 10); 149 150 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 151 152 return (ret); 153 } 154 155 extern __inline__ double 156 ceil(double d) 157 { 158 double ret; 159 short rd = __swap87RD(fp_positive); 160 161 __asm__ __volatile__("frndint" : "=t" (ret) : "0" (d)); 162 __swap87RD(rd); 163 164 return (ret); 165 } 166 167 extern __inline__ double 168 copysign(double d1, double d2) 169 { 170 __asm__ __volatile__( 171 "andl $0x7fffffff,%0\n\t" /* %0 <-- hi_32(abs(d)) */ 172 "andl $0x80000000,%1\n\t" /* %1[31] <-- sign_bit(d2) */ 173 "orl %1,%0\n\t" /* %0 <-- hi_32(copysign(x,y)) */ 174 : "+r" (_HI_WORD(d1)) 175 : "r" (_HI_WORD(d2))); 176 177 return (d1); 178 } 179 180 extern __inline__ double 181 fabs(double d) 182 { 183 double ret; 184 185 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d)); 186 return (ret); 187 } 188 189 extern __inline__ float 190 fabsf(float d) 191 { 192 float ret; 193 194 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d)); 195 return (ret); 196 } 197 198 extern __inline__ long double 199 fabsl(long double d) 200 { 201 long double ret; 202 203 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d)); 204 return (ret); 205 } 206 207 extern __inline__ int 208 finite(double d) 209 { 210 int ret; 211 212 __asm__ __volatile__( 213 "notl %1\n\t" 214 "andl $0x7ff00000,%1\n\t" 215 "negl %1\n\t" 216 "shrl $31,%1\n\t" 217 : "=r" (ret) 218 : "0" (_HI_WORD(d))); 219 return (ret); 220 } 221 222 extern __inline__ double 223 floor(double d) 224 { 225 double ret; 226 short rd = __swap87RD(fp_negative); 227 228 __asm__ __volatile__("frndint" : "=t" (ret) : "0" (d)); 229 __swap87RD(rd); 230 231 return (ret); 232 } 233 234 /* 235 * branchless __isnan 236 * ((0x7ff00000-[((lx|-lx)>>31)&1]|ahx)>>31)&1 = 1 iff x is NaN 237 */ 238 extern __inline__ int 239 isnan(double d) 240 { 241 int ret; 242 243 __asm__ __volatile__( 244 "movl %1,%%ecx\n\t" 245 "negl %%ecx\n\t" /* ecx <-- -lo_32(x) */ 246 "orl %%ecx,%1\n\t" 247 "shrl $31,%1\n\t" /* 1 iff lx != 0 */ 248 "andl $0x7fffffff,%2\n\t" /* ecx <-- hi_32(abs(x)) */ 249 "orl %2,%1\n\t" 250 "subl $0x7ff00000,%1\n\t" 251 "negl %1\n\t" 252 "shrl $31,%1\n\t" 253 : "=r" (ret) 254 : "0" (_HI_WORD(d)), "r" (_LO_WORD(d)) 255 : "ecx"); 256 257 return (ret); 258 } 259 260 extern __inline__ int 261 isnanf(float f) 262 { 263 int ret; 264 265 __asm__ __volatile__( 266 "andl $0x7fffffff,%0\n\t" 267 "negl %0\n\t" 268 "addl $0x7f800000,%0\n\t" 269 "shrl $31,%0\n\t" 270 : "=r" (ret) 271 : "0" (f)); 272 273 return (ret); 274 } 275 276 extern __inline__ int 277 isinf(double d) 278 { 279 int ret; 280 281 __asm__ __volatile__( 282 "andl $0x7fffffff,%1\n\t" /* set first bit to 0 */ 283 "cmpl $0x7ff00000,%1\n\t" 284 "pushfl\n\t" 285 "popl %0\n\t" 286 "cmpl $0,%2\n\t" /* is lo_32(x) = 0? */ 287 "pushfl\n\t" 288 "popl %2\n\t" /* bit 6 of ecx <-- lo_32(x) == 0 */ 289 "andl %2,%0\n\t" 290 "andl $0x40,%0\n\t" 291 "shrl $6,%0\n\t" 292 : "=r" (ret) 293 : "0" (_HI_WORD(d)), "r" (_LO_WORD(d))); 294 295 return (ret); 296 } 297 298 extern __inline__ double 299 rint(double a) { 300 double ret; 301 302 __asm__ __volatile__( 303 "andl $0x7fffffff,%2\n\t" 304 "cmpl $0x43300000,%2\n\t" 305 "jae 1f\n\t" 306 "frndint\n\t" 307 "1: fwait\n\t" 308 : "=t" (ret) 309 : "0" (a), "r" (_HI_WORD(a))); 310 311 return (ret); 312 } 313 314 extern __inline__ double 315 scalbn(double d, int n) 316 { 317 double ret, dummy; 318 319 __asm__ __volatile__( 320 "fildl %3\n\t" /* Convert N to extended */ 321 "fxch\n\t" 322 "fscale\n\t" 323 : "=t" (ret), "=u" (dummy) 324 : "0" (d), "m" (n)); 325 326 return (ret); 327 } 328 329 extern __inline__ int 330 signbit(double d) 331 { 332 return (_HI_WORD(d) >> 31); 333 } 334 335 extern __inline__ int 336 signbitf(float f) 337 { 338 return ((*(uint32_t *)&f) >> 31); 339 } 340 341 extern __inline__ double 342 sqrt(double d) 343 { 344 double ret; 345 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (d)); 346 return (ret); 347 } 348 349 extern __inline__ float 350 sqrtf(float f) 351 { 352 float ret; 353 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (f)); 354 return (ret); 355 } 356 357 extern __inline__ long double 358 sqrtl(long double ld) 359 { 360 long double ret; 361 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (ld)); 362 return (ret); 363 } 364 365 extern __inline__ int 366 isnanl(long double ld) 367 { 368 int ret; 369 370 __asm__ __volatile__( 371 "andl $0x00007fff,%1\n\t" 372 "jz 1f\n\t" /* jump if __exp is all 0 */ 373 "xorl $0x00007fff,%1\n\t" 374 "jz 2f\n\t" /* jump if __exp is all 1 */ 375 "testl $0x80000000,%2\n\t" 376 "jz 3f\n\t" /* jump if leading bit is 0 */ 377 "movl $0,%1\n\t" 378 "jmp 1f\n\t" 379 "2:\n\t" /* note that %eax = 0 from before */ 380 "cmpl $0x80000000,%2\n\t" /* what is first half of __significand? */ 381 "jnz 3f\n\t" /* jump if not equal to 0x80000000 */ 382 "testl $0xffffffff,%3\n\t" /* is second half of __significand 0? */ 383 "jnz 3f\n\t" /* jump if not equal to 0 */ 384 "jmp 1f\n\t" 385 "3:\n\t" 386 "movl $1,%1\n\t" 387 "1:\n\t" 388 : "=r" (ret) 389 : "0" (_HIER_WORD(ld)), "r" (_HI_WORD(ld)), "r" (_LO_WORD(ld))); 390 391 return (ret); 392 } 393 394 #ifdef __cplusplus 395 } 396 #endif 397 398 #endif /* __GNUC__ */ 399 400 #endif /* _LIBM_INLINES_H */ | 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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2011, Richard Lowe 29 */ 30 31 /* Functions in this file are duplicated in locallibm.il. Keep them in sync */ 32 33 #ifndef _LIBM_INLINES_H 34 #define _LIBM_INLINES_H 35 36 #ifdef __GNUC__ 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 #include <sys/types.h> 43 #include <sys/ieeefp.h> 44 45 #define _LO_WORD(x) ((uint32_t *)&x)[0] 46 #define _HI_WORD(x) ((uint32_t *)&x)[1] 47 #define _HIER_WORD(x) ((uint32_t *)&x)[2] 48 49 extern __inline__ double 50 __inline_sqrt(double a) 51 { 52 double ret; 53 54 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a) : "cc"); 55 return (ret); 56 } 57 58 extern __inline__ double 59 __ieee754_sqrt(double a) 60 { 61 return (__inline_sqrt(a)); 62 } 63 64 extern __inline__ float 65 __inline_sqrtf(float a) 66 { 67 float ret; 68 69 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a) : "cc"); 70 return (ret); 71 } 72 73 extern __inline__ double 74 __inline_rint(double a) 75 { 76 __asm__ __volatile__( 77 "andl $0x7fffffff,%1\n\t" 78 "cmpl $0x43300000,%1\n\t" 79 "jae 1f\n\t" 80 "frndint\n\t" 81 "1: fwait\n\t" 82 : "+t" (a), "+&r" (_HI_WORD(a)) 83 : 84 : "cc"); 85 86 return (a); 87 } 88 89 /* 90 * 00 - 24 bits 91 * 01 - reserved 92 * 10 - 53 bits 93 * 11 - 64 bits 94 */ 95 extern __inline__ int 96 __swapRP(int i) 97 { 98 int ret; 99 uint16_t cw; 100 101 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 102 103 ret = (cw >> 8) & 0x3; 104 cw = (cw & 0xfcff) | ((i & 0x3) << 8); 105 106 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 116 */ 117 extern __inline__ enum fp_direction_type 118 __swap87RD(enum fp_direction_type i) 119 { 120 int ret; 121 uint16_t cw; 122 123 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 124 125 ret = (cw >> 10) & 0x3; 126 cw = (cw & 0xf3ff) | ((i & 0x3) << 10); 127 128 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 129 130 return (ret); 131 } 132 133 extern __inline__ double 134 ceil(double d) 135 { 136 short rd = __swap87RD(fp_positive); 137 138 __asm__ __volatile__("frndint" : "+t" (d), "+r" (rd) : : "cc"); 139 __swap87RD(rd); 140 141 return (d); 142 } 143 144 extern __inline__ double 145 copysign(double d1, double d2) 146 { 147 __asm__ __volatile__( 148 "andl $0x7fffffff,%0\n\t" /* %0 <-- hi_32(abs(d)) */ 149 "andl $0x80000000,%1\n\t" /* %1[31] <-- sign_bit(d2) */ 150 "orl %1,%0\n\t" /* %0 <-- hi_32(copysign(x,y)) */ 151 : "+&r" (_HI_WORD(d1)), "+r" (_HI_WORD(d2)) 152 : 153 : "cc"); 154 155 return (d1); 156 } 157 158 extern __inline__ double 159 fabs(double d) 160 { 161 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc"); 162 return (d); 163 } 164 165 extern __inline__ float 166 fabsf(float d) 167 { 168 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc"); 169 return (d); 170 } 171 172 extern __inline__ long double 173 fabsl(long double d) 174 { 175 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc"); 176 return (d); 177 } 178 179 extern __inline__ int 180 finite(double d) 181 { 182 int ret = _HI_WORD(d); 183 184 __asm__ __volatile__( 185 "notl %0\n\t" 186 "andl $0x7ff00000,%0\n\t" 187 "negl %0\n\t" 188 "shrl $31,%0\n\t" 189 : "+r" (ret) 190 : 191 : "cc"); 192 return (ret); 193 } 194 195 extern __inline__ double 196 floor(double d) 197 { 198 short rd = __swap87RD(fp_negative); 199 200 __asm__ __volatile__("frndint" : "+t" (d), "+r" (rd) : : "cc"); 201 __swap87RD(rd); 202 203 return (d); 204 } 205 206 extern __inline__ int 207 isnanf(float f) 208 { 209 __asm__ __volatile__( 210 "andl $0x7fffffff,%0\n\t" 211 "negl %0\n\t" 212 "addl $0x7f800000,%0\n\t" 213 "shrl $31,%0\n\t" 214 : "+r" (f) 215 : 216 : "cc"); 217 218 return (f); 219 } 220 221 extern __inline__ double 222 rint(double a) { 223 return (__inline_rint(a)); 224 } 225 226 extern __inline__ double 227 scalbn(double d, int n) 228 { 229 double dummy; 230 231 __asm__ __volatile__( 232 "fildl %2\n\t" /* Convert N to extended */ 233 "fxch\n\t" 234 "fscale\n\t" 235 : "+t" (d), "=u" (dummy) 236 : "m" (n) 237 : "cc"); 238 239 return (d); 240 } 241 242 extern __inline__ int 243 signbit(double d) 244 { 245 return (_HI_WORD(d) >> 31); 246 } 247 248 extern __inline__ int 249 signbitf(float f) 250 { 251 return ((*(uint32_t *)&f) >> 31); 252 } 253 254 extern __inline__ double 255 sqrt(double d) 256 { 257 return (__inline_sqrt(d)); 258 } 259 260 extern __inline__ float 261 sqrtf(float f) 262 { 263 return (__inline_sqrtf(f)); 264 } 265 266 extern __inline__ long double 267 sqrtl(long double ld) 268 { 269 __asm__ __volatile__("fsqrt" : "+t" (ld) : : "cc"); 270 return (ld); 271 } 272 273 extern __inline__ int 274 isnanl(long double ld) 275 { 276 int ret = _HIER_WORD(ld); 277 278 __asm__ __volatile__( 279 "andl $0x00007fff,%0\n\t" 280 "jz 1f\n\t" /* jump if exp is all 0 */ 281 "xorl $0x00007fff,%0\n\t" 282 "jz 2f\n\t" /* jump if exp is all 1 */ 283 "testl $0x80000000,%1\n\t" 284 "jz 3f\n\t" /* jump if leading bit is 0 */ 285 "movl $0,%0\n\t" 286 "jmp 1f\n\t" 287 "2:\n\t" /* note that %0 = 0 from before */ 288 "cmpl $0x80000000,%1\n\t" /* what is first half of significand? */ 289 "jnz 3f\n\t" /* jump if not equal to 0x80000000 */ 290 "testl $0xffffffff,%2\n\t" /* is second half of significand 0? */ 291 "jnz 3f\n\t" /* jump if not equal to 0 */ 292 "jmp 1f\n\t" 293 "3:\n\t" 294 "movl $1,%0\n\t" 295 "1:\n\t" 296 : "+&r" (ret) 297 : "r" (_HI_WORD(ld)), "r" (_LO_WORD(ld)) 298 : "cc"); 299 300 return (ret); 301 } 302 303 #ifdef __cplusplus 304 } 305 #endif 306 307 #endif /* __GNUC__ */ 308 309 #endif /* _LIBM_INLINES_H */ |