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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2011, Richard Lowe
29 */
30
31 /* Functions in this file are duplicated in libm.m4. Keep them in sync */
32
33 #ifndef _LIBM_INLINES_H
34 #define _LIBM_INLINES_H
35
36 #ifdef __GNUC__
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 #include <sys/types.h>
43 #include <sys/ieeefp.h>
44
45 #define _LO_WORD(x) ((uint32_t *)&x)[0]
46 #define _HI_WORD(x) ((uint32_t *)&x)[1]
47 #define _HIER_WORD(x) ((uint32_t *)&x)[2]
48
49 extern __inline__ double
50 __ieee754_sqrt(double a)
51 {
52 double ret;
53
54 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a));
55 return (ret);
56 }
57
58 extern __inline__ double
59 __inline_sqrt(double a)
60 {
61 double ret;
62
63 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a));
64 return (ret);
65 }
66
67 extern __inline__ double
68 __d_sqrt_(double *a)
69 {
70 double ret;
71
72 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (*a));
73 return (ret);
74 }
75
76 extern __inline__ float
77 __inline_sqrtf(float a)
78 {
79 float ret;
80
81 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a));
82 return (ret);
83 }
84
85 extern __inline__ double
86 __inline_rint(double a)
87 {
88 double ret;
89
90 __asm__ __volatile__(
91 "andl $0x7fffffff,%2\n\t"
92 "cmpl $0x43300000,%2\n\t"
93 "jae 1f\n\t"
94 "frndint\n\t"
95 "1: fwait\n\t"
96 : "=t" (ret)
97 : "0" (a), "r" (_HI_WORD(a)));
98
99 return (ret);
100 }
101
102 extern __inline__ short
103 __inline_fstsw(void)
104 {
105 short ret;
106
107 __asm__ __volatile__("fstsw %0\n\t" : "=r" (ret));
108 return (ret);
109 }
110
111 /*
112 * 00 - 24 bits
113 * 01 - reserved
114 * 10 - 53 bits
115 * 11 - 64 bits
116 */
117 extern __inline__ int
118 __swapRP(int i)
119 {
120 int ret;
121 uint16_t cw;
122
123 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
124
125 ret = (cw >> 8) & 0x3;
126 cw = (cw & 0xfcff) | ((i & 0x3) << 8);
127
128 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
138 */
139 extern __inline__ enum fp_direction_type
140 __swap87RD(enum fp_direction_type i)
141 {
142 int ret;
143 uint16_t cw;
144
145 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
146
147 ret = (cw >> 10) & 0x3;
148 cw = (cw & 0xf3ff) | ((i & 0x3) << 10);
149
150 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
151
152 return (ret);
153 }
154
155 extern __inline__ double
156 ceil(double d)
157 {
158 double ret;
159 short rd = __swap87RD(fp_positive);
160
161 __asm__ __volatile__("frndint" : "=t" (ret) : "0" (d));
162 __swap87RD(rd);
163
164 return (ret);
165 }
166
167 extern __inline__ double
168 copysign(double d1, double d2)
169 {
170 __asm__ __volatile__(
171 "andl $0x7fffffff,%0\n\t" /* %0 <-- hi_32(abs(d)) */
172 "andl $0x80000000,%1\n\t" /* %1[31] <-- sign_bit(d2) */
173 "orl %1,%0\n\t" /* %0 <-- hi_32(copysign(x,y)) */
174 : "+r" (_HI_WORD(d1))
175 : "r" (_HI_WORD(d2)));
176
177 return (d1);
178 }
179
180 extern __inline__ double
181 fabs(double d)
182 {
183 double ret;
184
185 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d));
186 return (ret);
187 }
188
189 extern __inline__ float
190 fabsf(float d)
191 {
192 float ret;
193
194 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d));
195 return (ret);
196 }
197
198 extern __inline__ long double
199 fabsl(long double d)
200 {
201 long double ret;
202
203 __asm__ __volatile__("fabs\n\t" : "=t" (ret) : "0" (d));
204 return (ret);
205 }
206
207 extern __inline__ int
208 finite(double d)
209 {
210 int ret;
211
212 __asm__ __volatile__(
213 "notl %1\n\t"
214 "andl $0x7ff00000,%1\n\t"
215 "negl %1\n\t"
216 "shrl $31,%1\n\t"
217 : "=r" (ret)
218 : "0" (_HI_WORD(d)));
219 return (ret);
220 }
221
222 extern __inline__ double
223 floor(double d)
224 {
225 double ret;
226 short rd = __swap87RD(fp_negative);
227
228 __asm__ __volatile__("frndint" : "=t" (ret) : "0" (d));
229 __swap87RD(rd);
230
231 return (ret);
232 }
233
234 /*
235 * branchless __isnan
236 * ((0x7ff00000-[((lx|-lx)>>31)&1]|ahx)>>31)&1 = 1 iff x is NaN
237 */
238 extern __inline__ int
239 isnan(double d)
240 {
241 int ret;
242
243 __asm__ __volatile__(
244 "movl %1,%%ecx\n\t"
245 "negl %%ecx\n\t" /* ecx <-- -lo_32(x) */
246 "orl %%ecx,%1\n\t"
247 "shrl $31,%1\n\t" /* 1 iff lx != 0 */
248 "andl $0x7fffffff,%2\n\t" /* ecx <-- hi_32(abs(x)) */
249 "orl %2,%1\n\t"
250 "subl $0x7ff00000,%1\n\t"
251 "negl %1\n\t"
252 "shrl $31,%1\n\t"
253 : "=r" (ret)
254 : "0" (_HI_WORD(d)), "r" (_LO_WORD(d))
255 : "ecx");
256
257 return (ret);
258 }
259
260 extern __inline__ int
261 isnanf(float f)
262 {
263 int ret;
264
265 __asm__ __volatile__(
266 "andl $0x7fffffff,%0\n\t"
267 "negl %0\n\t"
268 "addl $0x7f800000,%0\n\t"
269 "shrl $31,%0\n\t"
270 : "=r" (ret)
271 : "0" (f));
272
273 return (ret);
274 }
275
276 extern __inline__ int
277 isinf(double d)
278 {
279 int ret;
280
281 __asm__ __volatile__(
282 "andl $0x7fffffff,%1\n\t" /* set first bit to 0 */
283 "cmpl $0x7ff00000,%1\n\t"
284 "pushfl\n\t"
285 "popl %0\n\t"
286 "cmpl $0,%2\n\t" /* is lo_32(x) = 0? */
287 "pushfl\n\t"
288 "popl %2\n\t" /* bit 6 of ecx <-- lo_32(x) == 0 */
289 "andl %2,%0\n\t"
290 "andl $0x40,%0\n\t"
291 "shrl $6,%0\n\t"
292 : "=r" (ret)
293 : "0" (_HI_WORD(d)), "r" (_LO_WORD(d)));
294
295 return (ret);
296 }
297
298 extern __inline__ double
299 rint(double a) {
300 double ret;
301
302 __asm__ __volatile__(
303 "andl $0x7fffffff,%2\n\t"
304 "cmpl $0x43300000,%2\n\t"
305 "jae 1f\n\t"
306 "frndint\n\t"
307 "1: fwait\n\t"
308 : "=t" (ret)
309 : "0" (a), "r" (_HI_WORD(a)));
310
311 return (ret);
312 }
313
314 extern __inline__ double
315 scalbn(double d, int n)
316 {
317 double ret, dummy;
318
319 __asm__ __volatile__(
320 "fildl %3\n\t" /* Convert N to extended */
321 "fxch\n\t"
322 "fscale\n\t"
323 : "=t" (ret), "=u" (dummy)
324 : "0" (d), "m" (n));
325
326 return (ret);
327 }
328
329 extern __inline__ int
330 signbit(double d)
331 {
332 return (_HI_WORD(d) >> 31);
333 }
334
335 extern __inline__ int
336 signbitf(float f)
337 {
338 return ((*(uint32_t *)&f) >> 31);
339 }
340
341 extern __inline__ double
342 sqrt(double d)
343 {
344 double ret;
345 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (d));
346 return (ret);
347 }
348
349 extern __inline__ float
350 sqrtf(float f)
351 {
352 float ret;
353 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (f));
354 return (ret);
355 }
356
357 extern __inline__ long double
358 sqrtl(long double ld)
359 {
360 long double ret;
361 __asm__ __volatile__("fsqrt" : "=t" (ret) : "0" (ld));
362 return (ret);
363 }
364
365 extern __inline__ int
366 isnanl(long double ld)
367 {
368 int ret;
369
370 __asm__ __volatile__(
371 "andl $0x00007fff,%1\n\t"
372 "jz 1f\n\t" /* jump if __exp is all 0 */
373 "xorl $0x00007fff,%1\n\t"
374 "jz 2f\n\t" /* jump if __exp is all 1 */
375 "testl $0x80000000,%2\n\t"
376 "jz 3f\n\t" /* jump if leading bit is 0 */
377 "movl $0,%1\n\t"
378 "jmp 1f\n\t"
379 "2:\n\t" /* note that %eax = 0 from before */
380 "cmpl $0x80000000,%2\n\t" /* what is first half of __significand? */
381 "jnz 3f\n\t" /* jump if not equal to 0x80000000 */
382 "testl $0xffffffff,%3\n\t" /* is second half of __significand 0? */
383 "jnz 3f\n\t" /* jump if not equal to 0 */
384 "jmp 1f\n\t"
385 "3:\n\t"
386 "movl $1,%1\n\t"
387 "1:\n\t"
388 : "=r" (ret)
389 : "0" (_HIER_WORD(ld)), "r" (_HI_WORD(ld)), "r" (_LO_WORD(ld)));
390
391 return (ret);
392 }
393
394 #ifdef __cplusplus
395 }
396 #endif
397
398 #endif /* __GNUC__ */
399
400 #endif /* _LIBM_INLINES_H */
|
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 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2011, Richard Lowe
29 */
30
31 /* Functions in this file are duplicated in locallibm.il. Keep them in sync */
32
33 #ifndef _LIBM_INLINES_H
34 #define _LIBM_INLINES_H
35
36 #ifdef __GNUC__
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 #include <sys/types.h>
43 #include <sys/ieeefp.h>
44
45 #define _LO_WORD(x) ((uint32_t *)&x)[0]
46 #define _HI_WORD(x) ((uint32_t *)&x)[1]
47 #define _HIER_WORD(x) ((uint32_t *)&x)[2]
48
49 extern __inline__ double
50 __inline_sqrt(double a)
51 {
52 double ret;
53
54 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a) : "cc");
55 return (ret);
56 }
57
58 extern __inline__ double
59 __ieee754_sqrt(double a)
60 {
61 return (__inline_sqrt(a));
62 }
63
64 extern __inline__ float
65 __inline_sqrtf(float a)
66 {
67 float ret;
68
69 __asm__ __volatile__("fsqrt\n\t" : "=t" (ret) : "0" (a) : "cc");
70 return (ret);
71 }
72
73 extern __inline__ double
74 __inline_rint(double a)
75 {
76 __asm__ __volatile__(
77 "andl $0x7fffffff,%1\n\t"
78 "cmpl $0x43300000,%1\n\t"
79 "jae 1f\n\t"
80 "frndint\n\t"
81 "1: fwait\n\t"
82 : "+t" (a), "+&r" (_HI_WORD(a))
83 :
84 : "cc");
85
86 return (a);
87 }
88
89 /*
90 * 00 - 24 bits
91 * 01 - reserved
92 * 10 - 53 bits
93 * 11 - 64 bits
94 */
95 extern __inline__ int
96 __swapRP(int i)
97 {
98 int ret;
99 uint16_t cw;
100
101 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
102
103 ret = (cw >> 8) & 0x3;
104 cw = (cw & 0xfcff) | ((i & 0x3) << 8);
105
106 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
116 */
117 extern __inline__ enum fp_direction_type
118 __swap87RD(enum fp_direction_type i)
119 {
120 int ret;
121 uint16_t cw;
122
123 __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
124
125 ret = (cw >> 10) & 0x3;
126 cw = (cw & 0xf3ff) | ((i & 0x3) << 10);
127
128 __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
129
130 return (ret);
131 }
132
133 extern __inline__ double
134 ceil(double d)
135 {
136 short rd = __swap87RD(fp_positive);
137
138 __asm__ __volatile__("frndint" : "+t" (d), "+r" (rd) : : "cc");
139 __swap87RD(rd);
140
141 return (d);
142 }
143
144 extern __inline__ double
145 copysign(double d1, double d2)
146 {
147 __asm__ __volatile__(
148 "andl $0x7fffffff,%0\n\t" /* %0 <-- hi_32(abs(d)) */
149 "andl $0x80000000,%1\n\t" /* %1[31] <-- sign_bit(d2) */
150 "orl %1,%0\n\t" /* %0 <-- hi_32(copysign(x,y)) */
151 : "+&r" (_HI_WORD(d1)), "+r" (_HI_WORD(d2))
152 :
153 : "cc");
154
155 return (d1);
156 }
157
158 extern __inline__ double
159 fabs(double d)
160 {
161 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc");
162 return (d);
163 }
164
165 extern __inline__ float
166 fabsf(float d)
167 {
168 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc");
169 return (d);
170 }
171
172 extern __inline__ long double
173 fabsl(long double d)
174 {
175 __asm__ __volatile__("fabs\n\t" : "+t" (d) : : "cc");
176 return (d);
177 }
178
179 extern __inline__ int
180 finite(double d)
181 {
182 int ret = _HI_WORD(d);
183
184 __asm__ __volatile__(
185 "notl %0\n\t"
186 "andl $0x7ff00000,%0\n\t"
187 "negl %0\n\t"
188 "shrl $31,%0\n\t"
189 : "+r" (ret)
190 :
191 : "cc");
192 return (ret);
193 }
194
195 extern __inline__ double
196 floor(double d)
197 {
198 short rd = __swap87RD(fp_negative);
199
200 __asm__ __volatile__("frndint" : "+t" (d), "+r" (rd) : : "cc");
201 __swap87RD(rd);
202
203 return (d);
204 }
205
206 extern __inline__ int
207 isnanf(float f)
208 {
209 __asm__ __volatile__(
210 "andl $0x7fffffff,%0\n\t"
211 "negl %0\n\t"
212 "addl $0x7f800000,%0\n\t"
213 "shrl $31,%0\n\t"
214 : "+r" (f)
215 :
216 : "cc");
217
218 return (f);
219 }
220
221 extern __inline__ double
222 rint(double a) {
223 return (__inline_rint(a));
224 }
225
226 extern __inline__ double
227 scalbn(double d, int n)
228 {
229 double dummy;
230
231 __asm__ __volatile__(
232 "fildl %2\n\t" /* Convert N to extended */
233 "fxch\n\t"
234 "fscale\n\t"
235 : "+t" (d), "=u" (dummy)
236 : "m" (n)
237 : "cc");
238
239 return (d);
240 }
241
242 extern __inline__ int
243 signbit(double d)
244 {
245 return (_HI_WORD(d) >> 31);
246 }
247
248 extern __inline__ int
249 signbitf(float f)
250 {
251 return ((*(uint32_t *)&f) >> 31);
252 }
253
254 extern __inline__ double
255 sqrt(double d)
256 {
257 return (__inline_sqrt(d));
258 }
259
260 extern __inline__ float
261 sqrtf(float f)
262 {
263 return (__inline_sqrtf(f));
264 }
265
266 extern __inline__ long double
267 sqrtl(long double ld)
268 {
269 __asm__ __volatile__("fsqrt" : "+t" (ld) : : "cc");
270 return (ld);
271 }
272
273 extern __inline__ int
274 isnanl(long double ld)
275 {
276 int ret = _HIER_WORD(ld);
277
278 __asm__ __volatile__(
279 "andl $0x00007fff,%0\n\t"
280 "jz 1f\n\t" /* jump if exp is all 0 */
281 "xorl $0x00007fff,%0\n\t"
282 "jz 2f\n\t" /* jump if exp is all 1 */
283 "testl $0x80000000,%1\n\t"
284 "jz 3f\n\t" /* jump if leading bit is 0 */
285 "movl $0,%0\n\t"
286 "jmp 1f\n\t"
287 "2:\n\t" /* note that %0 = 0 from before */
288 "cmpl $0x80000000,%1\n\t" /* what is first half of significand? */
289 "jnz 3f\n\t" /* jump if not equal to 0x80000000 */
290 "testl $0xffffffff,%2\n\t" /* is second half of significand 0? */
291 "jnz 3f\n\t" /* jump if not equal to 0 */
292 "jmp 1f\n\t"
293 "3:\n\t"
294 "movl $1,%0\n\t"
295 "1:\n\t"
296 : "+&r" (ret)
297 : "r" (_HI_WORD(ld)), "r" (_LO_WORD(ld))
298 : "cc");
299
300 return (ret);
301 }
302
303 #ifdef __cplusplus
304 }
305 #endif
306
307 #endif /* __GNUC__ */
308
309 #endif /* _LIBM_INLINES_H */
|