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