Print this page




  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 */