xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/rs6000/float128-ifunc.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /* Automatic switching between software and hardware IEEE 128-bit
2    floating-point emulation for PowerPC.
3 
4    Copyright (C) 2016 Free Software Foundation, Inc.
5    This file is part of the GNU C Library.
6    Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
7    Code is based on the main soft-fp library written by:
8 	Richard Henderson (rth@cygnus.com) and
9 	Jakub Jelinek (jj@ultra.linux.cz).
10 
11    The GNU C Library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 2.1 of the License, or (at your option) any later version.
15 
16    In addition to the permissions in the GNU Lesser General Public
17    License, the Free Software Foundation gives you unlimited
18    permission to link the compiled version of this file into
19    combinations with other programs, and to distribute those
20    combinations without any restriction coming from the use of this
21    file.  (The Lesser General Public License restrictions do apply in
22    other respects; for example, they cover modification of the file,
23    and distribution when not linked into a combine executable.)
24 
25    The GNU C Library is distributed in the hope that it will be useful,
26    but WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28    Lesser General Public License for more details.
29 
30    You should have received a copy of the GNU Lesser General Public
31    License along with the GNU C Library; if not, see
32    <http://www.gnu.org/licenses/>.  */
33 
34 #include <soft-fp.h>
35 #include <quad-float128.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 
40 #ifndef FLOAT128_HW_INSNS
41 #error "float128-ifunc.c needs access to ISA 3.0 instructions and ifunc"
42 #endif
43 
44 #ifdef __FLOAT128_HARDWARE__
45 #error "This module must not be compiled with IEEE 128-bit hardware support"
46 #endif
47 
48 #include <sys/auxv.h>
49 
50 /* Use the namespace clean version of getauxval.  However, not all versions of
51    sys/auxv.h declare it, so declare it here.  This code is intended to be
52    temporary until a suitable version of __builtin_cpu_supports is added that
53    allows us to tell quickly if the machine supports IEEE 128-bit hardware.  */
54 extern unsigned long __getauxval (unsigned long);
55 
56 static int
57 have_ieee_hw_p (void)
58 {
59   static int ieee_hw_p = -1;
60 
61   if (ieee_hw_p < 0)
62     {
63       char *p = (char *) __getauxval (AT_PLATFORM);
64 
65       ieee_hw_p = 0;
66 
67       /* Don't use atoi/strtol/strncmp/etc.  These may require the normal
68 	 environment to be setup to set errno to 0, and the ifunc resolvers run
69 	 before the whole glibc environment is initialized.  */
70       if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e'
71 	  && p[4] == 'r')
72 	{
73 	  long n = 0;
74 	  char ch;
75 
76 	  p += 5;
77 	  while ((ch = *p++) >= '0' && (ch <= '9'))
78 	    n = (n * 10) + (ch - '0');
79 
80 	  if (n >= 9)
81 	    ieee_hw_p = 1;
82 	}
83     }
84 
85   return ieee_hw_p;
86 }
87 
88 #define SW_OR_HW(SW, HW) (have_ieee_hw_p () ? HW : SW)
89 
90 /* Resolvers.  */
91 
92 /* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
93    and __floatuntikf.  There is no ISA 3.0 instruction that converts between
94    128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
95    use the emulator functions for these conversions.  */
96 
97 static void *__addkf3_resolve (void);
98 static void *__subkf3_resolve (void);
99 static void *__mulkf3_resolve (void);
100 static void *__divkf3_resolve (void);
101 static void *__negkf2_resolve (void);
102 static void *__eqkf2_resolve (void);
103 static void *__nekf2_resolve (void);
104 static void *__gekf2_resolve (void);
105 static void *__gtkf2_resolve (void);
106 static void *__lekf2_resolve (void);
107 static void *__ltkf2_resolve (void);
108 static void *__unordkf2_resolve (void);
109 static void *__extendsfkf2_resolve (void);
110 static void *__extenddfkf2_resolve (void);
111 static void *__trunckfsf2_resolve (void);
112 static void *__trunckfdf2_resolve (void);
113 static void *__fixkfsi_resolve (void);
114 static void *__fixkfdi_resolve (void);
115 static void *__fixunskfsi_resolve (void);
116 static void *__fixunskfdi_resolve (void);
117 static void *__floatsikf_resolve (void);
118 static void *__floatdikf_resolve (void);
119 static void *__floatunsikf_resolve (void);
120 static void *__floatundikf_resolve (void);
121 static void *__extendkftf2_resolve (void);
122 static void *__trunctfkf2_resolve (void);
123 
124 static void *
125 __addkf3_resolve (void)
126 {
127   return (void *) SW_OR_HW (__addkf3_sw, __addkf3_hw);
128 }
129 
130 static void *
131 __subkf3_resolve (void)
132 {
133   return (void *) SW_OR_HW (__subkf3_sw, __subkf3_hw);
134 }
135 
136 static void *
137 __mulkf3_resolve (void)
138 {
139   return (void *) SW_OR_HW (__mulkf3_sw, __mulkf3_hw);
140 }
141 
142 static void *
143 __divkf3_resolve (void)
144 {
145   return (void *) SW_OR_HW (__divkf3_sw, __divkf3_hw);
146 }
147 
148 static void *
149 __negkf2_resolve (void)
150 {
151   return (void *) SW_OR_HW (__negkf2_sw, __negkf2_hw);
152 }
153 
154 static void *
155 __floatsikf_resolve (void)
156 {
157   return (void *) SW_OR_HW (__floatsikf_sw, __floatsikf_hw);
158 }
159 
160 static void *
161 __floatdikf_resolve (void)
162 {
163   return (void *) SW_OR_HW (__floatdikf_sw, __floatdikf_hw);
164 }
165 
166 static void *
167 __floatunsikf_resolve (void)
168 {
169   return (void *) SW_OR_HW (__floatunsikf_sw, __floatunsikf_hw);
170 }
171 
172 static void *
173 __floatundikf_resolve (void)
174 {
175   return (void *) SW_OR_HW (__floatundikf_sw, __floatundikf_hw);
176 }
177 
178 static void *
179 __fixkfsi_resolve (void)
180 {
181   return (void *) SW_OR_HW (__fixkfsi_sw, __fixkfsi_hw);
182 }
183 
184 static void *
185 __fixkfdi_resolve (void)
186 {
187   return (void *) SW_OR_HW (__fixkfdi_sw, __fixkfdi_hw);
188 }
189 
190 static void *
191 __fixunskfsi_resolve (void)
192 {
193   return (void *) SW_OR_HW (__fixunskfsi_sw, __fixunskfsi_hw);
194 }
195 
196 static void *
197 __fixunskfdi_resolve (void)
198 {
199   return (void *) SW_OR_HW (__fixunskfdi_sw, __fixunskfdi_hw);
200 }
201 
202 static void *
203 __extendsfkf2_resolve (void)
204 {
205   return (void *) SW_OR_HW (__extendsfkf2_sw, __extendsfkf2_hw);
206 }
207 
208 static void *
209 __extenddfkf2_resolve (void)
210 {
211   return (void *) SW_OR_HW (__extenddfkf2_sw, __extenddfkf2_hw);
212 }
213 
214 static void *
215 __trunckfsf2_resolve (void)
216 {
217   return (void *) SW_OR_HW (__trunckfsf2_sw, __trunckfsf2_hw);
218 }
219 
220 static void *
221 __trunckfdf2_resolve (void)
222 {
223   return (void *) SW_OR_HW (__trunckfdf2_sw, __trunckfdf2_hw);
224 }
225 
226 static void *
227 __extendkftf2_resolve (void)
228 {
229   return (void *) SW_OR_HW (__extendkftf2_sw, __extendkftf2_hw);
230 }
231 
232 static void *
233 __trunctfkf2_resolve (void)
234 {
235   return (void *) SW_OR_HW (__trunctfkf2_sw, __trunctfkf2_hw);
236 }
237 
238 static void *
239 __eqkf2_resolve (void)
240 {
241   return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw);
242 }
243 
244 static void *
245 __gekf2_resolve (void)
246 {
247   return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw);
248 }
249 
250 static void *
251 __lekf2_resolve (void)
252 {
253   return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw);
254 }
255 
256 static void *
257 __unordkf2_resolve (void)
258 {
259   return (void *) SW_OR_HW (__unordkf2_sw, __unordkf2_hw);
260 }
261 
262 /* Resolve __nekf2, __gtkf2, __ltkf2 like __eqkf2, __gekf2, and __lekf2, since
263    the functions return the same values.  */
264 
265 static void *
266 __nekf2_resolve (void)
267 {
268   return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw);
269 }
270 
271 static void *
272 __gtkf2_resolve (void)
273 {
274   return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw);
275 }
276 
277 static void *
278 __ltkf2_resolve (void)
279 {
280   return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw);
281 }
282 
283 
284 
285 /* Ifunc definitions.  */
286 TFtype __addkf3 (TFtype, TFtype)
287   __attribute__ ((__ifunc__ ("__addkf3_resolve")));
288 
289 TFtype __subkf3 (TFtype, TFtype)
290   __attribute__ ((__ifunc__ ("__subkf3_resolve")));
291 
292 TFtype __mulkf3 (TFtype, TFtype)
293   __attribute__ ((__ifunc__ ("__mulkf3_resolve")));
294 
295 TFtype __divkf3 (TFtype, TFtype)
296   __attribute__ ((__ifunc__ ("__divkf3_resolve")));
297 
298 TFtype __negkf2 (TFtype)
299   __attribute__ ((__ifunc__ ("__negkf2_resolve")));
300 
301 CMPtype __eqkf2 (TFtype, TFtype)
302   __attribute__ ((__ifunc__ ("__eqkf2_resolve")));
303 
304 CMPtype __nekf2 (TFtype, TFtype)
305   __attribute__ ((__ifunc__ ("__nekf2_resolve")));
306 
307 CMPtype __gekf2 (TFtype, TFtype)
308   __attribute__ ((__ifunc__ ("__gekf2_resolve")));
309 
310 CMPtype __gtkf2 (TFtype, TFtype)
311   __attribute__ ((__ifunc__ ("__gtkf2_resolve")));
312 
313 CMPtype __lekf2 (TFtype, TFtype)
314   __attribute__ ((__ifunc__ ("__lekf2_resolve")));
315 
316 CMPtype __ltkf2 (TFtype, TFtype)
317   __attribute__ ((__ifunc__ ("__ltkf2_resolve")));
318 
319 CMPtype __unordkf2 (TFtype, TFtype)
320   __attribute__ ((__ifunc__ ("__unordkf2_resolve")));
321 
322 TFtype __extendsfkf2 (float)
323   __attribute__ ((__ifunc__ ("__extendsfkf2_resolve")));
324 
325 TFtype __extenddfkf2 (double)
326   __attribute__ ((__ifunc__ ("__extenddfkf2_resolve")));
327 
328 float __trunckfsf2 (TFtype)
329   __attribute__ ((__ifunc__ ("__trunckfsf2_resolve")));
330 
331 double __trunckfdf2 (TFtype)
332   __attribute__ ((__ifunc__ ("__trunckfdf2_resolve")));
333 
334 SItype_ppc __fixkfsi (TFtype)
335   __attribute__ ((__ifunc__ ("__fixkfsi_resolve")));
336 
337 DItype_ppc __fixkfdi (TFtype)
338   __attribute__ ((__ifunc__ ("__fixkfdi_resolve")));
339 
340 USItype_ppc __fixunskfsi (TFtype)
341   __attribute__ ((__ifunc__ ("__fixunskfsi_resolve")));
342 
343 UDItype_ppc __fixunskfdi (TFtype)
344   __attribute__ ((__ifunc__ ("__fixunskfdi_resolve")));
345 
346 TFtype __floatsikf (SItype_ppc)
347   __attribute__ ((__ifunc__ ("__floatsikf_resolve")));
348 
349 TFtype __floatdikf (DItype_ppc)
350   __attribute__ ((__ifunc__ ("__floatdikf_resolve")));
351 
352 TFtype __floatunsikf (USItype_ppc)
353   __attribute__ ((__ifunc__ ("__floatunsikf_resolve")));
354 
355 TFtype __floatundikf (UDItype_ppc)
356   __attribute__ ((__ifunc__ ("__floatundikf_resolve")));
357 
358 IBM128_TYPE __extendkftf2 (TFtype)
359   __attribute__ ((__ifunc__ ("__extendkftf2_resolve")));
360 
361 TFtype __trunctfkf2 (IBM128_TYPE)
362   __attribute__ ((__ifunc__ ("__trunctfkf2_resolve")));
363