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 /* 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 __GNU_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), "+f" (f) 89 : 90 : "cc"); 91 92 return (ret); 93 } 94 95 extern __GNU_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), "+e" (d) 141 : 142 : "cc"); 143 144 return (ret); 145 } 146 147 extern __GNU_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 __GNU_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 __GNU_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 __GNU_INLINE enum fp_precision_type 198 __swapRP(enum fp_precision_type i) 199 { 200 return (0); 201 } 202 203 extern __GNU_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 __GNU_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 __GNU_INLINE double 263 sqrt(double d) 264 { 265 return (__inline_sqrt(d)); 266 } 267 268 extern __GNU_INLINE float 269 sqrtf(float f) 270 { 271 return (__inline_sqrtf(f)); 272 } 273 274 extern __GNU_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 __GNU_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 */