OSDN Git Service

(ENDFILE_SPEC): Add missing `%s'.
[pf3gnuchains/gcc-fork.git] / gcc / genopinit.c
1 /* Generate code to initialize optabs from machine description.
2    Copyright (C) 1993, 1994, 1995 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   "clrstr_optab[(int) %A] = CODE_FOR_%(clrstr%a%)" };
127
128 /* Allow linking with print-rtl.c.  */
129 char **insn_name_ptr;
130
131 static void
132 gen_insn (insn)
133      rtx insn;
134 {
135   char *name = XSTR (insn, 0);
136   int m1, m2, op;
137   int pindex;
138   int i;
139   char *np, *pp, *p, *q;
140   struct obstack *obstack_ptr;
141
142   /* Don't mention instructions whose names are the null string.
143      They are in the machine description just to be recognized.  */
144   if (*name == 0)
145     return;
146
147   /* See if NAME matches one of the patterns we have for the optabs we know
148      about.  */
149
150   for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
151     {
152       int force_float = 0, force_int = 0;
153       int force_consec = 0;
154       int matches = 1;
155
156       for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
157         ;
158
159       for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
160            pp++)
161         {
162           if (*pp != '%')
163             {
164               if (*pp != *np++)
165                 break;
166             }
167           else
168             switch (*++pp)
169               {
170               case 'N':
171                 force_consec = 1;
172                 break;
173               case 'I':
174                 force_int = 1;
175                 break;
176               case 'F':
177                 force_float = 1;
178                 break;
179               case 'c':
180                 for (op = 0; op < NUM_RTX_CODE; op++)
181                   {
182                     for (p = rtx_name[op], q = np; *p; p++, q++)
183                       if (*p != *q)
184                         break;
185
186                     /* We have to be concerned about matching "gt" and
187                        missing "gtu", e.g., so verify we have reached the
188                        end of thing we are to match.  We do not have this
189                        problem with modes since no mode is a prefix of
190                        another.  */
191                     if (*p == 0 && *q == 0 && rtx_class[op] == '<')
192                       break;
193                   }
194
195                 if (op == NUM_RTX_CODE)
196                   matches = 0;
197                 else
198                   np += strlen (rtx_name[op]);
199                 break;
200               case 'a':
201               case 'b':
202                 for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
203                   {
204                     for (p = mode_name[i], q = np; *p; p++, q++)
205                       if (tolower (*p) != *q)
206                         break;
207
208                     if (*p == 0
209                         && (! force_int || mode_class[i] == MODE_INT)
210                         && (! force_float || mode_class[i] == MODE_FLOAT))
211                       break;
212                   }
213
214                 if (i == (int) MAX_MACHINE_MODE)
215                   matches = 0;
216                 else if (*pp == 'a')
217                   m1 = i, np += strlen (mode_name[i]);
218                 else
219                   m2 = i, np += strlen (mode_name[i]);
220
221                 force_int = force_float = 0;
222                 break;
223
224               default:
225                 abort ();
226               }
227         }
228
229       if (matches && pp[0] == '%' && pp[1] == ')'
230           && *np == 0
231           && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
232         break;
233     }
234
235   if (pindex == sizeof optabs / sizeof optabs[0])
236     return;
237
238   /* We found a match.  If this pattern is only conditionally present,
239      write out the "if" and two extra blanks.  */
240
241   if (*XSTR (insn, 2) != 0)
242     printf ("  if (HAVE_%s)\n  ", name);
243
244   printf ("  ");
245
246   /* Now write out the initialization, making all required substitutions.  */
247   for (pp = optabs[pindex]; *pp; pp++)
248     {
249       if (*pp != '%')
250         printf ("%c", *pp);
251       else
252         switch (*++pp)
253           {
254           case '(':  case ')':
255           case 'I':  case 'F':  case 'N':
256             break;
257           case 'a':
258             for (np = mode_name[m1]; *np; np++)
259               printf ("%c", tolower (*np));
260             break;
261           case 'b':
262             for (np = mode_name[m2]; *np; np++)
263               printf ("%c", tolower (*np));
264             break;
265           case 'A':
266             printf ("%smode", mode_name[m1]);
267             break;
268           case 'B':
269             printf ("%smode", mode_name[m2]);
270             break;
271           case 'c':
272             printf ("%s", rtx_name[op]);
273             break;
274           case 'C':
275             for (np = rtx_name[op]; *np; np++)
276               printf ("%c", toupper (*np));
277             break;
278           }
279     }
280
281   printf (";\n");
282 }
283 \f
284 char *
285 xmalloc (size)
286      unsigned size;
287 {
288   register char *val = (char *) malloc (size);
289
290   if (val == 0)
291     fatal ("virtual memory exhausted");
292
293   return val;
294 }
295
296 char *
297 xrealloc (ptr, size)
298      char *ptr;
299      unsigned size;
300 {
301   char *result = (char *) realloc (ptr, size);
302   if (!result)
303     fatal ("virtual memory exhausted");
304   return result;
305 }
306
307 static void
308 fatal (s, a1, a2)
309      char *s;
310 {
311   fprintf (stderr, "genopinit: ");
312   fprintf (stderr, s, a1, a2);
313   fprintf (stderr, "\n");
314   exit (FATAL_EXIT_CODE);
315 }
316
317 /* More 'friendly' abort that prints the line and file.
318    config.h can #define abort fancy_abort if you like that sort of thing.  */
319
320 void
321 fancy_abort ()
322 {
323   fatal ("Internal gcc abort.");
324 }
325 \f
326 int
327 main (argc, argv)
328      int argc;
329      char **argv;
330 {
331   rtx desc;
332   rtx dummy;
333   rtx *insn_ptr;
334   FILE *infile;
335   register int c;
336
337   obstack_init (rtl_obstack);
338
339   if (argc <= 1)
340     fatal ("No input file name.");
341
342   infile = fopen (argv[1], "r");
343   if (infile == 0)
344     {
345       perror (argv[1]);
346       exit (FATAL_EXIT_CODE);
347     }
348
349   init_rtl ();
350
351   printf ("/* Generated automatically by the program `genopinit'\n\
352 from the machine description file `md'.  */\n\n");
353
354   printf ("#include \"config.h\"\n");
355   printf ("#include \"rtl.h\"\n");
356   printf ("#include \"flags.h\"\n");
357   printf ("#include \"insn-flags.h\"\n");
358   printf ("#include \"insn-codes.h\"\n");
359   printf ("#include \"insn-config.h\"\n");
360   printf ("#include \"recog.h\"\n");
361   printf ("#include \"expr.h\"\n");
362   printf ("#include \"reload.h\"\n\n");
363
364   printf ("void\ninit_all_optabs ()\n{\n");
365
366   /* Read the machine description.  */
367
368   while (1)
369     {
370       c = read_skip_spaces (infile);
371       if (c == EOF)
372         break;
373       ungetc (c, infile);
374
375       desc = read_rtx (infile);
376       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
377         gen_insn (desc);
378     }
379
380   printf ("}\n");
381
382   fflush (stdout);
383   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
384   /* NOTREACHED */
385   return 0;
386 }