OSDN Git Service

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