]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/x86_64/fpu/bits/mathinline.h
Do not provide inlines for GCC build-in functions
[thirdparty/glibc.git] / sysdeps / x86_64 / fpu / bits / mathinline.h
1 /* Inline math functions for x86-64.
2 Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifndef _MATH_H
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21 #endif
22
23 #ifndef __extern_always_inline
24 # define __MATH_INLINE __inline
25 #else
26 # define __MATH_INLINE __extern_always_inline
27 #endif
28
29
30 /* The gcc, version 2.7 or below, has problems with all this inlining
31 code. So disable it for this version of the compiler. */
32 #if __GNUC_PREREQ (2, 8) && defined __USE_ISOC99
33 __BEGIN_NAMESPACE_C99
34
35 /* Test for negative number. Used in the signbit() macro. */
36 __MATH_INLINE int
37 __NTH (__signbitf (float __x))
38 {
39 # ifndef __x86_64__
40 __extension__ union { float __f; int __i; } __u = { __f: __x };
41 return __u.__i < 0;
42 # else
43 int __m;
44 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
45 return __m & 0x8;
46 # endif
47 }
48 __MATH_INLINE int
49 __NTH (__signbit (double __x))
50 {
51 # ifndef __x86_64__
52 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
53 return __u.__i[1] < 0;
54 # else
55 int __m;
56 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
57 return __m & 0x80;
58 # endif
59 }
60 __MATH_INLINE int
61 __NTH (__signbitl (long double __x))
62 {
63 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
64 return __u.__i[2] & 0x8000;
65 }
66
67 __END_NAMESPACE_C99
68 #endif
69
70
71 #if __GNUC_PREREQ (2, 8) && !__GNUC_PREREQ (3, 4) \
72 && !defined __NO_MATH_INLINES && defined __OPTIMIZE__
73 /* GCC 3.4 introduced builtins for all functions below, so
74 there's no need to define any of these inline functions. */
75
76 # ifdef __USE_ISOC99
77 __BEGIN_NAMESPACE_C99
78
79 /* Round to nearest integer. */
80 # ifdef __SSE_MATH__
81 __MATH_INLINE long int
82 __NTH (lrintf (float __x))
83 {
84 long int __res;
85 /* Mark as volatile since the result is dependend on the state of
86 the SSE control register (the rounding mode). Otherwise GCC might
87 remove these assembler instructions since it does not know about
88 the rounding mode change and cannot currently be told. */
89 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
90 return __res;
91 }
92 # endif
93 # ifdef __SSE2_MATH__
94 __MATH_INLINE long int
95 __NTH (lrint (double __x))
96 {
97 long int __res;
98 /* Mark as volatile since the result is dependend on the state of
99 the SSE control register (the rounding mode). Otherwise GCC might
100 remove these assembler instructions since it does not know about
101 the rounding mode change and cannot currently be told. */
102 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
103 return __res;
104 }
105 # endif
106 # ifdef __x86_64__
107 __MATH_INLINE long long int
108 __NTH (llrintf (float __x))
109 {
110 long long int __res;
111 /* Mark as volatile since the result is dependend on the state of
112 the SSE control register (the rounding mode). Otherwise GCC might
113 remove these assembler instructions since it does not know about
114 the rounding mode change and cannot currently be told. */
115 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
116 return __res;
117 }
118 __MATH_INLINE long long int
119 __NTH (llrint (double __x))
120 {
121 long long int __res;
122 /* Mark as volatile since the result is dependend on the state of
123 the SSE control register (the rounding mode). Otherwise GCC might
124 remove these assembler instructions since it does not know about
125 the rounding mode change and cannot currently be told. */
126 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
127 return __res;
128 }
129 # endif
130
131 # if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
132 && defined __SSE2_MATH__
133 /* Determine maximum of two values. */
134 __MATH_INLINE float
135 __NTH (fmaxf (float __x, float __y))
136 {
137 # ifdef __AVX__
138 float __res;
139 __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
140 return __res;
141 # else
142 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
143 return __x;
144 # endif
145 }
146 __MATH_INLINE double
147 __NTH (fmax (double __x, double __y))
148 {
149 # ifdef __AVX__
150 float __res;
151 __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
152 return __res;
153 # else
154 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
155 return __x;
156 # endif
157 }
158
159 /* Determine minimum of two values. */
160 __MATH_INLINE float
161 __NTH (fminf (float __x, float __y))
162 {
163 # ifdef __AVX__
164 float __res;
165 __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
166 return __res;
167 # else
168 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
169 return __x;
170 # endif
171 }
172 __MATH_INLINE double
173 __NTH (fmin (double __x, double __y))
174 {
175 # ifdef __AVX__
176 float __res;
177 __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
178 return __res;
179 # else
180 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
181 return __x;
182 # endif
183 }
184 # endif
185
186 __END_NAMESPACE_C99
187 # endif
188
189 # if defined __SSE4_1__ && defined __SSE2_MATH__
190 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
191 __BEGIN_NAMESPACE_C99
192
193 /* Round to nearest integer. */
194 __MATH_INLINE double
195 __NTH (rint (double __x))
196 {
197 double __res;
198 /* Mark as volatile since the result is dependend on the state of
199 the SSE control register (the rounding mode). Otherwise GCC might
200 remove these assembler instructions since it does not know about
201 the rounding mode change and cannot currently be told. */
202 __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
203 return __res;
204 }
205 __MATH_INLINE float
206 __NTH (rintf (float __x))
207 {
208 float __res;
209 /* Mark as volatile since the result is dependend on the state of
210 the SSE control register (the rounding mode). Otherwise GCC might
211 remove these assembler instructions since it does not know about
212 the rounding mode change and cannot currently be told. */
213 __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
214 return __res;
215 }
216
217 # ifdef __USE_ISOC99
218 /* Round to nearest integer without raising inexact exception. */
219 __MATH_INLINE double
220 __NTH (nearbyint (double __x))
221 {
222 double __res;
223 /* Mark as volatile since the result is dependend on the state of
224 the SSE control register (the rounding mode). Otherwise GCC might
225 remove these assembler instructions since it does not know about
226 the rounding mode change and cannot currently be told. */
227 __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
228 return __res;
229 }
230 __MATH_INLINE float
231 __NTH (nearbyintf (float __x))
232 {
233 float __res;
234 /* Mark as volatile since the result is dependend on the state of
235 the SSE control register (the rounding mode). Otherwise GCC might
236 remove these assembler instructions since it does not know about
237 the rounding mode change and cannot currently be told. */
238 __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
239 return __res;
240 }
241 # endif
242
243 __END_NAMESPACE_C99
244 # endif
245
246 __BEGIN_NAMESPACE_STD
247 /* Smallest integral value not less than X. */
248 __MATH_INLINE double
249 __NTH (ceil (double __x))
250 {
251 double __res;
252 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
253 return __res;
254 }
255 __END_NAMESPACE_STD
256
257 __BEGIN_NAMESPACE_C99
258 __MATH_INLINE float
259 __NTH (ceilf (float __x))
260 {
261 float __res;
262 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
263 return __res;
264 }
265 __END_NAMESPACE_C99
266
267 __BEGIN_NAMESPACE_STD
268 /* Largest integer not greater than X. */
269 __MATH_INLINE double
270 __NTH (floor (double __x))
271 {
272 double __res;
273 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
274 return __res;
275 }
276 __END_NAMESPACE_STD
277
278 __BEGIN_NAMESPACE_C99
279 __MATH_INLINE float
280 __NTH (floorf (float __x))
281 {
282 float __res;
283 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
284 return __res;
285 }
286 __END_NAMESPACE_C99
287 # endif
288
289 #endif