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));
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 __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 __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 */
|
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 */
|