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