OSDN Git Service

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