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 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
__inline_sqrtf(float a)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
__inline_sqrt(double a)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
__ieee754_sqrt(double a)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
__swapRP(int i)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
__swap87RD(enum fp_direction_type i)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
abs(int i)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
copysign(double d1,double d2)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
fabs(double d)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
fabsf(float d)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
finite(double d)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
signbit(double d)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
sqrt(double d)204 sqrt(double d)
205 {
206 return (__inline_sqrt(d));
207 }
208
209 extern __inline__ float
sqrtf(float f)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 */
222