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