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 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)); 103 104 return (ret); 105 } 106 107 /* 108 * 00 - Round to nearest, with even preferred 109 * 01 - Round down 110 * 10 - Round up 111 * 11 - Chop 112 */ 113 extern __inline__ enum fp_direction_type 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 */