annotate gcc/optabs-libfuncs.c @ 131:84e7813d76e9

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