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 locallibm.il. Keep them in sync */ 35 36 #ifndef _LIBM_INLINES_H 37 #define _LIBM_INLINES_H 38 39 #ifdef __GNUC__ 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 #include <sys/types.h> 45 #include <sys/ieeefp.h> 46 47 extern __GNU_INLINE float 48 __inline_sqrtf(float a) 49 { 50 float ret; 51 52 __asm__ __volatile__("sqrtss %1, %0\n\t" : "=x" (ret) : "x" (a)); 53 return (ret); 54 } 55 56 extern __GNU_INLINE double 57 __inline_sqrt(double a) 58 { 59 double ret; 60 61 __asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a)); 62 return (ret); 63 } 64 65 extern __GNU_INLINE double 66 __ieee754_sqrt(double a) 67 { 68 return (__inline_sqrt(a)); 69 } 70 71 /* 72 * 00 - 24 bits 73 * 01 - reserved 74 * 10 - 53 bits 75 * 11 - 64 bits 76 */ 77 extern __GNU_INLINE int 78 __swapRP(int i) 79 { 80 int ret; 81 uint16_t cw; 82 83 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 84 85 ret = (cw >> 8) & 0x3; 86 cw = (cw & 0xfcff) | ((i & 0x3) << 8); 87 88 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 89 90 return (ret); 91 } 92 93 /* 94 * 00 - Round to nearest, with even preferred 95 * 01 - Round down 96 * 10 - Round up 97 * 11 - Chop 98 */ 99 extern __GNU_INLINE enum fp_direction_type 100 __swap87RD(enum fp_direction_type i) 101 { 102 int ret; 103 uint16_t cw; 104 105 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); 106 107 ret = (cw >> 10) & 0x3; 108 cw = (cw & 0xf3ff) | ((i & 0x3) << 10); 109 110 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); 111 112 return (ret); 113 } 114 115 extern __GNU_INLINE int 116 abs(int i) 117 { 118 int ret; 119 __asm__ __volatile__( 120 "movl %1, %0\n\t" 121 "negl %1\n\t" 122 "cmovnsl %1, %0\n\t" 123 : "=r" (ret), "+r" (i) 124 : 125 : "cc"); 126 return (ret); 127 } 128 129 extern __GNU_INLINE double 130 copysign(double d1, double d2) 131 { 132 double tmpd; 133 134 __asm__ __volatile__( 135 "movd %3, %1\n\t" 136 "andpd %1, %0\n\t" 137 "andnpd %2, %1\n\t" 138 "orpd %1, %0\n\t" 139 : "+&x" (d1), "=&x" (tmpd) 140 : "x" (d2), "r" (0x7fffffffffffffff)); 141 142 return (d1); 143 } 144 145 extern __GNU_INLINE double 146 fabs(double d) 147 { 148 double tmp; 149 150 __asm__ __volatile__( 151 "movd %2, %1\n\t" 152 "andpd %1, %0" 153 : "+x" (d), "=&x" (tmp) 154 : "r" (0x7fffffffffffffff)); 155 156 return (d); 157 } 158 159 extern __GNU_INLINE float 160 fabsf(float d) 161 { 162 __asm__ __volatile__( 163 "andpd %1, %0" 164 : "+x" (d) 165 : "x" (0x7fffffff)); 166 167 return (d); 168 } 169 170 extern __GNU_INLINE int 171 finite(double d) 172 { 173 long ret = 0x7fffffffffffffff; 174 uint64_t tmp; 175 176 __asm__ __volatile__( 177 "movq %2, %1\n\t" 178 "andq %1, %0\n\t" 179 "movq $0x7ff0000000000000, %1\n\t" 180 "subq %1, %0\n\t" 181 "shrq $63, %0\n\t" 182 : "+r" (ret), "=r" (tmp) 183 : "x" (d) 184 : "cc"); 185 186 return (ret); 187 } 188 189 extern __GNU_INLINE int 190 signbit(double d) 191 { 192 long ret; 193 __asm__ __volatile__( 194 "movmskpd %1, %0\n\t" 195 "andq $1, %0\n\t" 196 : "=r" (ret) 197 : "x" (d) 198 : "cc"); 199 return (ret); 200 } 201 202 extern __GNU_INLINE double 203 sqrt(double d) 204 { 205 return (__inline_sqrt(d)); 206 } 207 208 extern __GNU_INLINE float 209 sqrtf(float f) 210 { 211 return (__inline_sqrtf(f)); 212 } 213 214 #ifdef __cplusplus 215 } 216 #endif 217 #endif /* __GNUC__ */ 218 #endif /* _LIBM_INLINES_H */