]> gcc.gnu.org Git - gcc.git/blame - gcc/genopinit.c
(smul_highpart_optab, umul_highpart_optab): New variables.
[gcc.git] / gcc / genopinit.c
CommitLineData
af9e4a0c 1/* Generate code to initialize optabs from machine description.
5f54da49 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
af9e4a0c
RK
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <stdio.h>
22#include "hconfig.h"
23#include "rtl.h"
24#include "obstack.h"
25#include <ctype.h>
26
27static struct obstack obstack;
28struct obstack *rtl_obstack = &obstack;
29
30#define obstack_chunk_alloc xmalloc
31#define obstack_chunk_free free
32
33extern void free ();
34extern rtx read_rtx ();
35
36char *xmalloc ();
37static void fatal ();
38void fancy_abort ();
39
40/* Many parts of GCC use arrays that are indexed by machine mode and
41 contain the insn codes for pattern in the MD file that perform a given
42 operation on operands of that mode.
43
44 These patterns are present in the MD file with names that contain
45 the mode(s) used and the name of the operation. This program
46 writes a function `init_all_optabs' that initializes the optabs with
47 all the insn codes of the relevant patterns present in the MD file.
48
49 This array contains a list of optabs that need to be initialized. Within
50 each string, the name of the pattern to be matched against is delimited
51 with %( and %). In the string, %a and %b are used to match a short mode
52 name (the part of the mode name not including `mode' and converted to
53 lower-case). When writing out the initializer, the entire string is
54 used. %A and %B are replaced with the full name of the mode; %a and %b
55 are replaced with the short form of the name, as above.
56
57 If %N is present in the pattern, it means the two modes must be consecutive
58 widths in the same mode class (e.g, QImode and HImode). %I means that
59 only integer modes should be considered for the next mode, and %F means
60 that only float modes should be considered.
61
62 For some optabs, we store the operation by RTL codes. These are only
63 used for comparisons. In that case, %c and %C are the lower-case and
64 upper-case forms of the comparison, respectively. */
65
8c9881d1
RS
66/* The reason we use \% is to avoid sequences of the form %-capletter-%
67 which SCCS treats as magic. This gets warnings which you should ignore. */
68
af9e4a0c 69char *optabs[] =
8c9881d1
RS
70{ "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)",
71 "extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)",
72 "fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)",
73 "fixtab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns%F\%a%b2%)",
74 "fixtrunctab[(int) %A][(int) %B][0] = CODE_FOR_%(fix_trunc%F\%a%I\%b2%)",
75 "fixtrunctab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns_trunc%F\%a%I\%b2%)",
76 "floattab[(int) %B][(int) %A][0] = CODE_FOR_%(float%I\%a%F\%b2%)",
53f26922 77 "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)",
af9e4a0c
RK
78 "add_optab->handlers[(int) %A].insn_code = CODE_FOR_%(add%a3%)",
79 "sub_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sub%a3%)",
80 "smul_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mul%a3%)",
81 "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N",
82 "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N",
8c9881d1
RS
83 "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)",
84 "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)",
af9e4a0c
RK
85 "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)",
86 "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)",
87 "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)",
88 "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)",
8c9881d1
RS
89 "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)",
90 "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)",
af9e4a0c
RK
91 "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)",
92 "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)",
93 "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)",
94 "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)",
95 "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)",
af9e4a0c
RK
96 "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)",
97 "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)",
98 "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)",
8c9881d1
RS
99 "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)",
100 "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)",
101 "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)",
102 "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)",
103 "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)",
104 "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)",
af9e4a0c
RK
105 "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)",
106 "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)",
107 "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)",
108 "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)",
109 "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)",
ed58a128 110 "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
af9e4a0c
RK
111 "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)",
112 "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)",
113 "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)",
114 "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)",
115 "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)",
116 "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)",
117 "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
118 "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
119 "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
120 "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
121 "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)" };
122
53f26922
RS
123/* Allow linking with print-rtl.c. */
124char **insn_name_ptr;
125
af9e4a0c
RK
126static void
127gen_insn (insn)
128 rtx insn;
129{
130 char *name = XSTR (insn, 0);
131 int m1, m2, op;
132 int pindex;
133 int i;
134 char *np, *pp, *p, *q;
135 struct obstack *obstack_ptr;
136
137 /* Don't mention instructions whose names are the null string.
138 They are in the machine description just to be recognized. */
139 if (*name == 0)
140 return;
141
142 /* See if NAME matches one of the patterns we have for the optabs we know
143 about. */
144
145 for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
146 {
147 int force_float = 0, force_int = 0;
148 int force_consec = 0;
149 int matches = 1;
150
151 for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
152 ;
153
154 for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
155 pp++)
156 {
157 if (*pp != '%')
158 {
159 if (*pp != *np++)
160 break;
161 }
162 else
163 switch (*++pp)
164 {
165 case 'N':
166 force_consec = 1;
167 break;
168 case 'I':
169 force_int = 1;
170 break;
171 case 'F':
172 force_float = 1;
173 break;
174 case 'c':
175 for (op = 0; op < NUM_RTX_CODE; op++)
176 {
177 for (p = rtx_name[op], q = np; *p; p++, q++)
178 if (*p != *q)
179 break;
180
181 /* We have to be concerned about matching "gt" and
182 missing "gtu", e.g., so verify we have reached the
183 end of thing we are to match. We do not have this
184 problem with modes since no mode is a prefix of
185 another. */
186 if (*p == 0 && *q == 0 && rtx_class[op] == '<')
187 break;
188 }
189
190 if (op == NUM_RTX_CODE)
191 matches = 0;
192 else
193 np += strlen (rtx_name[op]);
194 break;
195 case 'a':
196 case 'b':
197 for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
198 {
199 for (p = mode_name[i], q = np; *p; p++, q++)
200 if (tolower (*p) != *q)
201 break;
202
203 if (*p == 0
204 && (! force_int || mode_class[i] == MODE_INT)
205 && (! force_float || mode_class[i] == MODE_FLOAT))
206 break;
207 }
208
209 if (i == (int) MAX_MACHINE_MODE)
210 matches = 0;
211 else if (*pp == 'a')
212 m1 = i, np += strlen (mode_name[i]);
213 else
214 m2 = i, np += strlen (mode_name[i]);
215
216 force_int = force_float = 0;
217 break;
218
219 default:
220 abort ();
221 }
222 }
223
224 if (matches && pp[0] == '%' && pp[1] == ')'
225 && *np == 0
226 && (! force_consec || (int) mode_wider_mode[m1] == m2))
227 break;
228 }
229
230 if (pindex == sizeof optabs / sizeof optabs[0])
231 return;
232
233 /* We found a match. If this pattern is only conditionally present,
234 write out the "if" and two extra blanks. */
235
236 if (*XSTR (insn, 2) != 0)
237 printf (" if (HAVE_%s)\n ", name);
238
239 printf (" ");
240
241 /* Now write out the initialization, making all required substitutions. */
242 for (pp = optabs[pindex]; *pp; pp++)
243 {
244 if (*pp != '%')
245 printf ("%c", *pp);
246 else
247 switch (*++pp)
248 {
249 case '(': case ')':
250 case 'I': case 'F': case 'N':
251 break;
252 case 'a':
253 for (np = mode_name[m1]; *np; np++)
254 printf ("%c", tolower (*np));
255 break;
256 case 'b':
257 for (np = mode_name[m2]; *np; np++)
258 printf ("%c", tolower (*np));
259 break;
260 case 'A':
261 printf ("%smode", mode_name[m1]);
262 break;
263 case 'B':
264 printf ("%smode", mode_name[m2]);
265 break;
266 case 'c':
267 printf ("%s", rtx_name[op]);
268 break;
269 case 'C':
270 for (np = rtx_name[op]; *np; np++)
271 printf ("%c", toupper (*np));
272 break;
273 }
274 }
275
276 printf (";\n");
277}
278\f
279char *
280xmalloc (size)
281 unsigned size;
282{
283 register char *val = (char *) malloc (size);
284
285 if (val == 0)
286 fatal ("virtual memory exhausted");
287
288 return val;
289}
290
291char *
292xrealloc (ptr, size)
293 char *ptr;
294 unsigned size;
295{
296 char *result = (char *) realloc (ptr, size);
297 if (!result)
298 fatal ("virtual memory exhausted");
299 return result;
300}
301
302static void
303fatal (s, a1, a2)
304 char *s;
305{
306 fprintf (stderr, "genopinit: ");
307 fprintf (stderr, s, a1, a2);
308 fprintf (stderr, "\n");
309 exit (FATAL_EXIT_CODE);
310}
311
312/* More 'friendly' abort that prints the line and file.
313 config.h can #define abort fancy_abort if you like that sort of thing. */
314
315void
316fancy_abort ()
317{
318 fatal ("Internal gcc abort.");
319}
320\f
321int
322main (argc, argv)
323 int argc;
324 char **argv;
325{
326 rtx desc;
327 rtx dummy;
328 rtx *insn_ptr;
329 FILE *infile;
330 register int c;
331
332 obstack_init (rtl_obstack);
333
334 if (argc <= 1)
335 fatal ("No input file name.");
336
337 infile = fopen (argv[1], "r");
338 if (infile == 0)
339 {
340 perror (argv[1]);
341 exit (FATAL_EXIT_CODE);
342 }
343
344 init_rtl ();
345
346 printf ("/* Generated automatically by the program `genopinit'\n\
347from the machine description file `md'. */\n\n");
348
349 printf ("#include \"config.h\"\n");
350 printf ("#include \"rtl.h\"\n");
351 printf ("#include \"flags.h\"\n");
352 printf ("#include \"insn-flags.h\"\n");
353 printf ("#include \"insn-codes.h\"\n");
354 printf ("#include \"insn-config.h\"\n");
355 printf ("#include \"recog.h\"\n");
356 printf ("#include \"expr.h\"\n");
357 printf ("#include \"reload.h\"\n\n");
358
359 printf ("void\ninit_all_optabs ()\n{\n");
360
361 /* Read the machine description. */
362
363 while (1)
364 {
365 c = read_skip_spaces (infile);
366 if (c == EOF)
367 break;
368 ungetc (c, infile);
369
370 desc = read_rtx (infile);
371 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
372 gen_insn (desc);
373 }
374
375 printf ("}\n");
376
377 fflush (stdout);
378 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
379 /* NOTREACHED */
380 return 0;
381}
This page took 0.161066 seconds and 5 git commands to generate.