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 #include <sys/types.h>
39 #include <sys/ieeefp.h>
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 extern __inline__ double
46 __inline_sqrt(double d)
47 {
48 double ret;
49
50 __asm__ __volatile__("fsqrtd %1,%0\n\t" : "=e" (ret) : "e" (d));
51 return (ret);
52 }
53
54 extern __inline__ float
55 __inline_sqrtf(float f)
56 {
57 float ret;
58
59 __asm__ __volatile__("fsqrts %1,%0\n\t" : "=f" (ret) : "f" (f));
60 return (ret);
61 }
62
63 extern __inline__ enum fp_class_type
64 fp_classf(float f)
65 {
66 enum fp_class_type ret;
67 uint32_t tmp;
68
69 /* XXX: Separate input and output */
70 __asm__ __volatile__(
71 "sethi %%hi(0x80000000),%1\n\t"
72 "andncc %2,%1,%0\n\t"
73 "bne 1f\n\t"
74 "nop\n\t"
75 "mov 0,%0\n\t"
76 "ba 2f\n\t" /* x is 0 */
77 "nop\n\t"
78 "1:\n\t"
79 "sethi %%hi(0x7f800000),%1\n\t"
80 "andcc %0,%1,%%g0\n\t"
81 "bne 1f\n\t"
82 "nop\n\t"
83 "mov 1,%0\n\t"
96 "mov 3,%0\n\t"
97 "ba 2f\n\t" /* x is __infinity */
98 "nop\n\t"
99 "1:\n\t"
100 "sethi %%hi(0x00400000),%1\n\t"
101 "andcc %0,%1,%%g0\n\t"
102 "mov 4,%0\n\t" /* x is quiet NaN */
103 "bne 2f\n\t"
104 "nop\n\t"
105 "mov 5,%0\n\t" /* x is signaling NaN */
106 "2:\n\t"
107 : "=r" (ret), "=&r" (tmp)
108 : "r" (f)
109 : "cc");
110 return (ret);
111 }
112
113 #define _HI_WORD(x) ((uint32_t *)&x)[0]
114 #define _LO_WORD(x) ((uint32_t *)&x)[1]
115
116 extern __inline__ enum fp_class_type
117 fp_class(double d)
118 {
119 enum fp_class_type ret;
120 uint32_t tmp;
121
122 __asm__ __volatile__(
123 "sethi %%hi(0x80000000),%1\n\t" /* %1 gets 80000000 */
124 "andn %2,%1,%0\n\t" /* %2-%0 gets abs(x) */
125 "orcc %0,%3,%%g0\n\t" /* set cc as x is zero/nonzero */
126 "bne 1f\n\t" /* branch if x is nonzero */
127 "nop\n\t"
128 "mov 0,%0\n\t"
129 "ba 2f\n\t" /* x is 0 */
130 "nop\n\t"
131 "1:\n\t"
132 "sethi %%hi(0x7ff00000),%1\n\t" /* %1 gets 7ff00000 */
133 "andcc %0,%1,%%g0\n\t" /* cc set by __exp field of x */
134 "bne 1f\n\t" /* branch if normal or max __exp */
135 "nop\n\t"
136 "mov 1,%0\n\t"
152 "ba 2f\n\t" /* x is __infinity */
153 "nop\n\t"
154 "1:\n\t"
155 "sethi %%hi(0x00080000),%1\n\t"
156 "andcc %0,%1,%%g0\n\t" /* set cc by quiet/sig bit */
157 "be 1f\n\t" /* Branch if signaling */
158 "nop\n\t"
159 "mov 4,%0\n\t" /* x is quiet NaN */
160 "ba 2f\n\t"
161 "nop\n\t"
162 "1:\n\t"
163 "mov 5,%0\n\t" /* x is signaling NaN */
164 "2:\n\t"
165 : "=&r" (ret), "=&r" (tmp)
166 : "r" (_HI_WORD(d)), "r" (_LO_WORD(d))
167 : "cc");
168
169 return (ret);
170 }
171
172 extern __inline__ int
173 __swapEX(int i)
174 {
175 int ret;
176 uint32_t fsr;
177 uint32_t tmp1, tmp2;
178
179 __asm__ __volatile__(
180 "and %4,0x1f,%2\n\t" /* tmp1 = %2 = %o1 */
181 "sll %2,5,%2\n\t" /* shift input to aexc bit location */
182 ".volatile\n\t"
183 "st %%fsr,%1\n\t"
184 "ld %1,%0\n\t" /* %0 = fsr */
185 "andn %0,0x3e0,%3\n\t" /* tmp2 = %3 = %o2 */
186 "or %2,%3,%2\n\t" /* %2 = new fsr */
187 "st %2,%1\n\t"
188 "ld %1,%%fsr\n\t"
189 "srl %0,5,%0\n\t"
190 "and %0,0x1f,%0\n\t" /* %0 = ret = %o0 */
191 ".nonvolatile\n\t"
192 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
193 : "r" (i)
194 : "cc");
195
196 return (ret);
197 }
198
199 /*
200 * On the SPARC, __swapRP is a no-op; always return 0 for backward
201 * compatibility
202 */
203 /* ARGSUSED */
204 extern __inline__ enum fp_precision_type
205 __swapRP(enum fp_precision_type i)
206 {
207 return (0);
208 }
209
210 extern __inline__ enum fp_direction_type
211 __swapRD(enum fp_direction_type d)
212 {
213 enum fp_direction_type ret;
214 uint32_t fsr;
215 uint32_t tmp1, tmp2, tmp3;
216
217 __asm__ __volatile__(
218 "and %5,0x3,%0\n\t"
219 "sll %0,30,%2\n\t" /* shift input to RD bit location */
220 ".volatile\n\t"
221 "st %%fsr,%1\n\t"
222 "ld %1,%0\n\t" /* %0 = fsr */
223 "set 0xc0000000,%4\n\t" /* mask of rounding direction bits */
224 "andn %0,%4,%3\n\t"
225 "or %2,%3,%2\n\t" /* %2 = new fsr */
226 "st %2,%1\n\t"
227 "ld %1,%%fsr\n\t"
228 "srl %0,30,%0\n\t"
229 "and %0,0x3,%0\n\t"
230 ".nonvolatile\n\t"
231 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
232 : "r" (d)
233 : "cc");
234
235 return (ret);
236 }
237
238 extern __inline__ int
239 __swapTE(int i)
240 {
241 int ret;
242 uint32_t fsr, tmp1, tmp2;
243
244 __asm__ __volatile__(
245 "and %4,0x1f,%0\n\t"
246 "sll %0,23,%2\n\t" /* shift input to TEM bit location */
247 ".volatile\n\t"
248 "st %%fsr,%1\n\t"
249 "ld %1,%0\n\t" /* %0 = fsr */
250 "set 0x0f800000,%3\n\t" /* mask of TEM (Trap Enable Mode bits) */
251 "andn %0,%3,%3\n\t"
252 "or %2,%3,%2\n\t" /* %2 = new fsr */
253 "st %2,%1\n\t"
254 "ld %1,%%fsr\n\t"
255 "srl %0,23,%0\n\t"
256 "and %0,0x1f,%0\n\t"
257 ".nonvolatile\n\t"
258 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
259 : "r" (i)
260 : "cc");
261
262 return (ret);
263 }
264
265 extern __inline__ double
266 sqrt(double d)
267 {
268 return (__inline_sqrt(d));
269 }
270
271 extern __inline__ float
272 sqrtf(float f)
273 {
274 return (__inline_sqrtf(f));
275 }
276
277 extern __inline__ double
278 fabs(double d)
279 {
280 double ret;
281
282 __asm__ __volatile__("fabsd %1,%0\n\t" : "=e" (ret) : "e" (d));
283 return (ret);
284 }
285
286 extern __inline__ float
287 fabsf(float f)
288 {
289 float ret;
290
291 __asm__ __volatile__("fabss %1,%0\n\t" : "=f" (ret) : "f" (f));
292 return (ret);
293 }
294
295 #ifdef __cplusplus
296 }
297 #endif
298
299 #endif /* __GNUC */
300
301 #endif /* _LIBM_INLINES_H */
|
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 #include <sys/types.h>
39 #include <sys/ieeefp.h>
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 extern __GNU_INLINE double
46 __inline_sqrt(double d)
47 {
48 double ret;
49
50 __asm__ __volatile__("fsqrtd %1,%0\n\t" : "=e" (ret) : "e" (d));
51 return (ret);
52 }
53
54 extern __GNU_INLINE float
55 __inline_sqrtf(float f)
56 {
57 float ret;
58
59 __asm__ __volatile__("fsqrts %1,%0\n\t" : "=f" (ret) : "f" (f));
60 return (ret);
61 }
62
63 extern __GNU_INLINE enum fp_class_type
64 fp_classf(float f)
65 {
66 enum fp_class_type ret;
67 uint32_t tmp;
68
69 /* XXX: Separate input and output */
70 __asm__ __volatile__(
71 "sethi %%hi(0x80000000),%1\n\t"
72 "andncc %2,%1,%0\n\t"
73 "bne 1f\n\t"
74 "nop\n\t"
75 "mov 0,%0\n\t"
76 "ba 2f\n\t" /* x is 0 */
77 "nop\n\t"
78 "1:\n\t"
79 "sethi %%hi(0x7f800000),%1\n\t"
80 "andcc %0,%1,%%g0\n\t"
81 "bne 1f\n\t"
82 "nop\n\t"
83 "mov 1,%0\n\t"
96 "mov 3,%0\n\t"
97 "ba 2f\n\t" /* x is __infinity */
98 "nop\n\t"
99 "1:\n\t"
100 "sethi %%hi(0x00400000),%1\n\t"
101 "andcc %0,%1,%%g0\n\t"
102 "mov 4,%0\n\t" /* x is quiet NaN */
103 "bne 2f\n\t"
104 "nop\n\t"
105 "mov 5,%0\n\t" /* x is signaling NaN */
106 "2:\n\t"
107 : "=r" (ret), "=&r" (tmp)
108 : "r" (f)
109 : "cc");
110 return (ret);
111 }
112
113 #define _HI_WORD(x) ((uint32_t *)&x)[0]
114 #define _LO_WORD(x) ((uint32_t *)&x)[1]
115
116 extern __GNU_INLINE enum fp_class_type
117 fp_class(double d)
118 {
119 enum fp_class_type ret;
120 uint32_t tmp;
121
122 __asm__ __volatile__(
123 "sethi %%hi(0x80000000),%1\n\t" /* %1 gets 80000000 */
124 "andn %2,%1,%0\n\t" /* %2-%0 gets abs(x) */
125 "orcc %0,%3,%%g0\n\t" /* set cc as x is zero/nonzero */
126 "bne 1f\n\t" /* branch if x is nonzero */
127 "nop\n\t"
128 "mov 0,%0\n\t"
129 "ba 2f\n\t" /* x is 0 */
130 "nop\n\t"
131 "1:\n\t"
132 "sethi %%hi(0x7ff00000),%1\n\t" /* %1 gets 7ff00000 */
133 "andcc %0,%1,%%g0\n\t" /* cc set by __exp field of x */
134 "bne 1f\n\t" /* branch if normal or max __exp */
135 "nop\n\t"
136 "mov 1,%0\n\t"
152 "ba 2f\n\t" /* x is __infinity */
153 "nop\n\t"
154 "1:\n\t"
155 "sethi %%hi(0x00080000),%1\n\t"
156 "andcc %0,%1,%%g0\n\t" /* set cc by quiet/sig bit */
157 "be 1f\n\t" /* Branch if signaling */
158 "nop\n\t"
159 "mov 4,%0\n\t" /* x is quiet NaN */
160 "ba 2f\n\t"
161 "nop\n\t"
162 "1:\n\t"
163 "mov 5,%0\n\t" /* x is signaling NaN */
164 "2:\n\t"
165 : "=&r" (ret), "=&r" (tmp)
166 : "r" (_HI_WORD(d)), "r" (_LO_WORD(d))
167 : "cc");
168
169 return (ret);
170 }
171
172 extern __GNU_INLINE int
173 __swapEX(int i)
174 {
175 int ret;
176 uint32_t fsr;
177 uint32_t tmp1, tmp2;
178
179 __asm__ __volatile__(
180 "and %4,0x1f,%2\n\t" /* tmp1 = %2 = %o1 */
181 "sll %2,5,%2\n\t" /* shift input to aexc bit location */
182 ".volatile\n\t"
183 "st %%fsr,%1\n\t"
184 "ld %1,%0\n\t" /* %0 = fsr */
185 "andn %0,0x3e0,%3\n\t" /* tmp2 = %3 = %o2 */
186 "or %2,%3,%2\n\t" /* %2 = new fsr */
187 "st %2,%1\n\t"
188 "ld %1,%%fsr\n\t"
189 "srl %0,5,%0\n\t"
190 "and %0,0x1f,%0\n\t" /* %0 = ret = %o0 */
191 ".nonvolatile\n\t"
192 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
193 : "r" (i)
194 : "cc");
195
196 return (ret);
197 }
198
199 /*
200 * On the SPARC, __swapRP is a no-op; always return 0 for backward
201 * compatibility
202 */
203 /* ARGSUSED */
204 extern __GNU_INLINE enum fp_precision_type
205 __swapRP(enum fp_precision_type i)
206 {
207 return (0);
208 }
209
210 extern __GNU_INLINE enum fp_direction_type
211 __swapRD(enum fp_direction_type d)
212 {
213 enum fp_direction_type ret;
214 uint32_t fsr;
215 uint32_t tmp1, tmp2, tmp3;
216
217 __asm__ __volatile__(
218 "and %5,0x3,%0\n\t"
219 "sll %0,30,%2\n\t" /* shift input to RD bit location */
220 ".volatile\n\t"
221 "st %%fsr,%1\n\t"
222 "ld %1,%0\n\t" /* %0 = fsr */
223 "set 0xc0000000,%4\n\t" /* mask of rounding direction bits */
224 "andn %0,%4,%3\n\t"
225 "or %2,%3,%2\n\t" /* %2 = new fsr */
226 "st %2,%1\n\t"
227 "ld %1,%%fsr\n\t"
228 "srl %0,30,%0\n\t"
229 "and %0,0x3,%0\n\t"
230 ".nonvolatile\n\t"
231 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
232 : "r" (d)
233 : "cc");
234
235 return (ret);
236 }
237
238 extern __GNU_INLINE int
239 __swapTE(int i)
240 {
241 int ret;
242 uint32_t fsr, tmp1, tmp2;
243
244 __asm__ __volatile__(
245 "and %4,0x1f,%0\n\t"
246 "sll %0,23,%2\n\t" /* shift input to TEM bit location */
247 ".volatile\n\t"
248 "st %%fsr,%1\n\t"
249 "ld %1,%0\n\t" /* %0 = fsr */
250 "set 0x0f800000,%3\n\t" /* mask of TEM (Trap Enable Mode bits) */
251 "andn %0,%3,%3\n\t"
252 "or %2,%3,%2\n\t" /* %2 = new fsr */
253 "st %2,%1\n\t"
254 "ld %1,%%fsr\n\t"
255 "srl %0,23,%0\n\t"
256 "and %0,0x1f,%0\n\t"
257 ".nonvolatile\n\t"
258 : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
259 : "r" (i)
260 : "cc");
261
262 return (ret);
263 }
264
265 extern __GNU_INLINE double
266 sqrt(double d)
267 {
268 return (__inline_sqrt(d));
269 }
270
271 extern __GNU_INLINE float
272 sqrtf(float f)
273 {
274 return (__inline_sqrtf(f));
275 }
276
277 extern __GNU_INLINE double
278 fabs(double d)
279 {
280 double ret;
281
282 __asm__ __volatile__("fabsd %1,%0\n\t" : "=e" (ret) : "e" (d));
283 return (ret);
284 }
285
286 extern __GNU_INLINE float
287 fabsf(float f)
288 {
289 float ret;
290
291 __asm__ __volatile__("fabss %1,%0\n\t" : "=f" (ret) : "f" (f));
292 return (ret);
293 }
294
295 #ifdef __cplusplus
296 }
297 #endif
298
299 #endif /* __GNUC */
300
301 #endif /* _LIBM_INLINES_H */
|