OSDN Git Service

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