xref: /dflybsd-src/contrib/gcc-8.0/gcc/optabs-libfuncs.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Mapping from optabs to underlying library functions
2*38fd1498Szrj    Copyright (C) 1987-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj 
21*38fd1498Szrj #include "config.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "target.h"
25*38fd1498Szrj #include "insn-codes.h"
26*38fd1498Szrj #include "optabs-libfuncs.h"
27*38fd1498Szrj #include "libfuncs.h"
28*38fd1498Szrj #include "optabs-query.h"
29*38fd1498Szrj #include "tree.h"
30*38fd1498Szrj #include "stringpool.h"
31*38fd1498Szrj #include "varasm.h"
32*38fd1498Szrj #include "stor-layout.h"
33*38fd1498Szrj #include "rtl.h"
34*38fd1498Szrj 
35*38fd1498Szrj struct target_libfuncs default_target_libfuncs;
36*38fd1498Szrj #if SWITCHABLE_TARGET
37*38fd1498Szrj struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
38*38fd1498Szrj #endif
39*38fd1498Szrj 
40*38fd1498Szrj #define libfunc_hash \
41*38fd1498Szrj   (this_target_libfuncs->x_libfunc_hash)
42*38fd1498Szrj 
43*38fd1498Szrj /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
44*38fd1498Szrj #if ENABLE_DECIMAL_BID_FORMAT
45*38fd1498Szrj #define DECIMAL_PREFIX "bid_"
46*38fd1498Szrj #else
47*38fd1498Szrj #define DECIMAL_PREFIX "dpd_"
48*38fd1498Szrj #endif
49*38fd1498Szrj 
50*38fd1498Szrj /* Used for libfunc_hash.  */
51*38fd1498Szrj 
52*38fd1498Szrj hashval_t
hash(libfunc_entry * e)53*38fd1498Szrj libfunc_hasher::hash (libfunc_entry *e)
54*38fd1498Szrj {
55*38fd1498Szrj   return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
56*38fd1498Szrj }
57*38fd1498Szrj 
58*38fd1498Szrj /* Used for libfunc_hash.  */
59*38fd1498Szrj 
60*38fd1498Szrj bool
equal(libfunc_entry * e1,libfunc_entry * e2)61*38fd1498Szrj libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
62*38fd1498Szrj {
63*38fd1498Szrj   return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
64*38fd1498Szrj }
65*38fd1498Szrj 
66*38fd1498Szrj /* Return libfunc corresponding operation defined by OPTAB converting
67*38fd1498Szrj    from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
68*38fd1498Szrj    if no libfunc is available.  */
69*38fd1498Szrj rtx
convert_optab_libfunc(convert_optab optab,machine_mode mode1,machine_mode mode2)70*38fd1498Szrj convert_optab_libfunc (convert_optab optab, machine_mode mode1,
71*38fd1498Szrj 		       machine_mode mode2)
72*38fd1498Szrj {
73*38fd1498Szrj   struct libfunc_entry e;
74*38fd1498Szrj   struct libfunc_entry **slot;
75*38fd1498Szrj 
76*38fd1498Szrj   /* ??? This ought to be an assert, but not all of the places
77*38fd1498Szrj      that we expand optabs know about the optabs that got moved
78*38fd1498Szrj      to being direct.  */
79*38fd1498Szrj   if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
80*38fd1498Szrj     return NULL_RTX;
81*38fd1498Szrj 
82*38fd1498Szrj   e.op = optab;
83*38fd1498Szrj   e.mode1 = mode1;
84*38fd1498Szrj   e.mode2 = mode2;
85*38fd1498Szrj   slot = libfunc_hash->find_slot (&e, NO_INSERT);
86*38fd1498Szrj   if (!slot)
87*38fd1498Szrj     {
88*38fd1498Szrj       const struct convert_optab_libcall_d *d
89*38fd1498Szrj 	= &convlib_def[optab - FIRST_CONV_OPTAB];
90*38fd1498Szrj 
91*38fd1498Szrj       if (d->libcall_gen == NULL)
92*38fd1498Szrj 	return NULL;
93*38fd1498Szrj 
94*38fd1498Szrj       d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
95*38fd1498Szrj       slot = libfunc_hash->find_slot (&e, NO_INSERT);
96*38fd1498Szrj       if (!slot)
97*38fd1498Szrj 	return NULL;
98*38fd1498Szrj     }
99*38fd1498Szrj   return (*slot)->libfunc;
100*38fd1498Szrj }
101*38fd1498Szrj 
102*38fd1498Szrj /* Return libfunc corresponding operation defined by OPTAB in MODE.
103*38fd1498Szrj    Trigger lazy initialization if needed, return NULL if no libfunc is
104*38fd1498Szrj    available.  */
105*38fd1498Szrj rtx
optab_libfunc(optab optab,machine_mode mode)106*38fd1498Szrj optab_libfunc (optab optab, machine_mode mode)
107*38fd1498Szrj {
108*38fd1498Szrj   struct libfunc_entry e;
109*38fd1498Szrj   struct libfunc_entry **slot;
110*38fd1498Szrj 
111*38fd1498Szrj   /* ??? This ought to be an assert, but not all of the places
112*38fd1498Szrj      that we expand optabs know about the optabs that got moved
113*38fd1498Szrj      to being direct.  */
114*38fd1498Szrj   if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
115*38fd1498Szrj     return NULL_RTX;
116*38fd1498Szrj 
117*38fd1498Szrj   e.op = optab;
118*38fd1498Szrj   e.mode1 = mode;
119*38fd1498Szrj   e.mode2 = VOIDmode;
120*38fd1498Szrj   slot = libfunc_hash->find_slot (&e, NO_INSERT);
121*38fd1498Szrj   if (!slot)
122*38fd1498Szrj     {
123*38fd1498Szrj       const struct optab_libcall_d *d
124*38fd1498Szrj 	= &normlib_def[optab - FIRST_NORM_OPTAB];
125*38fd1498Szrj 
126*38fd1498Szrj       if (d->libcall_gen == NULL)
127*38fd1498Szrj 	return NULL;
128*38fd1498Szrj 
129*38fd1498Szrj       d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
130*38fd1498Szrj       slot = libfunc_hash->find_slot (&e, NO_INSERT);
131*38fd1498Szrj       if (!slot)
132*38fd1498Szrj 	return NULL;
133*38fd1498Szrj     }
134*38fd1498Szrj   return (*slot)->libfunc;
135*38fd1498Szrj }
136*38fd1498Szrj 
137*38fd1498Szrj /* Initialize the libfunc fields of an entire group of entries in some
138*38fd1498Szrj    optab.  Each entry is set equal to a string consisting of a leading
139*38fd1498Szrj    pair of underscores followed by a generic operation name followed by
140*38fd1498Szrj    a mode name (downshifted to lowercase) followed by a single character
141*38fd1498Szrj    representing the number of operands for the given operation (which is
142*38fd1498Szrj    usually one of the characters '2', '3', or '4').
143*38fd1498Szrj 
144*38fd1498Szrj    OPTABLE is the table in which libfunc fields are to be initialized.
145*38fd1498Szrj    OPNAME is the generic (string) name of the operation.
146*38fd1498Szrj    SUFFIX is the character which specifies the number of operands for
147*38fd1498Szrj      the given generic operation.
148*38fd1498Szrj    MODE is the mode to generate for.  */
149*38fd1498Szrj 
150*38fd1498Szrj static void
gen_libfunc(optab optable,const char * opname,int suffix,machine_mode mode)151*38fd1498Szrj gen_libfunc (optab optable, const char *opname, int suffix,
152*38fd1498Szrj 	     machine_mode mode)
153*38fd1498Szrj {
154*38fd1498Szrj   unsigned opname_len = strlen (opname);
155*38fd1498Szrj   const char *mname = GET_MODE_NAME (mode);
156*38fd1498Szrj   unsigned mname_len = strlen (mname);
157*38fd1498Szrj   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
158*38fd1498Szrj   int len = prefix_len + opname_len + mname_len + 1 + 1;
159*38fd1498Szrj   char *libfunc_name = XALLOCAVEC (char, len);
160*38fd1498Szrj   char *p;
161*38fd1498Szrj   const char *q;
162*38fd1498Szrj 
163*38fd1498Szrj   p = libfunc_name;
164*38fd1498Szrj   *p++ = '_';
165*38fd1498Szrj   *p++ = '_';
166*38fd1498Szrj   if (targetm.libfunc_gnu_prefix)
167*38fd1498Szrj     {
168*38fd1498Szrj       *p++ = 'g';
169*38fd1498Szrj       *p++ = 'n';
170*38fd1498Szrj       *p++ = 'u';
171*38fd1498Szrj       *p++ = '_';
172*38fd1498Szrj     }
173*38fd1498Szrj   for (q = opname; *q;)
174*38fd1498Szrj     *p++ = *q++;
175*38fd1498Szrj   for (q = mname; *q; q++)
176*38fd1498Szrj     *p++ = TOLOWER (*q);
177*38fd1498Szrj   *p++ = suffix;
178*38fd1498Szrj   *p = '\0';
179*38fd1498Szrj 
180*38fd1498Szrj   set_optab_libfunc (optable, mode,
181*38fd1498Szrj 		     ggc_alloc_string (libfunc_name, p - libfunc_name));
182*38fd1498Szrj }
183*38fd1498Szrj 
184*38fd1498Szrj /* Like gen_libfunc, but verify that integer operation is involved.  */
185*38fd1498Szrj 
186*38fd1498Szrj void
gen_int_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)187*38fd1498Szrj gen_int_libfunc (optab optable, const char *opname, char suffix,
188*38fd1498Szrj 		 machine_mode mode)
189*38fd1498Szrj {
190*38fd1498Szrj   int maxsize = 2 * BITS_PER_WORD;
191*38fd1498Szrj   int minsize = BITS_PER_WORD;
192*38fd1498Szrj   scalar_int_mode int_mode;
193*38fd1498Szrj 
194*38fd1498Szrj   if (!is_int_mode (mode, &int_mode))
195*38fd1498Szrj     return;
196*38fd1498Szrj   if (maxsize < LONG_LONG_TYPE_SIZE)
197*38fd1498Szrj     maxsize = LONG_LONG_TYPE_SIZE;
198*38fd1498Szrj   if (minsize > INT_TYPE_SIZE
199*38fd1498Szrj       && (trapv_binoptab_p (optable)
200*38fd1498Szrj 	  || trapv_unoptab_p (optable)))
201*38fd1498Szrj     minsize = INT_TYPE_SIZE;
202*38fd1498Szrj   if (GET_MODE_BITSIZE (int_mode) < minsize
203*38fd1498Szrj       || GET_MODE_BITSIZE (int_mode) > maxsize)
204*38fd1498Szrj     return;
205*38fd1498Szrj   gen_libfunc (optable, opname, suffix, int_mode);
206*38fd1498Szrj }
207*38fd1498Szrj 
208*38fd1498Szrj /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
209*38fd1498Szrj 
210*38fd1498Szrj void
gen_fp_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)211*38fd1498Szrj gen_fp_libfunc (optab optable, const char *opname, char suffix,
212*38fd1498Szrj 		machine_mode mode)
213*38fd1498Szrj {
214*38fd1498Szrj   char *dec_opname;
215*38fd1498Szrj 
216*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
217*38fd1498Szrj     gen_libfunc (optable, opname, suffix, mode);
218*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (mode))
219*38fd1498Szrj     {
220*38fd1498Szrj       dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
221*38fd1498Szrj       /* For BID support, change the name to have either a bid_ or dpd_ prefix
222*38fd1498Szrj 	 depending on the low level floating format used.  */
223*38fd1498Szrj       memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
224*38fd1498Szrj       strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
225*38fd1498Szrj       gen_libfunc (optable, dec_opname, suffix, mode);
226*38fd1498Szrj     }
227*38fd1498Szrj }
228*38fd1498Szrj 
229*38fd1498Szrj /* Like gen_libfunc, but verify that fixed-point operation is involved.  */
230*38fd1498Szrj 
231*38fd1498Szrj void
gen_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)232*38fd1498Szrj gen_fixed_libfunc (optab optable, const char *opname, char suffix,
233*38fd1498Szrj 		   machine_mode mode)
234*38fd1498Szrj {
235*38fd1498Szrj   if (!ALL_FIXED_POINT_MODE_P (mode))
236*38fd1498Szrj     return;
237*38fd1498Szrj   gen_libfunc (optable, opname, suffix, mode);
238*38fd1498Szrj }
239*38fd1498Szrj 
240*38fd1498Szrj /* Like gen_libfunc, but verify that signed fixed-point operation is
241*38fd1498Szrj    involved.  */
242*38fd1498Szrj 
243*38fd1498Szrj void
gen_signed_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)244*38fd1498Szrj gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
245*38fd1498Szrj 			  machine_mode mode)
246*38fd1498Szrj {
247*38fd1498Szrj   if (!SIGNED_FIXED_POINT_MODE_P (mode))
248*38fd1498Szrj     return;
249*38fd1498Szrj   gen_libfunc (optable, opname, suffix, mode);
250*38fd1498Szrj }
251*38fd1498Szrj 
252*38fd1498Szrj /* Like gen_libfunc, but verify that unsigned fixed-point operation is
253*38fd1498Szrj    involved.  */
254*38fd1498Szrj 
255*38fd1498Szrj void
gen_unsigned_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)256*38fd1498Szrj gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
257*38fd1498Szrj 			    machine_mode mode)
258*38fd1498Szrj {
259*38fd1498Szrj   if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
260*38fd1498Szrj     return;
261*38fd1498Szrj   gen_libfunc (optable, opname, suffix, mode);
262*38fd1498Szrj }
263*38fd1498Szrj 
264*38fd1498Szrj /* Like gen_libfunc, but verify that FP or INT operation is involved.  */
265*38fd1498Szrj 
266*38fd1498Szrj void
gen_int_fp_libfunc(optab optable,const char * name,char suffix,machine_mode mode)267*38fd1498Szrj gen_int_fp_libfunc (optab optable, const char *name, char suffix,
268*38fd1498Szrj 		    machine_mode mode)
269*38fd1498Szrj {
270*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
271*38fd1498Szrj     gen_fp_libfunc (optable, name, suffix, mode);
272*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
273*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
274*38fd1498Szrj }
275*38fd1498Szrj 
276*38fd1498Szrj /* Like gen_libfunc, but verify that FP or INT operation is involved
277*38fd1498Szrj    and add 'v' suffix for integer operation.  */
278*38fd1498Szrj 
279*38fd1498Szrj void
gen_intv_fp_libfunc(optab optable,const char * name,char suffix,machine_mode mode)280*38fd1498Szrj gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
281*38fd1498Szrj 		     machine_mode mode)
282*38fd1498Szrj {
283*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
284*38fd1498Szrj     gen_fp_libfunc (optable, name, suffix, mode);
285*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_INT)
286*38fd1498Szrj     {
287*38fd1498Szrj       int len = strlen (name);
288*38fd1498Szrj       char *v_name = XALLOCAVEC (char, len + 2);
289*38fd1498Szrj       strcpy (v_name, name);
290*38fd1498Szrj       v_name[len] = 'v';
291*38fd1498Szrj       v_name[len + 1] = 0;
292*38fd1498Szrj       gen_int_libfunc (optable, v_name, suffix, mode);
293*38fd1498Szrj     }
294*38fd1498Szrj }
295*38fd1498Szrj 
296*38fd1498Szrj /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
297*38fd1498Szrj    involved.  */
298*38fd1498Szrj 
299*38fd1498Szrj void
gen_int_fp_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)300*38fd1498Szrj gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
301*38fd1498Szrj 			  machine_mode mode)
302*38fd1498Szrj {
303*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
304*38fd1498Szrj     gen_fp_libfunc (optable, name, suffix, mode);
305*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
306*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
307*38fd1498Szrj   if (ALL_FIXED_POINT_MODE_P (mode))
308*38fd1498Szrj     gen_fixed_libfunc (optable, name, suffix, mode);
309*38fd1498Szrj }
310*38fd1498Szrj 
311*38fd1498Szrj /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
312*38fd1498Szrj    involved.  */
313*38fd1498Szrj 
314*38fd1498Szrj void
gen_int_fp_signed_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)315*38fd1498Szrj gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
316*38fd1498Szrj 				 machine_mode mode)
317*38fd1498Szrj {
318*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
319*38fd1498Szrj     gen_fp_libfunc (optable, name, suffix, mode);
320*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
321*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
322*38fd1498Szrj   if (SIGNED_FIXED_POINT_MODE_P (mode))
323*38fd1498Szrj     gen_signed_fixed_libfunc (optable, name, suffix, mode);
324*38fd1498Szrj }
325*38fd1498Szrj 
326*38fd1498Szrj /* Like gen_libfunc, but verify that INT or FIXED operation is
327*38fd1498Szrj    involved.  */
328*38fd1498Szrj 
329*38fd1498Szrj void
gen_int_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)330*38fd1498Szrj gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
331*38fd1498Szrj 		       machine_mode mode)
332*38fd1498Szrj {
333*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
334*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
335*38fd1498Szrj   if (ALL_FIXED_POINT_MODE_P (mode))
336*38fd1498Szrj     gen_fixed_libfunc (optable, name, suffix, mode);
337*38fd1498Szrj }
338*38fd1498Szrj 
339*38fd1498Szrj /* Like gen_libfunc, but verify that INT or signed FIXED operation is
340*38fd1498Szrj    involved.  */
341*38fd1498Szrj 
342*38fd1498Szrj void
gen_int_signed_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)343*38fd1498Szrj gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
344*38fd1498Szrj 			      machine_mode mode)
345*38fd1498Szrj {
346*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
347*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
348*38fd1498Szrj   if (SIGNED_FIXED_POINT_MODE_P (mode))
349*38fd1498Szrj     gen_signed_fixed_libfunc (optable, name, suffix, mode);
350*38fd1498Szrj }
351*38fd1498Szrj 
352*38fd1498Szrj /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
353*38fd1498Szrj    involved.  */
354*38fd1498Szrj 
355*38fd1498Szrj void
gen_int_unsigned_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)356*38fd1498Szrj gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
357*38fd1498Szrj 				machine_mode mode)
358*38fd1498Szrj {
359*38fd1498Szrj   if (INTEGRAL_MODE_P (mode))
360*38fd1498Szrj     gen_int_libfunc (optable, name, suffix, mode);
361*38fd1498Szrj   if (UNSIGNED_FIXED_POINT_MODE_P (mode))
362*38fd1498Szrj     gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
363*38fd1498Szrj }
364*38fd1498Szrj 
365*38fd1498Szrj /* Initialize the libfunc fields of an entire group of entries of an
366*38fd1498Szrj    inter-mode-class conversion optab.  The string formation rules are
367*38fd1498Szrj    similar to the ones for init_libfuncs, above, but instead of having
368*38fd1498Szrj    a mode name and an operand count these functions have two mode names
369*38fd1498Szrj    and no operand count.  */
370*38fd1498Szrj 
371*38fd1498Szrj void
gen_interclass_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)372*38fd1498Szrj gen_interclass_conv_libfunc (convert_optab tab,
373*38fd1498Szrj 			     const char *opname,
374*38fd1498Szrj 			     machine_mode tmode,
375*38fd1498Szrj 			     machine_mode fmode)
376*38fd1498Szrj {
377*38fd1498Szrj   size_t opname_len = strlen (opname);
378*38fd1498Szrj   size_t mname_len = 0;
379*38fd1498Szrj 
380*38fd1498Szrj   const char *fname, *tname;
381*38fd1498Szrj   const char *q;
382*38fd1498Szrj   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
383*38fd1498Szrj   char *libfunc_name, *suffix;
384*38fd1498Szrj   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
385*38fd1498Szrj   char *p;
386*38fd1498Szrj 
387*38fd1498Szrj   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
388*38fd1498Szrj      depends on which underlying decimal floating point format is used.  */
389*38fd1498Szrj   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
390*38fd1498Szrj 
391*38fd1498Szrj   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
392*38fd1498Szrj 
393*38fd1498Szrj   nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
394*38fd1498Szrj   nondec_name[0] = '_';
395*38fd1498Szrj   nondec_name[1] = '_';
396*38fd1498Szrj   if (targetm.libfunc_gnu_prefix)
397*38fd1498Szrj     {
398*38fd1498Szrj       nondec_name[2] = 'g';
399*38fd1498Szrj       nondec_name[3] = 'n';
400*38fd1498Szrj       nondec_name[4] = 'u';
401*38fd1498Szrj       nondec_name[5] = '_';
402*38fd1498Szrj     }
403*38fd1498Szrj 
404*38fd1498Szrj   memcpy (&nondec_name[prefix_len], opname, opname_len);
405*38fd1498Szrj   nondec_suffix = nondec_name + opname_len + prefix_len;
406*38fd1498Szrj 
407*38fd1498Szrj   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
408*38fd1498Szrj   dec_name[0] = '_';
409*38fd1498Szrj   dec_name[1] = '_';
410*38fd1498Szrj   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
411*38fd1498Szrj   memcpy (&dec_name[2+dec_len], opname, opname_len);
412*38fd1498Szrj   dec_suffix = dec_name + dec_len + opname_len + 2;
413*38fd1498Szrj 
414*38fd1498Szrj   fname = GET_MODE_NAME (fmode);
415*38fd1498Szrj   tname = GET_MODE_NAME (tmode);
416*38fd1498Szrj 
417*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
418*38fd1498Szrj     {
419*38fd1498Szrj       libfunc_name = dec_name;
420*38fd1498Szrj       suffix = dec_suffix;
421*38fd1498Szrj     }
422*38fd1498Szrj   else
423*38fd1498Szrj     {
424*38fd1498Szrj       libfunc_name = nondec_name;
425*38fd1498Szrj       suffix = nondec_suffix;
426*38fd1498Szrj     }
427*38fd1498Szrj 
428*38fd1498Szrj   p = suffix;
429*38fd1498Szrj   for (q = fname; *q; p++, q++)
430*38fd1498Szrj     *p = TOLOWER (*q);
431*38fd1498Szrj   for (q = tname; *q; p++, q++)
432*38fd1498Szrj     *p = TOLOWER (*q);
433*38fd1498Szrj 
434*38fd1498Szrj   *p = '\0';
435*38fd1498Szrj 
436*38fd1498Szrj   set_conv_libfunc (tab, tmode, fmode,
437*38fd1498Szrj 		    ggc_alloc_string (libfunc_name, p - libfunc_name));
438*38fd1498Szrj }
439*38fd1498Szrj 
440*38fd1498Szrj /* Same as gen_interclass_conv_libfunc but verify that we are producing
441*38fd1498Szrj    int->fp conversion.  */
442*38fd1498Szrj 
443*38fd1498Szrj void
gen_int_to_fp_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)444*38fd1498Szrj gen_int_to_fp_conv_libfunc (convert_optab tab,
445*38fd1498Szrj 			    const char *opname,
446*38fd1498Szrj 			    machine_mode tmode,
447*38fd1498Szrj 			    machine_mode fmode)
448*38fd1498Szrj {
449*38fd1498Szrj   if (GET_MODE_CLASS (fmode) != MODE_INT)
450*38fd1498Szrj     return;
451*38fd1498Szrj   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
452*38fd1498Szrj     return;
453*38fd1498Szrj   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
454*38fd1498Szrj }
455*38fd1498Szrj 
456*38fd1498Szrj /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
457*38fd1498Szrj    naming scheme.  */
458*38fd1498Szrj 
459*38fd1498Szrj void
gen_ufloat_conv_libfunc(convert_optab tab,const char * opname ATTRIBUTE_UNUSED,machine_mode tmode,machine_mode fmode)460*38fd1498Szrj gen_ufloat_conv_libfunc (convert_optab tab,
461*38fd1498Szrj 			 const char *opname ATTRIBUTE_UNUSED,
462*38fd1498Szrj 			 machine_mode tmode,
463*38fd1498Szrj 			 machine_mode fmode)
464*38fd1498Szrj {
465*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (tmode))
466*38fd1498Szrj     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
467*38fd1498Szrj   else
468*38fd1498Szrj     gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
469*38fd1498Szrj }
470*38fd1498Szrj 
471*38fd1498Szrj /* Same as gen_interclass_conv_libfunc but verify that we are producing
472*38fd1498Szrj    fp->int conversion.  */
473*38fd1498Szrj 
474*38fd1498Szrj void
gen_int_to_fp_nondecimal_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)475*38fd1498Szrj gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
476*38fd1498Szrj 				       const char *opname,
477*38fd1498Szrj 				       machine_mode tmode,
478*38fd1498Szrj 				       machine_mode fmode)
479*38fd1498Szrj {
480*38fd1498Szrj   if (GET_MODE_CLASS (fmode) != MODE_INT)
481*38fd1498Szrj     return;
482*38fd1498Szrj   if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
483*38fd1498Szrj     return;
484*38fd1498Szrj   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
485*38fd1498Szrj }
486*38fd1498Szrj 
487*38fd1498Szrj /* Same as gen_interclass_conv_libfunc but verify that we are producing
488*38fd1498Szrj    fp->int conversion with no decimal floating point involved.  */
489*38fd1498Szrj 
490*38fd1498Szrj void
gen_fp_to_int_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)491*38fd1498Szrj gen_fp_to_int_conv_libfunc (convert_optab tab,
492*38fd1498Szrj 			    const char *opname,
493*38fd1498Szrj 			    machine_mode tmode,
494*38fd1498Szrj 			    machine_mode fmode)
495*38fd1498Szrj {
496*38fd1498Szrj   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
497*38fd1498Szrj     return;
498*38fd1498Szrj   if (GET_MODE_CLASS (tmode) != MODE_INT)
499*38fd1498Szrj     return;
500*38fd1498Szrj   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
501*38fd1498Szrj }
502*38fd1498Szrj 
503*38fd1498Szrj /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
504*38fd1498Szrj    The string formation rules are
505*38fd1498Szrj    similar to the ones for init_libfunc, above.  */
506*38fd1498Szrj 
507*38fd1498Szrj void
gen_intraclass_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)508*38fd1498Szrj gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
509*38fd1498Szrj 			     machine_mode tmode, machine_mode fmode)
510*38fd1498Szrj {
511*38fd1498Szrj   size_t opname_len = strlen (opname);
512*38fd1498Szrj   size_t mname_len = 0;
513*38fd1498Szrj 
514*38fd1498Szrj   const char *fname, *tname;
515*38fd1498Szrj   const char *q;
516*38fd1498Szrj   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
517*38fd1498Szrj   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
518*38fd1498Szrj   char *libfunc_name, *suffix;
519*38fd1498Szrj   char *p;
520*38fd1498Szrj 
521*38fd1498Szrj   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
522*38fd1498Szrj      depends on which underlying decimal floating point format is used.  */
523*38fd1498Szrj   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
524*38fd1498Szrj 
525*38fd1498Szrj   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
526*38fd1498Szrj 
527*38fd1498Szrj   nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
528*38fd1498Szrj   nondec_name[0] = '_';
529*38fd1498Szrj   nondec_name[1] = '_';
530*38fd1498Szrj   if (targetm.libfunc_gnu_prefix)
531*38fd1498Szrj     {
532*38fd1498Szrj       nondec_name[2] = 'g';
533*38fd1498Szrj       nondec_name[3] = 'n';
534*38fd1498Szrj       nondec_name[4] = 'u';
535*38fd1498Szrj       nondec_name[5] = '_';
536*38fd1498Szrj     }
537*38fd1498Szrj   memcpy (&nondec_name[prefix_len], opname, opname_len);
538*38fd1498Szrj   nondec_suffix = nondec_name + opname_len + prefix_len;
539*38fd1498Szrj 
540*38fd1498Szrj   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
541*38fd1498Szrj   dec_name[0] = '_';
542*38fd1498Szrj   dec_name[1] = '_';
543*38fd1498Szrj   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
544*38fd1498Szrj   memcpy (&dec_name[2 + dec_len], opname, opname_len);
545*38fd1498Szrj   dec_suffix = dec_name + dec_len + opname_len + 2;
546*38fd1498Szrj 
547*38fd1498Szrj   fname = GET_MODE_NAME (fmode);
548*38fd1498Szrj   tname = GET_MODE_NAME (tmode);
549*38fd1498Szrj 
550*38fd1498Szrj   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
551*38fd1498Szrj     {
552*38fd1498Szrj       libfunc_name = dec_name;
553*38fd1498Szrj       suffix = dec_suffix;
554*38fd1498Szrj     }
555*38fd1498Szrj   else
556*38fd1498Szrj     {
557*38fd1498Szrj       libfunc_name = nondec_name;
558*38fd1498Szrj       suffix = nondec_suffix;
559*38fd1498Szrj     }
560*38fd1498Szrj 
561*38fd1498Szrj   p = suffix;
562*38fd1498Szrj   for (q = fname; *q; p++, q++)
563*38fd1498Szrj     *p = TOLOWER (*q);
564*38fd1498Szrj   for (q = tname; *q; p++, q++)
565*38fd1498Szrj     *p = TOLOWER (*q);
566*38fd1498Szrj 
567*38fd1498Szrj   *p++ = '2';
568*38fd1498Szrj   *p = '\0';
569*38fd1498Szrj 
570*38fd1498Szrj   set_conv_libfunc (tab, tmode, fmode,
571*38fd1498Szrj 		    ggc_alloc_string (libfunc_name, p - libfunc_name));
572*38fd1498Szrj }
573*38fd1498Szrj 
574*38fd1498Szrj /* Pick proper libcall for trunc_optab.  We need to chose if we do
575*38fd1498Szrj    truncation or extension and interclass or intraclass.  */
576*38fd1498Szrj 
577*38fd1498Szrj void
gen_trunc_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)578*38fd1498Szrj gen_trunc_conv_libfunc (convert_optab tab,
579*38fd1498Szrj 			const char *opname,
580*38fd1498Szrj 			machine_mode tmode,
581*38fd1498Szrj 			machine_mode fmode)
582*38fd1498Szrj {
583*38fd1498Szrj   scalar_float_mode float_tmode, float_fmode;
584*38fd1498Szrj   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
585*38fd1498Szrj       || !is_a <scalar_float_mode> (tmode, &float_tmode)
586*38fd1498Szrj       || float_tmode == float_fmode)
587*38fd1498Szrj     return;
588*38fd1498Szrj 
589*38fd1498Szrj   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
590*38fd1498Szrj     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
591*38fd1498Szrj 
592*38fd1498Szrj   if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode))
593*38fd1498Szrj     return;
594*38fd1498Szrj 
595*38fd1498Szrj   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
596*38fd1498Szrj     gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
597*38fd1498Szrj }
598*38fd1498Szrj 
599*38fd1498Szrj /* Pick proper libcall for extend_optab.  We need to chose if we do
600*38fd1498Szrj    truncation or extension and interclass or intraclass.  */
601*38fd1498Szrj 
602*38fd1498Szrj void
gen_extend_conv_libfunc(convert_optab tab,const char * opname ATTRIBUTE_UNUSED,machine_mode tmode,machine_mode fmode)603*38fd1498Szrj gen_extend_conv_libfunc (convert_optab tab,
604*38fd1498Szrj 			 const char *opname ATTRIBUTE_UNUSED,
605*38fd1498Szrj 			 machine_mode tmode,
606*38fd1498Szrj 			 machine_mode fmode)
607*38fd1498Szrj {
608*38fd1498Szrj   scalar_float_mode float_tmode, float_fmode;
609*38fd1498Szrj   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
610*38fd1498Szrj       || !is_a <scalar_float_mode> (tmode, &float_tmode)
611*38fd1498Szrj       || float_tmode == float_fmode)
612*38fd1498Szrj     return;
613*38fd1498Szrj 
614*38fd1498Szrj   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
615*38fd1498Szrj     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
616*38fd1498Szrj 
617*38fd1498Szrj   if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
618*38fd1498Szrj     return;
619*38fd1498Szrj 
620*38fd1498Szrj   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
621*38fd1498Szrj     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
622*38fd1498Szrj }
623*38fd1498Szrj 
624*38fd1498Szrj /* Pick proper libcall for fract_optab.  We need to chose if we do
625*38fd1498Szrj    interclass or intraclass.  */
626*38fd1498Szrj 
627*38fd1498Szrj void
gen_fract_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)628*38fd1498Szrj gen_fract_conv_libfunc (convert_optab tab,
629*38fd1498Szrj 			const char *opname,
630*38fd1498Szrj 			machine_mode tmode,
631*38fd1498Szrj 			machine_mode fmode)
632*38fd1498Szrj {
633*38fd1498Szrj   if (tmode == fmode)
634*38fd1498Szrj     return;
635*38fd1498Szrj   if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
636*38fd1498Szrj     return;
637*38fd1498Szrj 
638*38fd1498Szrj   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
639*38fd1498Szrj     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
640*38fd1498Szrj   else
641*38fd1498Szrj     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
642*38fd1498Szrj }
643*38fd1498Szrj 
644*38fd1498Szrj /* Pick proper libcall for fractuns_optab.  */
645*38fd1498Szrj 
646*38fd1498Szrj void
gen_fractuns_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)647*38fd1498Szrj gen_fractuns_conv_libfunc (convert_optab tab,
648*38fd1498Szrj 			   const char *opname,
649*38fd1498Szrj 			   machine_mode tmode,
650*38fd1498Szrj 			   machine_mode fmode)
651*38fd1498Szrj {
652*38fd1498Szrj   if (tmode == fmode)
653*38fd1498Szrj     return;
654*38fd1498Szrj   /* One mode must be a fixed-point mode, and the other must be an integer
655*38fd1498Szrj      mode.  */
656*38fd1498Szrj   if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
657*38fd1498Szrj 	|| (ALL_FIXED_POINT_MODE_P (fmode)
658*38fd1498Szrj 	    && GET_MODE_CLASS (tmode) == MODE_INT)))
659*38fd1498Szrj     return;
660*38fd1498Szrj 
661*38fd1498Szrj   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
662*38fd1498Szrj }
663*38fd1498Szrj 
664*38fd1498Szrj /* Pick proper libcall for satfract_optab.  We need to chose if we do
665*38fd1498Szrj    interclass or intraclass.  */
666*38fd1498Szrj 
667*38fd1498Szrj void
gen_satfract_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)668*38fd1498Szrj gen_satfract_conv_libfunc (convert_optab tab,
669*38fd1498Szrj 			   const char *opname,
670*38fd1498Szrj 			   machine_mode tmode,
671*38fd1498Szrj 			   machine_mode fmode)
672*38fd1498Szrj {
673*38fd1498Szrj   if (tmode == fmode)
674*38fd1498Szrj     return;
675*38fd1498Szrj   /* TMODE must be a fixed-point mode.  */
676*38fd1498Szrj   if (!ALL_FIXED_POINT_MODE_P (tmode))
677*38fd1498Szrj     return;
678*38fd1498Szrj 
679*38fd1498Szrj   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
680*38fd1498Szrj     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
681*38fd1498Szrj   else
682*38fd1498Szrj     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
683*38fd1498Szrj }
684*38fd1498Szrj 
685*38fd1498Szrj /* Pick proper libcall for satfractuns_optab.  */
686*38fd1498Szrj 
687*38fd1498Szrj void
gen_satfractuns_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)688*38fd1498Szrj gen_satfractuns_conv_libfunc (convert_optab tab,
689*38fd1498Szrj 			      const char *opname,
690*38fd1498Szrj 			      machine_mode tmode,
691*38fd1498Szrj 			      machine_mode fmode)
692*38fd1498Szrj {
693*38fd1498Szrj   if (tmode == fmode)
694*38fd1498Szrj     return;
695*38fd1498Szrj   /* TMODE must be a fixed-point mode, and FMODE must be an integer mode.  */
696*38fd1498Szrj   if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
697*38fd1498Szrj     return;
698*38fd1498Szrj 
699*38fd1498Szrj   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
700*38fd1498Szrj }
701*38fd1498Szrj 
702*38fd1498Szrj /* Hashtable callbacks for libfunc_decls.  */
703*38fd1498Szrj 
704*38fd1498Szrj struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
705*38fd1498Szrj {
706*38fd1498Szrj   static hashval_t
hashlibfunc_decl_hasher707*38fd1498Szrj   hash (tree entry)
708*38fd1498Szrj   {
709*38fd1498Szrj     return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
710*38fd1498Szrj   }
711*38fd1498Szrj 
712*38fd1498Szrj   static bool
equallibfunc_decl_hasher713*38fd1498Szrj   equal (tree decl, tree name)
714*38fd1498Szrj   {
715*38fd1498Szrj     return DECL_NAME (decl) == name;
716*38fd1498Szrj   }
717*38fd1498Szrj };
718*38fd1498Szrj 
719*38fd1498Szrj /* A table of previously-created libfuncs, hashed by name.  */
720*38fd1498Szrj static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
721*38fd1498Szrj 
722*38fd1498Szrj /* Build a decl for a libfunc named NAME.  */
723*38fd1498Szrj 
724*38fd1498Szrj tree
build_libfunc_function(const char * name)725*38fd1498Szrj build_libfunc_function (const char *name)
726*38fd1498Szrj {
727*38fd1498Szrj   /* ??? We don't have any type information; pretend this is "int foo ()".  */
728*38fd1498Szrj   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
729*38fd1498Szrj 			  get_identifier (name),
730*38fd1498Szrj 			  build_function_type (integer_type_node, NULL_TREE));
731*38fd1498Szrj   DECL_EXTERNAL (decl) = 1;
732*38fd1498Szrj   TREE_PUBLIC (decl) = 1;
733*38fd1498Szrj   DECL_ARTIFICIAL (decl) = 1;
734*38fd1498Szrj   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
735*38fd1498Szrj   DECL_VISIBILITY_SPECIFIED (decl) = 1;
736*38fd1498Szrj   gcc_assert (DECL_ASSEMBLER_NAME (decl));
737*38fd1498Szrj 
738*38fd1498Szrj   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
739*38fd1498Szrj      are the flags assigned by targetm.encode_section_info.  */
740*38fd1498Szrj   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
741*38fd1498Szrj 
742*38fd1498Szrj   return decl;
743*38fd1498Szrj }
744*38fd1498Szrj 
745*38fd1498Szrj /* Return a libfunc for NAME, creating one if we don't already have one.
746*38fd1498Szrj    The returned rtx is a SYMBOL_REF.  */
747*38fd1498Szrj 
748*38fd1498Szrj rtx
init_one_libfunc(const char * name)749*38fd1498Szrj init_one_libfunc (const char *name)
750*38fd1498Szrj {
751*38fd1498Szrj   tree id, decl;
752*38fd1498Szrj   hashval_t hash;
753*38fd1498Szrj 
754*38fd1498Szrj   if (libfunc_decls == NULL)
755*38fd1498Szrj     libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
756*38fd1498Szrj 
757*38fd1498Szrj   /* See if we have already created a libfunc decl for this function.  */
758*38fd1498Szrj   id = get_identifier (name);
759*38fd1498Szrj   hash = IDENTIFIER_HASH_VALUE (id);
760*38fd1498Szrj   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
761*38fd1498Szrj   decl = *slot;
762*38fd1498Szrj   if (decl == NULL)
763*38fd1498Szrj     {
764*38fd1498Szrj       /* Create a new decl, so that it can be passed to
765*38fd1498Szrj 	 targetm.encode_section_info.  */
766*38fd1498Szrj       decl = build_libfunc_function (name);
767*38fd1498Szrj       *slot = decl;
768*38fd1498Szrj     }
769*38fd1498Szrj   return XEXP (DECL_RTL (decl), 0);
770*38fd1498Szrj }
771*38fd1498Szrj 
772*38fd1498Szrj /* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
773*38fd1498Szrj 
774*38fd1498Szrj rtx
set_user_assembler_libfunc(const char * name,const char * asmspec)775*38fd1498Szrj set_user_assembler_libfunc (const char *name, const char *asmspec)
776*38fd1498Szrj {
777*38fd1498Szrj   tree id, decl;
778*38fd1498Szrj   hashval_t hash;
779*38fd1498Szrj 
780*38fd1498Szrj   id = get_identifier (name);
781*38fd1498Szrj   hash = IDENTIFIER_HASH_VALUE (id);
782*38fd1498Szrj   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
783*38fd1498Szrj   gcc_assert (slot);
784*38fd1498Szrj   decl = (tree) *slot;
785*38fd1498Szrj   set_user_assembler_name (decl, asmspec);
786*38fd1498Szrj   return XEXP (DECL_RTL (decl), 0);
787*38fd1498Szrj }
788*38fd1498Szrj 
789*38fd1498Szrj /* Call this to reset the function entry for one optab (OPTABLE) in mode
790*38fd1498Szrj    MODE to NAME, which should be either 0 or a string constant.  */
791*38fd1498Szrj 
792*38fd1498Szrj void
set_optab_libfunc(optab op,machine_mode mode,const char * name)793*38fd1498Szrj set_optab_libfunc (optab op, machine_mode mode, const char *name)
794*38fd1498Szrj {
795*38fd1498Szrj   rtx val;
796*38fd1498Szrj   struct libfunc_entry e;
797*38fd1498Szrj   struct libfunc_entry **slot;
798*38fd1498Szrj 
799*38fd1498Szrj   e.op = op;
800*38fd1498Szrj   e.mode1 = mode;
801*38fd1498Szrj   e.mode2 = VOIDmode;
802*38fd1498Szrj 
803*38fd1498Szrj   if (name)
804*38fd1498Szrj     val = init_one_libfunc (name);
805*38fd1498Szrj   else
806*38fd1498Szrj     val = 0;
807*38fd1498Szrj   slot = libfunc_hash->find_slot (&e, INSERT);
808*38fd1498Szrj   if (*slot == NULL)
809*38fd1498Szrj     *slot = ggc_alloc<libfunc_entry> ();
810*38fd1498Szrj   (*slot)->op = op;
811*38fd1498Szrj   (*slot)->mode1 = mode;
812*38fd1498Szrj   (*slot)->mode2 = VOIDmode;
813*38fd1498Szrj   (*slot)->libfunc = val;
814*38fd1498Szrj }
815*38fd1498Szrj 
816*38fd1498Szrj /* Call this to reset the function entry for one conversion optab
817*38fd1498Szrj    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
818*38fd1498Szrj    either 0 or a string constant.  */
819*38fd1498Szrj 
820*38fd1498Szrj void
set_conv_libfunc(convert_optab optab,machine_mode tmode,machine_mode fmode,const char * name)821*38fd1498Szrj set_conv_libfunc (convert_optab optab, machine_mode tmode,
822*38fd1498Szrj 		  machine_mode fmode, const char *name)
823*38fd1498Szrj {
824*38fd1498Szrj   rtx val;
825*38fd1498Szrj   struct libfunc_entry e;
826*38fd1498Szrj   struct libfunc_entry **slot;
827*38fd1498Szrj 
828*38fd1498Szrj   e.op = optab;
829*38fd1498Szrj   e.mode1 = tmode;
830*38fd1498Szrj   e.mode2 = fmode;
831*38fd1498Szrj 
832*38fd1498Szrj   if (name)
833*38fd1498Szrj     val = init_one_libfunc (name);
834*38fd1498Szrj   else
835*38fd1498Szrj     val = 0;
836*38fd1498Szrj   slot = libfunc_hash->find_slot (&e, INSERT);
837*38fd1498Szrj   if (*slot == NULL)
838*38fd1498Szrj     *slot = ggc_alloc<libfunc_entry> ();
839*38fd1498Szrj   (*slot)->op = optab;
840*38fd1498Szrj   (*slot)->mode1 = tmode;
841*38fd1498Szrj   (*slot)->mode2 = fmode;
842*38fd1498Szrj   (*slot)->libfunc = val;
843*38fd1498Szrj }
844*38fd1498Szrj 
845*38fd1498Szrj /* Call this to initialize the contents of the optabs
846*38fd1498Szrj    appropriately for the current target machine.  */
847*38fd1498Szrj 
848*38fd1498Szrj void
init_optabs(void)849*38fd1498Szrj init_optabs (void)
850*38fd1498Szrj {
851*38fd1498Szrj   if (libfunc_hash)
852*38fd1498Szrj     libfunc_hash->empty ();
853*38fd1498Szrj   else
854*38fd1498Szrj     libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
855*38fd1498Szrj 
856*38fd1498Szrj   /* Fill in the optabs with the insns we support.  */
857*38fd1498Szrj   init_all_optabs (this_fn_optabs);
858*38fd1498Szrj 
859*38fd1498Szrj   /* The ffs function operates on `int'.  Fall back on it if we do not
860*38fd1498Szrj      have a libgcc2 function for that width.  */
861*38fd1498Szrj   if (INT_TYPE_SIZE < BITS_PER_WORD)
862*38fd1498Szrj     {
863*38fd1498Szrj       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
864*38fd1498Szrj       set_optab_libfunc (ffs_optab, mode, "ffs");
865*38fd1498Szrj     }
866*38fd1498Szrj 
867*38fd1498Szrj   /* Explicitly initialize the bswap libfuncs since we need them to be
868*38fd1498Szrj      valid for things other than word_mode.  */
869*38fd1498Szrj   if (targetm.libfunc_gnu_prefix)
870*38fd1498Szrj     {
871*38fd1498Szrj       set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
872*38fd1498Szrj       set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
873*38fd1498Szrj     }
874*38fd1498Szrj   else
875*38fd1498Szrj     {
876*38fd1498Szrj       set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
877*38fd1498Szrj       set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
878*38fd1498Szrj     }
879*38fd1498Szrj 
880*38fd1498Szrj   /* Use cabs for double complex abs, since systems generally have cabs.
881*38fd1498Szrj      Don't define any libcall for float complex, so that cabs will be used.  */
882*38fd1498Szrj   if (complex_double_type_node)
883*38fd1498Szrj     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
884*38fd1498Szrj 		       "cabs");
885*38fd1498Szrj 
886*38fd1498Szrj   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
887*38fd1498Szrj   unwind_sjlj_unregister_libfunc
888*38fd1498Szrj     = init_one_libfunc ("_Unwind_SjLj_Unregister");
889*38fd1498Szrj 
890*38fd1498Szrj   /* Allow the target to add more libcalls or rename some, etc.  */
891*38fd1498Szrj   targetm.init_libfuncs ();
892*38fd1498Szrj }
893*38fd1498Szrj 
894*38fd1498Szrj /* A helper function for init_sync_libfuncs.  Using the basename BASE,
895*38fd1498Szrj    install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
896*38fd1498Szrj 
897*38fd1498Szrj static void
init_sync_libfuncs_1(optab tab,const char * base,int max)898*38fd1498Szrj init_sync_libfuncs_1 (optab tab, const char *base, int max)
899*38fd1498Szrj {
900*38fd1498Szrj   machine_mode mode;
901*38fd1498Szrj   char buf[64];
902*38fd1498Szrj   size_t len = strlen (base);
903*38fd1498Szrj   int i;
904*38fd1498Szrj 
905*38fd1498Szrj   gcc_assert (max <= 8);
906*38fd1498Szrj   gcc_assert (len + 3 < sizeof (buf));
907*38fd1498Szrj 
908*38fd1498Szrj   memcpy (buf, base, len);
909*38fd1498Szrj   buf[len] = '_';
910*38fd1498Szrj   buf[len + 1] = '0';
911*38fd1498Szrj   buf[len + 2] = '\0';
912*38fd1498Szrj 
913*38fd1498Szrj   mode = QImode;
914*38fd1498Szrj   for (i = 1; i <= max; i *= 2)
915*38fd1498Szrj     {
916*38fd1498Szrj       if (i > 1)
917*38fd1498Szrj 	mode = GET_MODE_2XWIDER_MODE (mode).require ();
918*38fd1498Szrj       buf[len + 1] = '0' + i;
919*38fd1498Szrj       set_optab_libfunc (tab, mode, buf);
920*38fd1498Szrj     }
921*38fd1498Szrj }
922*38fd1498Szrj 
923*38fd1498Szrj void
init_sync_libfuncs(int max)924*38fd1498Szrj init_sync_libfuncs (int max)
925*38fd1498Szrj {
926*38fd1498Szrj   if (!flag_sync_libcalls)
927*38fd1498Szrj     return;
928*38fd1498Szrj 
929*38fd1498Szrj   init_sync_libfuncs_1 (sync_compare_and_swap_optab,
930*38fd1498Szrj 			"__sync_val_compare_and_swap", max);
931*38fd1498Szrj   init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
932*38fd1498Szrj 			"__sync_lock_test_and_set", max);
933*38fd1498Szrj 
934*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
935*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
936*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
937*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
938*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
939*38fd1498Szrj   init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
940*38fd1498Szrj 
941*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
942*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
943*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
944*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
945*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
946*38fd1498Szrj   init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
947*38fd1498Szrj }
948*38fd1498Szrj 
949*38fd1498Szrj #include "gt-optabs-libfuncs.h"
950