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__ enum fp_class_type
  46 fp_classf(float f)
  47 {
  48         enum fp_class_type ret;
  49         int fint;                   /* scratch for f as int */

  50 
  51         __asm__ __volatile__(
  52             "fabss  %2,%2\n\t"
  53             "st     %2,%1\n\t"
  54             "ld     %1,%0\n\t"
  55             "orcc   %%g0,%0,%%g0\n\t"
  56             "be,pn  %%icc,2f\n\t"
  57             "nop\n\t"
  58             "1:\n\t"
  59             "sethi  %%hi(0x7f800000),%%o1\n\t"
  60             "andcc  %0,%%o1,%%g0\n\t"
  61             "bne,pt %%icc,1f\n\t"
  62             "nop\n\t"
  63             "or     %%g0,1,%0\n\t"
  64             "ba     2f\n\t"
  65             "nop\n\t"
  66             "1:\n\t"
  67             "subcc  %0,%%o1,%%g0\n\t"
  68             "bge,pn %%icc,1f\n\t"
  69             "nop\n\t"
  70             "or     %%g0,2,%0\n\t"
  71             "ba     2f\n\t"
  72             "nop\n\t"
  73             "1:\n\t"
  74             "bg,pn  %%icc,1f\n\t"
  75             "nop\n\t"
  76             "or     %%g0,3,%0\n\t"
  77             "ba     2f\n\t"
  78             "nop\n\t"
  79             "1:\n\t"
  80             "sethi  %%hi(0x00400000),%%o1\n\t"
  81             "andcc  %0,%%o1,%%g0\n\t"
  82             "or     %%g0,4,%0\n\t"
  83             "bne,pt %%icc,2f\n\t"
  84             "nop\n\t"
  85             "or     %%g0,5,%0\n\t"
  86             "2:\n\t"
  87             : "=r" (ret), "=m" (fint)
  88             : "f" (f)
  89             : "o1");
  90 
  91     return (ret);
  92 }
  93 
  94 extern __inline__ enum fp_class_type
  95 fp_class(double d)
  96 {
  97         enum fp_class_type ret;
  98         uint64_t dint;          /* Scratch for d-as-long */

  99 
 100         __asm__ __volatile__(
 101             "fabsd  %2,%2\n\t"
 102             "std    %2,%1\n\t"
 103             "ldx    %1,%0\n\t"
 104             "orcc   %%g0,%0,%%g0\n\t"
 105             "be,pn  %%xcc,2f\n\t"
 106             "nop\n\t"
 107             "sethi  %%hi(0x7ff00000),%%o1\n\t"
 108             "sllx   %%o1,32,%%o1\n\t"
 109             "andcc  %0,%%o1,%%g0\n\t"
 110             "bne,pt %%xcc,1f\n\t"
 111             "nop\n\t"
 112             "or     %%g0,1,%0\n\t"
 113             "ba     2f\n\t"
 114             "nop\n\t"
 115             "1:\n\t"
 116             "subcc  %0,%%o1,%%g0\n\t"
 117             "bge,pn %%xcc,1f\n\t"
 118             "nop\n\t"
 119             "or     %%g0,2,%0\n\t"
 120             "ba     2f\n\t"
 121             "nop\n\t"
 122             "1:\n\t"
 123             "andncc %0,%%o1,%0\n\t"
 124             "bne,pn %%xcc,1f\n\t"
 125             "nop\n\t"
 126             "or     %%g0,3,%0\n\t"
 127             "ba     2f\n\t"
 128             "nop\n\t"
 129             "1:\n\t"
 130             "sethi  %%hi(0x00080000),%%o1\n\t"
 131             "sllx   %%o1,32,%%o1\n\t"
 132             "andcc  %0,%%o1,%%g0\n\t"
 133             "or     %%g0,4,%0\n\t"
 134             "bne,pt %%xcc,2f\n\t"
 135             "nop\n\t"
 136             "or     %%g0,5,%0\n\t"
 137             "2:\n\t"
 138             : "=r" (ret), "=m" (dint)
 139             : "e" (d)
 140             : "o1");
 141 
 142         return (ret);
 143 }
 144 
 145 extern __inline__ float
 146 __inline_sqrtf(float f)
 147 {
 148         float ret;
 149 
 150         __asm__ __volatile__("fsqrts %0,%0\n\t" : "=f" (ret) : "f" (f));
 151         return (ret);
 152 }
 153 
 154 extern __inline__ double
 155 __inline_sqrt(double d)
 156 {
 157         double ret;
 158 
 159         __asm__ __volatile__("fsqrtd %0,%0\n\t" : "=f" (ret) : "0" (d));
 160         return (ret);
 161 }
 162 
 163 extern __inline__ int
 164 __swapEX(int i)
 165 {
 166         int ret;
 167         uint32_t fsr;

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

 205 
 206         __asm__ __volatile__(
 207             "and   %0,0x3,%0\n\t"
 208             "sll   %0,30,%%o1\n\t"            /* input to RD bit location */
 209             ".volatile\n\t"
 210             "st    %%fsr,%2\n\t"
 211             "ld    %2,%0\n\t"                 /* o0 = fsr */
 212             "sethi %%hi(0xc0000000),%%o4\n\t" /* mask of rounding direction bits */
 213             "andn  %0,%%o4,%%o2\n\t"
 214             "or    %%o1,%%o2,%%o1\n\t"        /* o1 = new fsr */
 215             "st    %%o1,%2\n\t"
 216             "ld    %2,%%fsr\n\t"

 217             "srl   %0,30,%0\n\t"
 218             "and   %0,0x3,%0\n\t"
 219             ".nonvolatile\n\t"
 220             : "=r" (ret)
 221             : "0" (d), "m" (fsr)
 222             : "o1", "o2", "o4");
 223 
 224         return (ret);
 225 }
 226 
 227 extern __inline__ int
 228 __swapTE(int i)
 229 {
 230         int ret;
 231         uint32_t fsr;

 232         
 233         __asm__ __volatile__(
 234             "and   %0,0x1f,%0\n\t"
 235             "sll   %0,23,%%o1\n\t"            /* input to TEM bit location */
 236             ".volatile\n\t"
 237             "st    %%fsr,%2\n\t"
 238             "ld    %2,%0\n\t"                 /* o0 = fsr */
 239             "sethi %%hi(0x0f800000),%%o4\n\t" /* mask of TEM (Trap Enable Mode bits) */
 240             "andn  %0,%%o4,%%o2\n\t"      
 241             "or    %%o1,%%o2,%%o1\n\t"        /* o1 = new fsr */
 242             "st    %%o1,%2\n\t"
 243             "ld    %2,%%fsr\n\t"

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



 266 }
 267 
 268 extern __inline__ float
 269 sqrtf(float f)
 270 {
 271         return (__inline_sqrtf(f));



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