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 #include <sys/types.h>
  39 #include <sys/ieeefp.h>
  40 
  41 #ifdef __cplusplus
  42 extern "C" {
  43 #endif
  44 
  45 extern __inline__ double
  46 __inline_sqrt(double d)
  47 {
  48         double ret;
  49 
  50         __asm__ __volatile__("fsqrtd %0,%0\n\t" : "=e" (ret) : "0" (d));
  51         return (ret);
  52 }
  53 
  54 extern __inline__ float
  55 __inline_sqrtf(float f)
  56 {
  57         float ret;
  58 
  59         __asm__ __volatile__("fsqrts %0,%0\n\t" : "=f" (ret) : "0" (f));
  60         return (ret);
  61 }
  62 
  63 extern __inline__ enum fp_class_type
  64 fp_classf(float f)
  65 {
  66         enum fp_class_type ret;

  67 

  68         __asm__ __volatile__(
  69             "sethi  %%hi(0x80000000),%%o2\n\t"
  70             "andncc %0,%%o2,%0\n\t"
  71             "bne    1f\n\t"
  72             "nop\n\t"
  73             "mov    0,%0\n\t"
  74             "ba 2f\n\t"             /* x is 0 */
  75             "nop\n\t"
  76             "1:\n\t"
  77             "sethi  %%hi(0x7f800000),%%o2\n\t"
  78             "andcc  %0,%%o2,%%g0\n\t"
  79             "bne    1f\n\t"
  80             "nop\n\t"
  81             "mov    1,%0\n\t"
  82             "ba     2f\n\t"         /* x is subnormal */
  83             "nop\n\t"
  84             "1:\n\t"
  85             "cmp    %0,%%o2\n\t"
  86             "bge    1f\n\t"
  87             "nop\n\t"
  88             "mov    2,%0\n\t"
  89             "ba     2f\n\t"         /* x is normal */
  90             "nop\n\t"
  91             "1:\n\t"
  92             "bg     1f\n\t"
  93             "nop\n\t"
  94             "mov    3,%0\n\t"
  95             "ba     2f\n\t"         /* x is __infinity */
  96             "nop\n\t"
  97             "1:\n\t"
  98             "sethi  %%hi(0x00400000),%%o2\n\t"
  99             "andcc  %0,%%o2,%%g0\n\t"
 100             "mov    4,%0\n\t"       /* x is quiet NaN */
 101             "bne    2f\n\t"
 102             "nop\n\t"
 103             "mov    5,%0\n\t"       /* x is signaling NaN */
 104             "2:\n\t"
 105             : "=r" (ret)
 106             : "0" (f)
 107             : "o2");
 108         return (ret);
 109 }
 110 
 111 #define _HI_WORD(x)     ((uint32_t *)&x)[0]
 112 #define _LO_WORD(x)     ((uint32_t *)&x)[1]
 113 
 114 extern __inline__ enum fp_class_type
 115 fp_class(double d)
 116 {
 117         enum fp_class_type ret;

 118 
 119         __asm__ __volatile__(
 120             "sethi %%hi(0x80000000),%%o2\n\t" /* o2 gets 80000000 */
 121             "andn  %0,%%o2,%0\n\t"            /* o0-o1 gets abs(x) */
 122             "orcc  %0,%2,%%g0\n\t"            /* set cc as x is zero/nonzero */
 123             "bne   1f\n\t"                    /* branch if x is nonzero */
 124             "nop\n\t"
 125             "mov   0,%0\n\t"
 126             "ba    2f\n\t"                    /* x is 0 */
 127             "nop\n\t"
 128             "1:\n\t"
 129             "sethi %%hi(0x7ff00000),%%o2\n\t" /* o2 gets 7ff00000 */
 130             "andcc %0,%%o2,%%g0\n\t"          /* cc set by __exp field of x */
 131             "bne   1f\n\t"                    /* branch if normal or max __exp */
 132             "nop\n\t"
 133             "mov   1,%0\n\t"
 134             "ba    2f\n\t"                    /* x is subnormal */
 135             "nop\n\t"
 136             "1:\n\t"
 137             "cmp   %0,%%o2\n\t"
 138             "bge   1f\n\t"                    /* branch if x is max __exp */
 139             "nop\n\t"
 140             "mov   2,%0\n\t"
 141             "ba    2f\n\t"                    /* x is normal */
 142             "nop\n\t"
 143             "1:\n\t"
 144             "andn  %0,%%o2,%0\n\t"            /* o0 gets msw __significand field */
 145             "orcc  %0,%2,%%g0\n\t"            /* set cc by OR __significand */
 146             "bne   1f\n\t"                    /* Branch if __nan */
 147             "nop\n\t"
 148             "mov   3,%0\n\t"
 149             "ba    2f\n\t"                    /* x is __infinity */
 150             "nop\n\t"
 151             "1:\n\t"
 152             "sethi %%hi(0x00080000),%%o2\n\t"
 153             "andcc %0,%%o2,%%g0\n\t"          /* set cc by quiet/sig bit */
 154             "be    1f\n\t"                    /* Branch if signaling */
 155             "nop\n\t"
 156             "mov   4,%0\n\t"                  /* x is quiet NaN */
 157             "ba    2f\n\t"
 158             "nop\n\t"
 159             "1:\n\t"
 160             "mov   5,%0\n\t"                  /* x is signaling NaN */
 161             "2:\n\t"
 162             : "=r" (ret)
 163             : "0" (_HI_WORD(d)), "r" (_LO_WORD(d))
 164             : "o2");
 165 
 166         return (ret);
 167 }
 168 
 169 extern __inline__ int
 170 __swapEX(int i)
 171 {
 172         int ret;
 173         uint32_t fsr;

 174 
 175         __asm__ __volatile__(
 176             "and  %0,0x1f,%%o1\n\t"
 177             "sll  %%o1,5,%%o1\n\t"    /*  input to aexc bit location */
 178             ".volatile\n\t"
 179             "st   %%fsr,%2\n\t"
 180             "ld   %2,%0\n\t"          /* = fsr */
 181             "andn %0,0x3e0,%%o2\n\t"
 182             "or   %%o1,%%o2,%%o1\n\t" /* o1 = new fsr */
 183             "st   %%o1,%2\n\t"
 184             "ld   %2,%%fsr\n\t"
 185             "srl  %0,5,%0\n\t"
 186             "and  %0,0x1f,%0\n\t"
 187             ".nonvolatile\n\t"
 188             : "=r" (ret)
 189             : "0" (i), "m" (fsr)
 190             : "o1", "o2");
 191 
 192         return (ret);
 193 }
 194 
 195 /*
 196  * On the SPARC, __swapRP is a no-op; always return 0 for backward
 197  * compatibility
 198  */
 199 /* ARGSUSED */
 200 extern __inline__ enum fp_precision_type
 201 __swapRP(enum fp_precision_type i)
 202 {
 203         return (0);
 204 }
 205 
 206 extern __inline__ enum fp_direction_type
 207 __swapRD(enum fp_direction_type d)
 208 {
 209         enum fp_direction_type ret;
 210         uint32_t fsr;

 211 
 212         __asm__ __volatile__(
 213             "and  %0,0x3,%0\n\t"
 214             "sll  %0,30,%%o1\n\t"      /* input to RD bit location */
 215             ".volatile\n\t"
 216             "st   %%fsr,%2\n\t"
 217             "ld   %2,%0\n\t"           /* o0 = fsr */
 218             "set  0xc0000000,%%o4\n\t" /* mask of rounding direction bits */
 219             "andn %0,%%o4,%%o2\n\t"
 220             "or   %%o1,%%o2,%%o1\n\t"  /* o1 = new fsr */
 221             "st   %%o1,%2\n\t"
 222             "ld   %2,%%fsr\n\t"
 223             "srl  %0,30,%0\n\t"
 224             "and  %0,0x3,%0\n\t"
 225             ".nonvolatile\n\t"
 226             : "=r" (ret)
 227             : "0" (d), "m" (fsr)
 228             : "o1", "o2", "o4");
 229 
 230         return (ret);
 231 }
 232 
 233 extern __inline__ int
 234 __swapTE(int i)
 235 {
 236         int ret;
 237         uint32_t fsr;
 238         
 239         __asm__ __volatile__(
 240             "and  %0,0x1f,%0\n\t"
 241             "sll  %0,23,%%o1\n\t"      /* input to TEM bit location */
 242             ".volatile\n\t"
 243             "st   %%fsr,%2\n\t"
 244             "ld   %2,%0\n\t"           /* o0 = fsr */
 245             "set  0x0f800000,%%o4\n\t" /* mask of TEM (Trap Enable Mode bits) */
 246             "andn %0,%%o4,%%o2\n\t"       
 247             "or   %%o1,%%o2,%%o1\n\t"  /* o1 = new fsr */
 248             "st   %%o1,%2\n\t"
 249             "ld   %2,%%fsr\n\t"
 250             "srl  %0,23,%0\n\t"
 251             "and  %0,0x1f,%0\n\t"
 252             ".nonvolatile\n\t"
 253             : "=r" (ret)
 254             : "0" (i), "m" (fsr)
 255             : "o1", "o2", "o4");
 256 
 257         return (ret);
 258 }
 259 
 260 extern __inline__ double
 261 sqrt(double d)
 262 {
 263     double ret;
 264 
 265     __asm__ __volatile__("fsqrtd %0,%0\n\t" : "=f" (ret) : "0" (d));
 266     return (ret);
 267 }
 268 
 269 extern __inline__ float
 270 sqrtf(float f)
 271 {
 272     float ret;
 273 
 274     __asm__ __volatile__("fsqrts %0,%0\n\t" : "=f" (ret) : "0" (f));
 275     return (ret);
 276 }
 277 
 278 extern __inline__ double
 279 fabs(double d)
 280 {
 281     double ret;
 282 
 283     __asm__ __volatile__("fabsd %0,%0\n\t" : "=e" (ret) : "0" (d));
 284     return (ret);
 285 }
 286 
 287 extern __inline__ float
 288 fabsf(float f)
 289 {
 290     float ret;
 291 
 292     __asm__ __volatile__("fabss %0,%0\n\t" : "=f" (ret) : "0" (f));
 293     return (ret);
 294 }
 295 
 296 #ifdef __cplusplus
 297 }
 298 #endif
 299 
 300 #endif  /* __GNUC */
 301 
 302 #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 #include <sys/types.h>
  39 #include <sys/ieeefp.h>
  40 
  41 #ifdef __cplusplus
  42 extern "C" {
  43 #endif
  44 
  45 extern __inline__ double
  46 __inline_sqrt(double d)
  47 {
  48         double ret;
  49 
  50         __asm__ __volatile__("fsqrtd %1,%0\n\t" : "=e" (ret) : "e" (d));
  51         return (ret);
  52 }
  53 
  54 extern __inline__ float
  55 __inline_sqrtf(float f)
  56 {
  57         float ret;
  58 
  59         __asm__ __volatile__("fsqrts %1,%0\n\t" : "=f" (ret) : "f" (f));
  60         return (ret);
  61 }
  62 
  63 extern __inline__ enum fp_class_type
  64 fp_classf(float f)
  65 {
  66         enum fp_class_type ret;
  67         uint32_t tmp;
  68 
  69         /* XXX: Separate input and output */
  70         __asm__ __volatile__(
  71             "sethi  %%hi(0x80000000),%1\n\t"
  72             "andncc %3,%1,%0\n\t"
  73             "bne    1f\n\t"
  74             "nop\n\t"
  75             "mov    0,%0\n\t"
  76             "ba 2f\n\t"         /* x is 0 */
  77             "nop\n\t"
  78             "1:\n\t"
  79             "sethi  %%hi(0x7f800000),%1\n\t"
  80             "andcc  %0,%1,%%g0\n\t"
  81             "bne    1f\n\t"
  82             "nop\n\t"
  83             "mov    1,%0\n\t"
  84             "ba     2f\n\t"     /* x is subnormal */
  85             "nop\n\t"
  86             "1:\n\t"
  87             "cmp    %0,%1\n\t"
  88             "bge    1f\n\t"
  89             "nop\n\t"
  90             "mov    2,%0\n\t"
  91             "ba     2f\n\t"     /* x is normal */
  92             "nop\n\t"
  93             "1:\n\t"
  94             "bg     1f\n\t"
  95             "nop\n\t"
  96             "mov    3,%0\n\t"
  97             "ba     2f\n\t"     /* x is __infinity */
  98             "nop\n\t"
  99             "1:\n\t"
 100             "sethi  %%hi(0x00400000),%1\n\t"
 101             "andcc  %0,%1,%%g0\n\t"
 102             "mov    4,%0\n\t"   /* x is quiet NaN */
 103             "bne    2f\n\t"
 104             "nop\n\t"
 105             "mov    5,%0\n\t"   /* x is signaling NaN */
 106             "2:\n\t"
 107             : "+r" (ret), "=&r" (tmp)
 108             : "r" (f)
 109             : "cc");
 110         return (ret);
 111 }
 112 
 113 #define _HI_WORD(x)     ((uint32_t *)&x)[0]
 114 #define _LO_WORD(x)     ((uint32_t *)&x)[1]
 115 
 116 extern __inline__ enum fp_class_type
 117 fp_class(double d)
 118 {
 119         enum fp_class_type ret;
 120         uint32_t tmp;
 121 
 122         __asm__ __volatile__(
 123             "sethi %%hi(0x80000000),%1\n\t"     /* %1 gets 80000000 */
 124             "andn  %2,%1,%0\n\t"                /* %2-%0 gets abs(x) */
 125             "orcc  %0,%3,%%g0\n\t"              /* set cc as x is zero/nonzero */
 126             "bne   1f\n\t"                      /* branch if x is nonzero */
 127             "nop\n\t"
 128             "mov   0,%0\n\t"
 129             "ba    2f\n\t"                      /* x is 0 */
 130             "nop\n\t"
 131             "1:\n\t"
 132             "sethi %%hi(0x7ff00000),%1\n\t"     /* %1 gets 7ff00000 */
 133             "andcc %0,%1,%%g0\n\t"              /* cc set by __exp field of x */
 134             "bne   1f\n\t"                      /* branch if normal or max __exp */
 135             "nop\n\t"
 136             "mov   1,%0\n\t"
 137             "ba    2f\n\t"                      /* x is subnormal */
 138             "nop\n\t"
 139             "1:\n\t"
 140             "cmp   %0,%1\n\t"
 141             "bge   1f\n\t"                      /* branch if x is max __exp */
 142             "nop\n\t"
 143             "mov   2,%0\n\t"
 144             "ba    2f\n\t"                      /* x is normal */
 145             "nop\n\t"
 146             "1:\n\t"
 147             "andn  %0,%1,%0\n\t"                /* o0 gets msw __significand field */
 148             "orcc  %0,%3,%%g0\n\t"              /* set cc by OR __significand */
 149             "bne   1f\n\t"                      /* Branch if __nan */
 150             "nop\n\t"
 151             "mov   3,%0\n\t"
 152             "ba    2f\n\t"                      /* x is __infinity */
 153             "nop\n\t"
 154             "1:\n\t"
 155             "sethi %%hi(0x00080000),%1\n\t"
 156             "andcc %0,%1,%%g0\n\t"              /* set cc by quiet/sig bit */
 157             "be    1f\n\t"                      /* Branch if signaling */
 158             "nop\n\t"
 159             "mov   4,%0\n\t"                    /* x is quiet NaN */
 160             "ba    2f\n\t"
 161             "nop\n\t"
 162             "1:\n\t"
 163             "mov   5,%0\n\t"                    /* x is signaling NaN */
 164             "2:\n\t"
 165             : "=&r" (ret), "=&r" (tmp)
 166             : "r" (_HI_WORD(d)), "r" (_LO_WORD(d))
 167             : "cc");
 168 
 169         return (ret);
 170 }
 171 
 172 extern __inline__ int
 173 __swapEX(int i)
 174 {
 175         int ret;
 176         uint32_t fsr;
 177         uint32_t tmp1, tmp2;
 178 
 179         __asm__ __volatile__(
 180             "and  %4,0x1f,%3\n\t"
 181             "sll  %3,5,%3\n\t"  /* shift input to aexc bit location */
 182             ".volatile\n\t"
 183             "st   %%fsr,%1\n\t"
 184             "ld   %1,%0\n\t"    /* %0 = fsr */
 185             "andn %0,0x3e0,%4\n\t"
 186             "or   %3,%4,%3\n\t" /* %3 = new fsr */
 187             "st   %3,%1\n\t"
 188             "ld   %1,%%fsr\n\t"
 189             "srl  %0,5,%0\n\t"
 190             "and  %0,0x1f,%0\n\t"
 191             ".nonvolatile\n\t"
 192             : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
 193             : "r" (i)
 194             : "cc");
 195 
 196         return (ret);
 197 }
 198 
 199 /*
 200  * On the SPARC, __swapRP is a no-op; always return 0 for backward
 201  * compatibility
 202  */
 203 /* ARGSUSED */
 204 extern __inline__ enum fp_precision_type
 205 __swapRP(enum fp_precision_type i)
 206 {
 207         return (0);
 208 }
 209 
 210 extern __inline__ enum fp_direction_type
 211 __swapRD(enum fp_direction_type d)
 212 {
 213         enum fp_direction_type ret;
 214         uint32_t fsr;
 215         uint32_t tmp1, tmp2, tmp3;
 216 
 217         __asm__ __volatile__(
 218             "and  %5,0x3,%0\n\t"
 219             "sll  %0,30,%2\n\t"         /* shift input to RD bit location */
 220             ".volatile\n\t"
 221             "st   %%fsr,%1\n\t"
 222             "ld   %1,%0\n\t"            /* %0 = fsr */
 223             "set  0xc0000000,%4\n\t"    /* mask of rounding direction bits */
 224             "andn %0,%4,%3\n\t"
 225             "or   %2,%3,%2\n\t"         /* %2 = new fsr */
 226             "st   %2,%1\n\t"
 227             "ld   %1,%%fsr\n\t"
 228             "srl  %0,30,%0\n\t"
 229             "and  %0,0x3,%0\n\t"
 230             ".nonvolatile\n\t"
 231             : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
 232             : "r" (d)
 233             : "cc");
 234 
 235         return (ret);
 236 }
 237 
 238 extern __inline__ int
 239 __swapTE(int i)
 240 {
 241         int ret;
 242         uint32_t fsr, tmp1, tmp2;
 243 
 244         __asm__ __volatile__(
 245             "and  %4,0x1f,%0\n\t"
 246             "sll  %0,23,%2\n\t"         /* shift input to TEM bit location */
 247             ".volatile\n\t"
 248             "st   %%fsr,%1\n\t"
 249             "ld   %1,%0\n\t"            /* %0 = fsr */
 250             "set  0x0f800000,%%o4\n\t"  /* mask of TEM (Trap Enable Mode bits) */
 251             "andn %0,%%o4,%3\n\t"
 252             "or   %2,%3,%2\n\t"         /* %2 = new fsr */
 253             "st   %2,%1\n\t"
 254             "ld   %1,%%fsr\n\t"
 255             "srl  %0,23,%0\n\t"
 256             "and  %0,0x1f,%0\n\t"
 257             ".nonvolatile\n\t"
 258             : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
 259             : "r" (i)
 260             : "cc");
 261 
 262         return (ret);
 263 }
 264 
 265 extern __inline__ double
 266 sqrt(double d)
 267 {
 268         return (__inline_sqrt(d));



 269 }
 270 
 271 extern __inline__ float
 272 sqrtf(float f)
 273 {
 274         return (__inline_sqrtf(f));



 275 }
 276 
 277 extern __inline__ double
 278 fabs(double d)
 279 {
 280         double ret;
 281 
 282         __asm__ __volatile__("fabsd %1,%0\n\t" : "=e" (ret) : "e" (d));
 283         return (ret);
 284 }
 285 
 286 extern __inline__ float
 287 fabsf(float f)
 288 {
 289         float ret;
 290 
 291         __asm__ __volatile__("fabss %1,%0\n\t" : "=f" (ret) : "f" (f));
 292         return (ret);
 293 }
 294 
 295 #ifdef __cplusplus
 296 }
 297 #endif
 298 
 299 #endif  /* __GNUC */
 300 
 301 #endif /* _LIBM_INLINES_H */