OSDN Git Service

(optabs): Add [us]mul_highpart_optab.
[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   "umul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umul%a3_highpart%)",
82   "smul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smul%a3_highpart%)",
83   "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N",
84   "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N",
85   "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)",
86   "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)",
87   "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)",
88   "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)",
89   "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)",
90   "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)",
91   "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)",
92   "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)",
93   "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)",
94   "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)",
95   "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)",
96   "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)",
97   "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)",
98   "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)",
99   "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)",
100   "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)",
101   "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)",
102   "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)",
103   "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)",
104   "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)",
105   "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)",
106   "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)",
107   "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)",
108   "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)",
109   "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)",
110   "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)",
111   "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)",
112   "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
113   "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)",
114   "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)",
115   "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)",
116   "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)",
117   "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)",
118   "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)",
119   "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
120   "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
121   "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
122   "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
123   "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)" };
124
125 /* Allow linking with print-rtl.c.  */
126 char **insn_name_ptr;
127
128 static void
129 gen_insn (insn)
130      rtx insn;
131 {
132   char *name = XSTR (insn, 0);
133   int m1, m2, op;
134   int pindex;
135   int i;
136   char *np, *pp, *p, *q;
137   struct obstack *obstack_ptr;
138
139   /* Don't mention instructions whose names are the null string.
140      They are in the machine description just to be recognized.  */
141   if (*name == 0)
142     return;
143
144   /* See if NAME matches one of the patterns we have for the optabs we know
145      about.  */
146
147   for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
148     {
149       int force_float = 0, force_int = 0;
150       int force_consec = 0;
151       int matches = 1;
152
153       for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
154         ;
155
156       for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
157            pp++)
158         {
159           if (*pp != '%')
160             {
161               if (*pp != *np++)
162                 break;
163             }
164           else
165             switch (*++pp)
166               {
167               case 'N':
168                 force_consec = 1;
169                 break;
170               case 'I':
171                 force_int = 1;
172                 break;
173               case 'F':
174                 force_float = 1;
175                 break;
176               case 'c':
177                 for (op = 0; op < NUM_RTX_CODE; op++)
178                   {
179                     for (p = rtx_name[op], q = np; *p; p++, q++)
180                       if (*p != *q)
181                         break;
182
183                     /* We have to be concerned about matching "gt" and
184                        missing "gtu", e.g., so verify we have reached the
185                        end of thing we are to match.  We do not have this
186                        problem with modes since no mode is a prefix of
187                        another.  */
188                     if (*p == 0 && *q == 0 && rtx_class[op] == '<')
189                       break;
190                   }
191
192                 if (op == NUM_RTX_CODE)
193                   matches = 0;
194                 else
195                   np += strlen (rtx_name[op]);
196                 break;
197               case 'a':
198               case 'b':
199                 for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
200                   {
201                     for (p = mode_name[i], q = np; *p; p++, q++)
202                       if (tolower (*p) != *q)
203                         break;
204
205                     if (*p == 0
206                         && (! force_int || mode_class[i] == MODE_INT)
207                         && (! force_float || mode_class[i] == MODE_FLOAT))
208                       break;
209                   }
210
211                 if (i == (int) MAX_MACHINE_MODE)
212                   matches = 0;
213                 else if (*pp == 'a')
214                   m1 = i, np += strlen (mode_name[i]);
215                 else
216                   m2 = i, np += strlen (mode_name[i]);
217
218                 force_int = force_float = 0;
219                 break;
220
221               default:
222                 abort ();
223               }
224         }
225
226       if (matches && pp[0] == '%' && pp[1] == ')'
227           && *np == 0
228           && (! force_consec || (int) mode_wider_mode[m1] == m2))
229         break;
230     }
231
232   if (pindex == sizeof optabs / sizeof optabs[0])
233     return;
234
235   /* We found a match.  If this pattern is only conditionally present,
236      write out the "if" and two extra blanks.  */
237
238   if (*XSTR (insn, 2) != 0)
239     printf ("  if (HAVE_%s)\n  ", name);
240
241   printf ("  ");
242
243   /* Now write out the initialization, making all required substitutions.  */
244   for (pp = optabs[pindex]; *pp; pp++)
245     {
246       if (*pp != '%')
247         printf ("%c", *pp);
248       else
249         switch (*++pp)
250           {
251           case '(':  case ')':
252           case 'I':  case 'F':  case 'N':
253             break;
254           case 'a':
255             for (np = mode_name[m1]; *np; np++)
256               printf ("%c", tolower (*np));
257             break;
258           case 'b':
259             for (np = mode_name[m2]; *np; np++)
260               printf ("%c", tolower (*np));
261             break;
262           case 'A':
263             printf ("%smode", mode_name[m1]);
264             break;
265           case 'B':
266             printf ("%smode", mode_name[m2]);
267             break;
268           case 'c':
269             printf ("%s", rtx_name[op]);
270             break;
271           case 'C':
272             for (np = rtx_name[op]; *np; np++)
273               printf ("%c", toupper (*np));
274             break;
275           }
276     }
277
278   printf (";\n");
279 }
280 \f
281 char *
282 xmalloc (size)
283      unsigned size;
284 {
285   register char *val = (char *) malloc (size);
286
287   if (val == 0)
288     fatal ("virtual memory exhausted");
289
290   return val;
291 }
292
293 char *
294 xrealloc (ptr, size)
295      char *ptr;
296      unsigned size;
297 {
298   char *result = (char *) realloc (ptr, size);
299   if (!result)
300     fatal ("virtual memory exhausted");
301   return result;
302 }
303
304 static void
305 fatal (s, a1, a2)
306      char *s;
307 {
308   fprintf (stderr, "genopinit: ");
309   fprintf (stderr, s, a1, a2);
310   fprintf (stderr, "\n");
311   exit (FATAL_EXIT_CODE);
312 }
313
314 /* More 'friendly' abort that prints the line and file.
315    config.h can #define abort fancy_abort if you like that sort of thing.  */
316
317 void
318 fancy_abort ()
319 {
320   fatal ("Internal gcc abort.");
321 }
322 \f
323 int
324 main (argc, argv)
325      int argc;
326      char **argv;
327 {
328   rtx desc;
329   rtx dummy;
330   rtx *insn_ptr;
331   FILE *infile;
332   register int c;
333
334   obstack_init (rtl_obstack);
335
336   if (argc <= 1)
337     fatal ("No input file name.");
338
339   infile = fopen (argv[1], "r");
340   if (infile == 0)
341     {
342       perror (argv[1]);
343       exit (FATAL_EXIT_CODE);
344     }
345
346   init_rtl ();
347
348   printf ("/* Generated automatically by the program `genopinit'\n\
349 from the machine description file `md'.  */\n\n");
350
351   printf ("#include \"config.h\"\n");
352   printf ("#include \"rtl.h\"\n");
353   printf ("#include \"flags.h\"\n");
354   printf ("#include \"insn-flags.h\"\n");
355   printf ("#include \"insn-codes.h\"\n");
356   printf ("#include \"insn-config.h\"\n");
357   printf ("#include \"recog.h\"\n");
358   printf ("#include \"expr.h\"\n");
359   printf ("#include \"reload.h\"\n\n");
360
361   printf ("void\ninit_all_optabs ()\n{\n");
362
363   /* Read the machine description.  */
364
365   while (1)
366     {
367       c = read_skip_spaces (infile);
368       if (c == EOF)
369         break;
370       ungetc (c, infile);
371
372       desc = read_rtx (infile);
373       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
374         gen_insn (desc);
375     }
376
377   printf ("}\n");
378
379   fflush (stdout);
380   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
381   /* NOTREACHED */
382   return 0;
383 }