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

Revision 8834, 11.7 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, 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 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
127/* Allow linking with print-rtl.c.  */
128char **insn_name_ptr;
129
130static void
131gen_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
283char *
284xmalloc (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
295char *
296xrealloc (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
306static void
307fatal (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
319void
320fancy_abort ()
321{
322  fatal ("Internal gcc abort.");
323}
324
325int
326main (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\
351from 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}
Note: See TracBrowser for help on using the repository browser.