Mercurial > hg > CbC > CbC_gcc
comparison gcc/optabs-libfuncs.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Mapping from optabs to underlying library functions | |
2 Copyright (C) 1987-2017 Free Software Foundation, Inc. | |
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 | |
722 /* Build a decl for a libfunc named NAME. */ | |
723 | |
724 tree | |
725 build_libfunc_function (const char *name) | |
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; | |
734 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; | |
735 DECL_VISIBILITY_SPECIFIED (decl) = 1; | |
736 gcc_assert (DECL_ASSEMBLER_NAME (decl)); | |
737 | |
738 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with | |
739 are the flags assigned by targetm.encode_section_info. */ | |
740 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL); | |
741 | |
742 return decl; | |
743 } | |
744 | |
745 /* Return a libfunc for NAME, creating one if we don't already have one. | |
746 The returned rtx is a SYMBOL_REF. */ | |
747 | |
748 rtx | |
749 init_one_libfunc (const char *name) | |
750 { | |
751 tree id, decl; | |
752 hashval_t hash; | |
753 | |
754 if (libfunc_decls == NULL) | |
755 libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37); | |
756 | |
757 /* See if we have already created a libfunc decl for this function. */ | |
758 id = get_identifier (name); | |
759 hash = IDENTIFIER_HASH_VALUE (id); | |
760 tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT); | |
761 decl = *slot; | |
762 if (decl == NULL) | |
763 { | |
764 /* Create a new decl, so that it can be passed to | |
765 targetm.encode_section_info. */ | |
766 decl = build_libfunc_function (name); | |
767 *slot = decl; | |
768 } | |
769 return XEXP (DECL_RTL (decl), 0); | |
770 } | |
771 | |
772 /* Adjust the assembler name of libfunc NAME to ASMSPEC. */ | |
773 | |
774 rtx | |
775 set_user_assembler_libfunc (const char *name, const char *asmspec) | |
776 { | |
777 tree id, decl; | |
778 hashval_t hash; | |
779 | |
780 id = get_identifier (name); | |
781 hash = IDENTIFIER_HASH_VALUE (id); | |
782 tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT); | |
783 gcc_assert (slot); | |
784 decl = (tree) *slot; | |
785 set_user_assembler_name (decl, asmspec); | |
786 return XEXP (DECL_RTL (decl), 0); | |
787 } | |
788 | |
789 /* Call this to reset the function entry for one optab (OPTABLE) in mode | |
790 MODE to NAME, which should be either 0 or a string constant. */ | |
791 | |
792 void | |
793 set_optab_libfunc (optab op, machine_mode mode, const char *name) | |
794 { | |
795 rtx val; | |
796 struct libfunc_entry e; | |
797 struct libfunc_entry **slot; | |
798 | |
799 e.op = op; | |
800 e.mode1 = mode; | |
801 e.mode2 = VOIDmode; | |
802 | |
803 if (name) | |
804 val = init_one_libfunc (name); | |
805 else | |
806 val = 0; | |
807 slot = libfunc_hash->find_slot (&e, INSERT); | |
808 if (*slot == NULL) | |
809 *slot = ggc_alloc<libfunc_entry> (); | |
810 (*slot)->op = op; | |
811 (*slot)->mode1 = mode; | |
812 (*slot)->mode2 = VOIDmode; | |
813 (*slot)->libfunc = val; | |
814 } | |
815 | |
816 /* Call this to reset the function entry for one conversion optab | |
817 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be | |
818 either 0 or a string constant. */ | |
819 | |
820 void | |
821 set_conv_libfunc (convert_optab optab, machine_mode tmode, | |
822 machine_mode fmode, const char *name) | |
823 { | |
824 rtx val; | |
825 struct libfunc_entry e; | |
826 struct libfunc_entry **slot; | |
827 | |
828 e.op = optab; | |
829 e.mode1 = tmode; | |
830 e.mode2 = fmode; | |
831 | |
832 if (name) | |
833 val = init_one_libfunc (name); | |
834 else | |
835 val = 0; | |
836 slot = libfunc_hash->find_slot (&e, INSERT); | |
837 if (*slot == NULL) | |
838 *slot = ggc_alloc<libfunc_entry> (); | |
839 (*slot)->op = optab; | |
840 (*slot)->mode1 = tmode; | |
841 (*slot)->mode2 = fmode; | |
842 (*slot)->libfunc = val; | |
843 } | |
844 | |
845 /* Call this to initialize the contents of the optabs | |
846 appropriately for the current target machine. */ | |
847 | |
848 void | |
849 init_optabs (void) | |
850 { | |
851 if (libfunc_hash) | |
852 libfunc_hash->empty (); | |
853 else | |
854 libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10); | |
855 | |
856 /* Fill in the optabs with the insns we support. */ | |
857 init_all_optabs (this_fn_optabs); | |
858 | |
859 /* The ffs function operates on `int'. Fall back on it if we do not | |
860 have a libgcc2 function for that width. */ | |
861 if (INT_TYPE_SIZE < BITS_PER_WORD) | |
862 { | |
863 scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require (); | |
864 set_optab_libfunc (ffs_optab, mode, "ffs"); | |
865 } | |
866 | |
867 /* Explicitly initialize the bswap libfuncs since we need them to be | |
868 valid for things other than word_mode. */ | |
869 if (targetm.libfunc_gnu_prefix) | |
870 { | |
871 set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2"); | |
872 set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2"); | |
873 } | |
874 else | |
875 { | |
876 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2"); | |
877 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2"); | |
878 } | |
879 | |
880 /* Use cabs for double complex abs, since systems generally have cabs. | |
881 Don't define any libcall for float complex, so that cabs will be used. */ | |
882 if (complex_double_type_node) | |
883 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), | |
884 "cabs"); | |
885 | |
886 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register"); | |
887 unwind_sjlj_unregister_libfunc | |
888 = init_one_libfunc ("_Unwind_SjLj_Unregister"); | |
889 | |
890 /* Allow the target to add more libcalls or rename some, etc. */ | |
891 targetm.init_libfuncs (); | |
892 } | |
893 | |
894 /* A helper function for init_sync_libfuncs. Using the basename BASE, | |
895 install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */ | |
896 | |
897 static void | |
898 init_sync_libfuncs_1 (optab tab, const char *base, int max) | |
899 { | |
900 machine_mode mode; | |
901 char buf[64]; | |
902 size_t len = strlen (base); | |
903 int i; | |
904 | |
905 gcc_assert (max <= 8); | |
906 gcc_assert (len + 3 < sizeof (buf)); | |
907 | |
908 memcpy (buf, base, len); | |
909 buf[len] = '_'; | |
910 buf[len + 1] = '0'; | |
911 buf[len + 2] = '\0'; | |
912 | |
913 mode = QImode; | |
914 for (i = 1; i <= max; i *= 2) | |
915 { | |
916 if (i > 1) | |
917 mode = GET_MODE_2XWIDER_MODE (mode).require (); | |
918 buf[len + 1] = '0' + i; | |
919 set_optab_libfunc (tab, mode, buf); | |
920 } | |
921 } | |
922 | |
923 void | |
924 init_sync_libfuncs (int max) | |
925 { | |
926 if (!flag_sync_libcalls) | |
927 return; | |
928 | |
929 init_sync_libfuncs_1 (sync_compare_and_swap_optab, | |
930 "__sync_val_compare_and_swap", max); | |
931 init_sync_libfuncs_1 (sync_lock_test_and_set_optab, | |
932 "__sync_lock_test_and_set", max); | |
933 | |
934 init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max); | |
935 init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max); | |
936 init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max); | |
937 init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max); | |
938 init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max); | |
939 init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max); | |
940 | |
941 init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max); | |
942 init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max); | |
943 init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max); | |
944 init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max); | |
945 init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max); | |
946 init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max); | |
947 } | |
948 | |
949 #include "gt-optabs-libfuncs.h" |