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