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 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 #include <sys/types.h> 46 #include <sys/ieeefp.h> 47 48 extern __GNU_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 __GNU_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 __GNU_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 __GNU_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)); 90 91 return (ret); 92 } 93 94 /* 95 * 00 - Round to nearest, with even preferred 96 * 01 - Round down 97 * 10 - Round up 98 * 11 - Chop 99 */ 100 extern __GNU_INLINE enum fp_direction_type 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 __GNU_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 __GNU_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 __GNU_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 __GNU_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 __GNU_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 __GNU_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 __GNU_INLINE double 204 sqrt(double d) 205 { 206 return (__inline_sqrt(d)); 207 } 208 209 extern __GNU_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 */ 222