genconfig.c revision 90075
1254562Scy/* Generate from machine description:
2254562Scy   - some #define configuration flags.
3254562Scy   Copyright (C) 1987, 1991, 1997, 1998,
4254562Scy   1999, 2000 Free Software Foundation, Inc.
5254562Scy
6254562ScyThis file is part of GCC.
7254562Scy
8254562ScyGCC is free software; you can redistribute it and/or modify it under
9254562Scythe terms of the GNU General Public License as published by the Free
10254562ScySoftware Foundation; either version 2, or (at your option) any later
11254562Scyversion.
12254562Scy
13254562ScyGCC is distributed in the hope that it will be useful, but WITHOUT ANY
14254562ScyWARRANTY; without even the implied warranty of MERCHANTABILITY or
15254562ScyFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16254562Scyfor more details.
17254562Scy
18254562ScyYou should have received a copy of the GNU General Public License
19254562Scyalong with GCC; see the file COPYING.  If not, write to the Free
20254562ScySoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
21254562Scy02111-1307, USA.  */
22254562Scy
23254562Scy
24254562Scy#include "hconfig.h"
25254562Scy#include "system.h"
26254562Scy#include "rtl.h"
27254562Scy#include "errors.h"
28254562Scy#include "gensupport.h"
29254562Scy
30254562Scy
31254562Scy/* flags to determine output of machine description dependent #define's.  */
32254562Scystatic int max_recog_operands;  /* Largest operand number seen.  */
33254562Scystatic int max_dup_operands;    /* Largest number of match_dup in any insn.  */
34254562Scystatic int max_clobbers_per_insn;
35254562Scystatic int have_cc0_flag;
36254562Scystatic int have_cmove_flag;
37254562Scystatic int have_cond_exec_flag;
38254562Scystatic int have_lo_sum_flag;
39254562Scystatic int have_peephole_flag;
40254562Scystatic int have_peephole2_flag;
41254562Scy
42254562Scy/* Maximum number of insns seen in a split.  */
43254562Scystatic int max_insns_per_split = 1;
44254562Scy
45254562Scy/* Maximum number of input insns for peephole2.  */
46254562Scystatic int max_insns_per_peep2;
47254562Scy
48254562Scystatic int clobbers_seen_this_insn;
49254562Scystatic int dup_operands_seen_this_insn;
50254562Scy
51254562Scystatic void walk_insn_part PARAMS ((rtx, int, int));
52254562Scystatic void gen_insn PARAMS ((rtx));
53254562Scystatic void gen_expand PARAMS ((rtx));
54254562Scystatic void gen_split PARAMS ((rtx));
55254562Scystatic void gen_peephole PARAMS ((rtx));
56254562Scystatic void gen_peephole2 PARAMS ((rtx));
57254562Scy
58254562Scy/* RECOG_P will be non-zero if this pattern was seen in a context where it will
59254562Scy   be used to recognize, rather than just generate an insn.
60254562Scy
61254562Scy   NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
62254562Scy   of a SET whose destination is not (pc).  */
63254562Scy
64254562Scystatic void
65254562Scywalk_insn_part (part, recog_p, non_pc_set_src)
66254562Scy     rtx part;
67254562Scy     int recog_p;
68254562Scy     int non_pc_set_src;
69254562Scy{
70254562Scy  int i, j;
71254562Scy  RTX_CODE code;
72254562Scy  const char *format_ptr;
73254562Scy
74254562Scy  if (part == 0)
75254562Scy    return;
76254562Scy
77254562Scy  code = GET_CODE (part);
78254562Scy  switch (code)
79254562Scy    {
80254562Scy    case CLOBBER:
81254562Scy      clobbers_seen_this_insn++;
82254562Scy      break;
83254562Scy
84254562Scy    case MATCH_OPERAND:
85254562Scy      if (XINT (part, 0) > max_recog_operands)
86254562Scy	max_recog_operands = XINT (part, 0);
87254562Scy      return;
88254562Scy
89254562Scy    case MATCH_OP_DUP:
90254562Scy    case MATCH_PAR_DUP:
91254562Scy      ++dup_operands_seen_this_insn;
92254562Scy    case MATCH_SCRATCH:
93254562Scy    case MATCH_PARALLEL:
94254562Scy    case MATCH_OPERATOR:
95254562Scy      if (XINT (part, 0) > max_recog_operands)
96	max_recog_operands = XINT (part, 0);
97      /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
98	 MATCH_PARALLEL.  */
99      break;
100
101    case LABEL_REF:
102      if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
103	break;
104      return;
105
106    case MATCH_DUP:
107      ++dup_operands_seen_this_insn;
108      if (XINT (part, 0) > max_recog_operands)
109	max_recog_operands = XINT (part, 0);
110      return;
111
112    case CC0:
113      if (recog_p)
114	have_cc0_flag = 1;
115      return;
116
117    case LO_SUM:
118      if (recog_p)
119	have_lo_sum_flag = 1;
120      return;
121
122    case SET:
123      walk_insn_part (SET_DEST (part), 0, recog_p);
124      walk_insn_part (SET_SRC (part), recog_p,
125		      GET_CODE (SET_DEST (part)) != PC);
126      return;
127
128    case IF_THEN_ELSE:
129      /* Only consider this machine as having a conditional move if the
130	 two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
131	 we have some specific IF_THEN_ELSE construct (like the doz
132	 instruction on the RS/6000) that can't be used in the general
133	 context we want it for.  */
134
135      if (recog_p && non_pc_set_src
136	  && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
137	  && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
138	have_cmove_flag = 1;
139      break;
140
141    case COND_EXEC:
142      if (recog_p)
143	have_cond_exec_flag = 1;
144      break;
145
146    case REG: case CONST_INT: case SYMBOL_REF:
147    case PC:
148      return;
149
150    default:
151      break;
152    }
153
154  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
155
156  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
157    switch (*format_ptr++)
158      {
159      case 'e':
160      case 'u':
161	walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
162	break;
163      case 'E':
164	if (XVEC (part, i) != NULL)
165	  for (j = 0; j < XVECLEN (part, i); j++)
166	    walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
167	break;
168      }
169}
170
171static void
172gen_insn (insn)
173     rtx insn;
174{
175  int i;
176
177  /* Walk the insn pattern to gather the #define's status.  */
178  clobbers_seen_this_insn = 0;
179  dup_operands_seen_this_insn = 0;
180  if (XVEC (insn, 1) != 0)
181    for (i = 0; i < XVECLEN (insn, 1); i++)
182      walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
183
184  if (clobbers_seen_this_insn > max_clobbers_per_insn)
185    max_clobbers_per_insn = clobbers_seen_this_insn;
186  if (dup_operands_seen_this_insn > max_dup_operands)
187    max_dup_operands = dup_operands_seen_this_insn;
188}
189
190/* Similar but scan a define_expand.  */
191
192static void
193gen_expand (insn)
194     rtx insn;
195{
196  int i;
197
198  /* Walk the insn pattern to gather the #define's status.  */
199
200  /* Note that we don't bother recording the number of MATCH_DUPs
201     that occur in a gen_expand, because only reload cares about that.  */
202  if (XVEC (insn, 1) != 0)
203    for (i = 0; i < XVECLEN (insn, 1); i++)
204      {
205	/* Compute the maximum SETs and CLOBBERS
206	   in any one of the sub-insns;
207	   don't sum across all of them.  */
208	clobbers_seen_this_insn = 0;
209
210	walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
211
212	if (clobbers_seen_this_insn > max_clobbers_per_insn)
213	  max_clobbers_per_insn = clobbers_seen_this_insn;
214      }
215}
216
217/* Similar but scan a define_split.  */
218
219static void
220gen_split (split)
221     rtx split;
222{
223  int i;
224
225  /* Look through the patterns that are matched
226     to compute the maximum operand number.  */
227  for (i = 0; i < XVECLEN (split, 0); i++)
228    walk_insn_part (XVECEXP (split, 0, i), 1, 0);
229  /* Look at the number of insns this insn could split into.  */
230  if (XVECLEN (split, 2) > max_insns_per_split)
231    max_insns_per_split = XVECLEN (split, 2);
232}
233
234static void
235gen_peephole (peep)
236     rtx peep;
237{
238  int i;
239
240  /* Look through the patterns that are matched
241     to compute the maximum operand number.  */
242  for (i = 0; i < XVECLEN (peep, 0); i++)
243    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
244}
245
246static void
247gen_peephole2 (peep)
248     rtx peep;
249{
250  int i, n;
251
252  /* Look through the patterns that are matched
253     to compute the maximum operand number.  */
254  for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
255    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
256
257  /* Look at the number of insns this insn can be matched from.  */
258  for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
259    if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
260	&& GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
261      n++;
262  if (n > max_insns_per_peep2)
263    max_insns_per_peep2 = n;
264}
265
266extern int main PARAMS ((int, char **));
267
268int
269main (argc, argv)
270     int argc;
271     char **argv;
272{
273  rtx desc;
274
275  progname = "genconfig";
276
277  if (argc <= 1)
278    fatal ("no input file name");
279
280  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
281    return (FATAL_EXIT_CODE);
282
283  puts ("/* Generated automatically by the program `genconfig'");
284  puts ("   from the machine description file `md'.  */\n");
285  puts ("#ifndef GCC_INSN_CONFIG_H");
286  puts ("#define GCC_INSN_CONFIG_H\n");
287
288  /* Allow at least 30 operands for the sake of asm constructs.  */
289  /* ??? We *really* ought to reorganize things such that there
290     is no fixed upper bound.  */
291  max_recog_operands = 29;  /* We will add 1 later.  */
292  max_dup_operands = 1;
293
294  /* Read the machine description.  */
295
296  while (1)
297    {
298      int line_no, insn_code_number = 0;
299
300      desc = read_md_rtx (&line_no, &insn_code_number);
301      if (desc == NULL)
302	break;
303
304      switch (GET_CODE (desc))
305	{
306  	  case DEFINE_INSN:
307	    gen_insn (desc);
308	    break;
309
310	  case DEFINE_EXPAND:
311	    gen_expand (desc);
312	    break;
313
314	  case DEFINE_SPLIT:
315	    gen_split (desc);
316	    break;
317
318	  case DEFINE_PEEPHOLE2:
319	    have_peephole2_flag = 1;
320	    gen_peephole2 (desc);
321	    break;
322
323	  case DEFINE_PEEPHOLE:
324	    have_peephole_flag = 1;
325	    gen_peephole (desc);
326	    break;
327
328	  default:
329	    break;
330	}
331    }
332
333  printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
334  printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
335
336  /* This is conditionally defined, in case the user writes code which emits
337     more splits than we can readily see (and knows s/he does it).  */
338  printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
339  printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
340  printf ("#endif\n");
341
342  if (have_cc0_flag)
343    printf ("#define HAVE_cc0 1\n");
344
345  if (have_cmove_flag)
346    printf ("#define HAVE_conditional_move 1\n");
347
348  if (have_cond_exec_flag)
349    printf ("#define HAVE_conditional_execution 1\n");
350
351  if (have_lo_sum_flag)
352    printf ("#define HAVE_lo_sum 1\n");
353
354  if (have_peephole_flag)
355    printf ("#define HAVE_peephole 1\n");
356
357  if (have_peephole2_flag)
358    {
359      printf ("#define HAVE_peephole2 1\n");
360      printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
361    }
362
363  puts("\n#endif /* GCC_INSN_CONFIG_H */");
364
365  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
366    return FATAL_EXIT_CODE;
367
368  return SUCCESS_EXIT_CODE;
369}
370
371/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
372const char *
373get_insn_name (code)
374     int code ATTRIBUTE_UNUSED;
375{
376  return NULL;
377}
378