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 2011 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* 31 * Copyright 2011, Richard Lowe. 32 */ 33 34 /* Functions in this file are duplicated in libm.m4. Keep them in sync */ 35 36 #ifndef _LIBM_INLINES_H 37 #define _LIBM_INLINES_H 38 39 #ifdef __GNUC__ 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 #include <sys/types.h> 46 #include <sys/ieeefp.h> 47 48 extern __inline__ double 49 __ieee754_sqrt(double a) 50 { 51 double ret; 52 53 __asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a)); 54 return (ret); 55 } 56 57 extern __inline__ float 58 __inline_sqrtf(float a) 59 { 60 float ret; 61 62 __asm__ __volatile__("sqrtss %1, %0\n\t" : "=x" (ret) : "x" (a)); 63 return (ret); 64 } 65 66 extern __inline__ double 67 __inline_sqrt(double a) 68 { 69 double ret; 70 71 __asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a)); 72 return (ret); 73 } 74 75 /* XXX: Not actually called */ 76 extern __inline__ short 77 __inline_fstsw(void) 78 { 79 short ret; 80 81 __asm__ __volatile__("fstsw %0\n\t" : "=r" (ret)); 82 return (ret); 83 } 84 85 /* 86 * 00 - 24 bits 87 * 01 - reserved 88 * 10 - 53 bits 89 * 11 - 64 bits 90 */ 91 extern __inline__ int 92 __swapRP(int i) 93 { 94 int ret; 95 uint16_t cw; 96 97 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 98 99 ret = (cw >> 8) & 0x3; 100 cw = (cw & 0xfcff) | ((i & 0x3) << 8); 101 102 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 114 __swap87RD(enum fp_direction_type i) 115 { 116 int ret; 117 uint16_t cw; 118 119 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 120 121 ret = (cw >> 10) & 0x3; 122 cw = (cw & 0xf3ff) | ((i & 0x3) << 10); 123 124 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 125 126 return (ret); 127 } 128 129 extern __inline__ int 130 abs(int i) 131 { 132 int ret; 133 __asm__ __volatile__( 134 "movl %1,%0\n\t" 135 "negl %1\n\t" 136 "cmovnsl %1,%0\n\t" 137 : "=r" (ret), "+r" (i)); 138 return (ret); 139 } 140 141 extern __inline__ double 142 copysign(double d1, double d2) 143 { 144 double ret; 145 146 __asm__ __volatile__( 147 "movq $0x7fffffffffffffff,%%rax\n\t" 148 "movd %%rax,%%xmm2\n\t" 149 "andpd %%xmm2,%0\n\t" 150 "andnpd %1,%%xmm2\n\t" 151 "orpd %%xmm2,%0\n\t" 152 : "=x" (ret) 153 : "x" (d2), "0" (d1) 154 : "xmm2", "rax"); 155 156 return (ret); 157 } 158 159 extern __inline__ double 160 d_sqrt_(double *d) 161 { 162 double ret; 163 __asm__ __volatile__( 164 "movlpd %1,%0\n\t" 165 "sqrtsd %0,%0" 166 : "=x" (ret) 167 : "m" (*d)); 168 return (ret); 169 } 170 171 extern __inline__ double 172 fabs(double d) 173 { 174 double ret; 175 176 __asm__ __volatile__( 177 "movq $0x7fffffffffffffff,%%rax\n\t" 178 "movd %%rax,%%xmm1\n\t" 179 "andpd %%xmm1,%0" 180 : "=x" (ret) 181 : "0" (d) 182 : "rax", "xmm1"); 183 184 return (ret); 185 } 186 187 extern __inline__ float 188 fabsf(float d) 189 { 190 float ret; 191 192 __asm__ __volatile__( 193 "andpd %2,%0" 194 : "=x" (ret) 195 : "0" (d), "x" (0x7fffffff)); 196 197 return (ret); 198 } 199 200 extern __inline__ int 201 finite(double d) 202 { 203 long ret; /* A long, so gcc chooses an %r* for %0 */ 204 205 __asm__ __volatile__( 206 "movq %1,%%rcx\n\t" 207 "movq $0x7fffffffffffffff,%0\n\t" 208 "andq %%rcx,%0\n\t" 209 "movq $0x7ff0000000000000,%%rcx\n\t" 210 "subq %%rcx,%0\n\t" 211 "shrq $63,%0\n\t" 212 : "=r" (ret) 213 : "x" (d) 214 : "rcx"); 215 216 return (ret); 217 } 218 219 extern __inline__ float 220 r_sqrt_(float *f) 221 { 222 float ret; 223 224 __asm__ __volatile__( 225 "movss %1,%0\n\t" 226 "sqrtss %0,%0\n\t" 227 : "+x" (ret) 228 : "m" (*f)); 229 return (ret); 230 } 231 232 extern __inline__ int 233 signbit(double d) 234 { 235 long ret; 236 __asm__ __volatile__( 237 "movmskpd %1,%0\n\t" 238 "andq $1, %0\n\t" 239 : "=r" (ret) 240 : "x" (d)); 241 return (ret); 242 } 243 244 extern __inline__ int 245 signbitf(float f) 246 { 247 int ret; 248 __asm__ __volatile__( 249 "movskps %1,%0\n\t" 250 "andq $1, %0\n\t" 251 : "=r" (ret) 252 : "x" (f)); 253 return (ret); 254 } 255 256 extern __inline__ double 257 sqrt(double d) 258 { 259 double ret; 260 261 __asm__ __volatile__( 262 "sqrtsd %0, %0" 263 : "=x" (ret) 264 : "0" (d)); 265 return (ret); 266 } 267 268 extern __inline__ float 269 sqrtf(float f) 270 { 271 float ret; 272 273 __asm__ __volatile__( 274 "sqrtss %0, %0" 275 : "=x" (ret) 276 : "0" (f)); 277 return (ret); 278 } 279 280 #ifdef __cplusplus 281 } 282 #endif 283 284 #endif /* __GNUC__ */ 285 286 #endif /* _LIBM_INLINES_H */ | 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 2011 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* 31 * Copyright 2011, Richard Lowe. 32 */ 33 34 /* Functions in this file are duplicated in locallibm.il. Keep them in sync */ 35 36 #ifndef _LIBM_INLINES_H 37 #define _LIBM_INLINES_H 38 39 #ifdef __GNUC__ 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 #include <sys/types.h> 46 #include <sys/ieeefp.h> 47 48 extern __inline__ float 49 __inline_sqrtf(float a) 50 { 51 float ret; 52 53 __asm__ __volatile__("sqrtss %1, %0\n\t" : "=x" (ret) : "x" (a)); 54 return (ret); 55 } 56 57 extern __inline__ double 58 __inline_sqrt(double a) 59 { 60 double ret; 61 62 __asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a)); 63 return (ret); 64 } 65 66 extern __inline__ double 67 __ieee754_sqrt(double a) 68 { 69 return (__inline_sqrt(a)); 70 } 71 72 /* 73 * 00 - 24 bits 74 * 01 - reserved 75 * 10 - 53 bits 76 * 11 - 64 bits 77 */ 78 extern __inline__ int 79 __swapRP(int i) 80 { 81 int ret; 82 uint16_t cw; 83 84 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 85 86 ret = (cw >> 8) & 0x3; 87 cw = (cw & 0xfcff) | ((i & 0x3) << 8); 88 89 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 101 __swap87RD(enum fp_direction_type i) 102 { 103 int ret; 104 uint16_t cw; 105 106 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 107 108 ret = (cw >> 10) & 0x3; 109 cw = (cw & 0xf3ff) | ((i & 0x3) << 10); 110 111 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 112 113 return (ret); 114 } 115 116 extern __inline__ int 117 abs(int i) 118 { 119 int ret; 120 __asm__ __volatile__( 121 "movl %1, %0\n\t" 122 "negl %1\n\t" 123 "cmovnsl %1, %0\n\t" 124 : "=r" (ret), "+r" (i) 125 : 126 : "cc"); 127 return (ret); 128 } 129 130 extern __inline__ double 131 copysign(double d1, double d2) 132 { 133 double tmpd; 134 135 __asm__ __volatile__( 136 "movd %3, %1\n\t" 137 "andpd %1, %0\n\t" 138 "andnpd %2, %1\n\t" 139 "orpd %1, %0\n\t" 140 : "+x" (d1), "=x" (tmpd) 141 : "x" (d2), "r" (0x7fffffffffffffff)); 142 143 return (d1); 144 } 145 146 extern __inline__ double 147 fabs(double d) 148 { 149 double tmp; 150 151 __asm__ __volatile__( 152 "movd %2, %1\n\t" 153 "andpd %1, %0" 154 : "+x" (d), "=x" (tmp) 155 : "r" (0x7fffffffffffffff)); 156 157 return (d); 158 } 159 160 extern __inline__ float 161 fabsf(float d) 162 { 163 __asm__ __volatile__( 164 "andpd %1, %0" 165 : "+x" (d) 166 : "x" (0x7fffffff)); 167 168 return (d); 169 } 170 171 extern __inline__ int 172 finite(double d) 173 { 174 long ret = 0x7fffffffffffffff; 175 uint64_t tmp; 176 177 __asm__ __volatile__( 178 "movq %2, %1\n\t" 179 "andq %1, %0\n\t" 180 "movq $0x7ff0000000000000, %1\n\t" 181 "subq %1, %0\n\t" 182 "shrq $63, %0\n\t" 183 : "+r" (ret), "=r" (tmp) 184 : "x" (d) 185 : "cc"); 186 187 return (ret); 188 } 189 190 extern __inline__ int 191 signbit(double d) 192 { 193 long ret; 194 __asm__ __volatile__( 195 "movmskpd %1, %0\n\t" 196 "andq $1, %0\n\t" 197 : "=r" (ret) 198 : "x" (d) 199 : "cc"); 200 return (ret); 201 } 202 203 extern __inline__ double 204 sqrt(double d) 205 { 206 return (__inline_sqrt(d)); 207 } 208 209 extern __inline__ float 210 sqrtf(float f) 211 { 212 return (__inline_sqrtf(f)); 213 } 214 215 #ifdef __cplusplus 216 } 217 #endif 218 219 #endif /* __GNUC__ */ 220 221 #endif /* _LIBM_INLINES_H */ |