OSDN Git Service

(notice_cc_update): Set CC_FCOMI is this is a float compare.
[pf3gnuchains/gcc-fork.git] / gcc / genopinit.c
1 /* Generate code to initialize optabs from machine description.
2    Copyright (C) 1993, 1994, 1995, 1996 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.  */
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 \f
286 char *
287 xmalloc (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
298 char *
299 xrealloc (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
309 static void
310 fatal (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
322 void
323 fancy_abort ()
324 {
325   fatal ("Internal gcc abort.");
326 }
327 \f
328 int
329 main (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\
354 from the machine description file `md'.  */\n\n");
355
356   printf ("#include \"config.h\"\n");
357   printf ("#include \"rtl.h\"\n");
358   printf ("#include \"flags.h\"\n");
359   printf ("#include \"insn-flags.h\"\n");
360   printf ("#include \"insn-codes.h\"\n");
361   printf ("#include \"insn-config.h\"\n");
362   printf ("#include \"recog.h\"\n");
363   printf ("#include \"expr.h\"\n");
364   printf ("#include \"reload.h\"\n\n");
365
366   printf ("void\ninit_all_optabs ()\n{\n");
367
368   /* Read the machine description.  */
369
370   while (1)
371     {
372       c = read_skip_spaces (infile);
373       if (c == EOF)
374         break;
375       ungetc (c, infile);
376
377       desc = read_rtx (infile);
378       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
379         gen_insn (desc);
380     }
381
382   printf ("}\n");
383
384   fflush (stdout);
385   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
386   /* NOTREACHED */
387   return 0;
388 }