source: trunk/third/gcc/genopinit.c @ 11288

Revision 11288, 12.0 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Generate code to initialize optabs from machine description.
2   Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
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, 59 Temple Place - Suite 330,
19Boston, 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
28static struct obstack obstack;
29struct obstack *rtl_obstack = &obstack;
30
31#define obstack_chunk_alloc xmalloc
32#define obstack_chunk_free free
33
34extern void free ();
35extern rtx read_rtx ();
36
37char *xmalloc ();
38static void fatal ();
39void 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
70char *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.  */
129char **insn_name_ptr;
130
131static void
132gen_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.  */
189                    if (*p == 0 && *q == 0 && rtx_class[op] == '<')
190                      break;
191                  }
192
193                if (op == NUM_RTX_CODE)
194                  matches = 0;
195                else
196                  np += strlen (rtx_name[op]);
197                break;
198              case 'a':
199              case 'b':
200                /* This loop will stop at the first prefix match, so
201                   look through the modes in reverse order, in case
202                   EXTRA_CC_MODES was used and CC is a prefix of the
203                   CC modes (as it should be).  */
204                for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
205                  {
206                    for (p = mode_name[i], q = np; *p; p++, q++)
207                      if (tolower (*p) != *q)
208                        break;
209
210                    if (*p == 0
211                        && (! force_int || mode_class[i] == MODE_INT)
212                        && (! force_float || mode_class[i] == MODE_FLOAT))
213                      break;
214                  }
215
216                if (i < 0)
217                  matches = 0;
218                else if (*pp == 'a')
219                  m1 = i, np += strlen (mode_name[i]);
220                else
221                  m2 = i, np += strlen (mode_name[i]);
222
223                force_int = force_float = 0;
224                break;
225
226              default:
227                abort ();
228              }
229        }
230
231      if (matches && pp[0] == '%' && pp[1] == ')'
232          && *np == 0
233          && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
234        break;
235    }
236
237  if (pindex == sizeof optabs / sizeof optabs[0])
238    return;
239
240  /* We found a match.  If this pattern is only conditionally present,
241     write out the "if" and two extra blanks.  */
242
243  if (*XSTR (insn, 2) != 0)
244    printf ("  if (HAVE_%s)\n  ", name);
245
246  printf ("  ");
247
248  /* Now write out the initialization, making all required substitutions.  */
249  for (pp = optabs[pindex]; *pp; pp++)
250    {
251      if (*pp != '%')
252        printf ("%c", *pp);
253      else
254        switch (*++pp)
255          {
256          case '(':  case ')':
257          case 'I':  case 'F':  case 'N':
258            break;
259          case 'a':
260            for (np = mode_name[m1]; *np; np++)
261              printf ("%c", tolower (*np));
262            break;
263          case 'b':
264            for (np = mode_name[m2]; *np; np++)
265              printf ("%c", tolower (*np));
266            break;
267          case 'A':
268            printf ("%smode", mode_name[m1]);
269            break;
270          case 'B':
271            printf ("%smode", mode_name[m2]);
272            break;
273          case 'c':
274            printf ("%s", rtx_name[op]);
275            break;
276          case 'C':
277            for (np = rtx_name[op]; *np; np++)
278              printf ("%c", toupper (*np));
279            break;
280          }
281    }
282
283  printf (";\n");
284}
285
286char *
287xmalloc (size)
288     unsigned size;
289{
290  register char *val = (char *) malloc (size);
291
292  if (val == 0)
293    fatal ("virtual memory exhausted");
294
295  return val;
296}
297
298char *
299xrealloc (ptr, size)
300     char *ptr;
301     unsigned size;
302{
303  char *result = (char *) realloc (ptr, size);
304  if (!result)
305    fatal ("virtual memory exhausted");
306  return result;
307}
308
309static void
310fatal (s, a1, a2)
311     char *s;
312{
313  fprintf (stderr, "genopinit: ");
314  fprintf (stderr, s, a1, a2);
315  fprintf (stderr, "\n");
316  exit (FATAL_EXIT_CODE);
317}
318
319/* More 'friendly' abort that prints the line and file.
320   config.h can #define abort fancy_abort if you like that sort of thing.  */
321
322void
323fancy_abort ()
324{
325  fatal ("Internal gcc abort.");
326}
327
328int
329main (argc, argv)
330     int argc;
331     char **argv;
332{
333  rtx desc;
334  rtx dummy;
335  rtx *insn_ptr;
336  FILE *infile;
337  register int c;
338
339  obstack_init (rtl_obstack);
340
341  if (argc <= 1)
342    fatal ("No input file name.");
343
344  infile = fopen (argv[1], "r");
345  if (infile == 0)
346    {
347      perror (argv[1]);
348      exit (FATAL_EXIT_CODE);
349    }
350
351  init_rtl ();
352
353  printf ("/* Generated automatically by the program `genopinit'\n\
354from the machine description file `md'.  */\n\n");
355
356  printf ("#include \"config.h\"\n");
357  printf ("#include <stdio.h>\n");
358  printf ("#include \"rtl.h\"\n");
359  printf ("#include \"flags.h\"\n");
360  printf ("#include \"insn-flags.h\"\n");
361  printf ("#include \"insn-codes.h\"\n");
362  printf ("#include \"insn-config.h\"\n");
363  printf ("#include \"recog.h\"\n");
364  printf ("#include \"expr.h\"\n");
365  printf ("#include \"reload.h\"\n\n");
366
367  printf ("void\ninit_all_optabs ()\n{\n");
368
369  /* Read the machine description.  */
370
371  while (1)
372    {
373      c = read_skip_spaces (infile);
374      if (c == EOF)
375        break;
376      ungetc (c, infile);
377
378      desc = read_rtx (infile);
379      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
380        gen_insn (desc);
381    }
382
383  printf ("}\n");
384
385  fflush (stdout);
386  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
387  /* NOTREACHED */
388  return 0;
389}
Note: See TracBrowser for help on using the repository browser.