OSDN Git Service

13f3b231a05b3979ae03df3d279d3e4c846e9834
[pf3gnuchains/gcc-fork.git] / gcc / genopinit.c
1 /* Generate code to initialize optabs from machine description.
2    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the 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
27 static struct obstack obstack;
28 struct obstack *rtl_obstack = &obstack;
29
30 #define obstack_chunk_alloc xmalloc
31 #define obstack_chunk_free free
32
33 extern void free ();
34 extern rtx read_rtx ();
35
36 char *xmalloc ();
37 static void fatal ();
38 void 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
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
69 char *optabs[] =
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%)",
77   "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)",
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",
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%)",
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%)",
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%)",
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%)",
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%)",
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%)",
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%)",
110   "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
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
123 /* Allow linking with print-rtl.c.  */
124 char **insn_name_ptr;
125
126 static void
127 gen_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
279 char *
280 xmalloc (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
291 char *
292 xrealloc (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
302 static void
303 fatal (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
315 void
316 fancy_abort ()
317 {
318   fatal ("Internal gcc abort.");
319 }
320 \f
321 int
322 main (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\
347 from 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 }