175592Sru/* Generate from machine description:
275592Sru   - some #define configuration flags.
394427Sru   Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004
4151504Sru   Free Software Foundation, Inc.
5114412Sru
6291738SbdreweryThis file is part of GCC.
7291738Sbdrewery
8291738SbdreweryGCC is free software; you can redistribute it and/or modify it under
975592Sruthe terms of the GNU General Public License as published by the Free
1075592SruSoftware Foundation; either version 2, or (at your option) any later
1175592Sruversion.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to the Free
20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2102110-1301, USA.  */
22
23
24#include "bconfig.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "rtl.h"
29#include "errors.h"
30#include "gensupport.h"
31
32
33/* flags to determine output of machine description dependent #define's.  */
34static int max_recog_operands;  /* Largest operand number seen.  */
35static int max_dup_operands;    /* Largest number of match_dup in any insn.  */
36static int max_clobbers_per_insn;
37static int have_cc0_flag;
38static int have_cmove_flag;
39static int have_cond_exec_flag;
40static int have_lo_sum_flag;
41static int have_peephole_flag;
42static int have_peephole2_flag;
43
44/* Maximum number of insns seen in a split.  */
45static int max_insns_per_split = 1;
46
47/* Maximum number of input insns for peephole2.  */
48static int max_insns_per_peep2;
49
50static int clobbers_seen_this_insn;
51static int dup_operands_seen_this_insn;
52
53static void walk_insn_part (rtx, int, int);
54static void gen_insn (rtx);
55static void gen_expand (rtx);
56static void gen_split (rtx);
57static void gen_peephole (rtx);
58static void gen_peephole2 (rtx);
59
60/* RECOG_P will be nonzero if this pattern was seen in a context where it will
61   be used to recognize, rather than just generate an insn.
62
63   NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC
64   of a SET whose destination is not (pc).  */
65
66static void
67walk_insn_part (rtx part, int recog_p, int non_pc_set_src)
68{
69  int i, j;
70  RTX_CODE code;
71  const char *format_ptr;
72
73  if (part == 0)
74    return;
75
76  code = GET_CODE (part);
77  switch (code)
78    {
79    case CLOBBER:
80      clobbers_seen_this_insn++;
81      break;
82
83    case MATCH_OPERAND:
84      if (XINT (part, 0) > max_recog_operands)
85	max_recog_operands = XINT (part, 0);
86      return;
87
88    case MATCH_OP_DUP:
89    case MATCH_PAR_DUP:
90      ++dup_operands_seen_this_insn;
91    case MATCH_SCRATCH:
92    case MATCH_PARALLEL:
93    case MATCH_OPERATOR:
94      if (XINT (part, 0) > max_recog_operands)
95	max_recog_operands = XINT (part, 0);
96      /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
97	 MATCH_PARALLEL.  */
98      break;
99
100    case LABEL_REF:
101      if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND
102	  || GET_CODE (XEXP (part, 0)) == MATCH_DUP)
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 (rtx insn)
173{
174  int i;
175
176  /* Walk the insn pattern to gather the #define's status.  */
177  clobbers_seen_this_insn = 0;
178  dup_operands_seen_this_insn = 0;
179  if (XVEC (insn, 1) != 0)
180    for (i = 0; i < XVECLEN (insn, 1); i++)
181      walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
182
183  if (clobbers_seen_this_insn > max_clobbers_per_insn)
184    max_clobbers_per_insn = clobbers_seen_this_insn;
185  if (dup_operands_seen_this_insn > max_dup_operands)
186    max_dup_operands = dup_operands_seen_this_insn;
187}
188
189/* Similar but scan a define_expand.  */
190
191static void
192gen_expand (rtx insn)
193{
194  int i;
195
196  /* Walk the insn pattern to gather the #define's status.  */
197
198  /* Note that we don't bother recording the number of MATCH_DUPs
199     that occur in a gen_expand, because only reload cares about that.  */
200  if (XVEC (insn, 1) != 0)
201    for (i = 0; i < XVECLEN (insn, 1); i++)
202      {
203	/* Compute the maximum SETs and CLOBBERS
204	   in any one of the sub-insns;
205	   don't sum across all of them.  */
206	clobbers_seen_this_insn = 0;
207
208	walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
209
210	if (clobbers_seen_this_insn > max_clobbers_per_insn)
211	  max_clobbers_per_insn = clobbers_seen_this_insn;
212      }
213}
214
215/* Similar but scan a define_split.  */
216
217static void
218gen_split (rtx split)
219{
220  int i;
221
222  /* Look through the patterns that are matched
223     to compute the maximum operand number.  */
224  for (i = 0; i < XVECLEN (split, 0); i++)
225    walk_insn_part (XVECEXP (split, 0, i), 1, 0);
226  /* Look at the number of insns this insn could split into.  */
227  if (XVECLEN (split, 2) > max_insns_per_split)
228    max_insns_per_split = XVECLEN (split, 2);
229}
230
231static void
232gen_peephole (rtx peep)
233{
234  int i;
235
236  /* Look through the patterns that are matched
237     to compute the maximum operand number.  */
238  for (i = 0; i < XVECLEN (peep, 0); i++)
239    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
240}
241
242static void
243gen_peephole2 (rtx peep)
244{
245  int i, n;
246
247  /* Look through the patterns that are matched
248     to compute the maximum operand number.  */
249  for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
250    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
251
252  /* Look at the number of insns this insn can be matched from.  */
253  for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
254    if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
255	&& GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
256      n++;
257  if (n > max_insns_per_peep2)
258    max_insns_per_peep2 = n;
259}
260
261int
262main (int argc, char **argv)
263{
264  rtx desc;
265
266  progname = "genconfig";
267
268  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
269    return (FATAL_EXIT_CODE);
270
271  puts ("/* Generated automatically by the program `genconfig'");
272  puts ("   from the machine description file `md'.  */\n");
273  puts ("#ifndef GCC_INSN_CONFIG_H");
274  puts ("#define GCC_INSN_CONFIG_H\n");
275
276  /* Allow at least 30 operands for the sake of asm constructs.  */
277  /* ??? We *really* ought to reorganize things such that there
278     is no fixed upper bound.  */
279  max_recog_operands = 29;  /* We will add 1 later.  */
280  max_dup_operands = 1;
281
282  /* Read the machine description.  */
283
284  while (1)
285    {
286      int line_no, insn_code_number = 0;
287
288      desc = read_md_rtx (&line_no, &insn_code_number);
289      if (desc == NULL)
290	break;
291
292      switch (GET_CODE (desc))
293	{
294  	  case DEFINE_INSN:
295	    gen_insn (desc);
296	    break;
297
298	  case DEFINE_EXPAND:
299	    gen_expand (desc);
300	    break;
301
302	  case DEFINE_SPLIT:
303	    gen_split (desc);
304	    break;
305
306	  case DEFINE_PEEPHOLE2:
307	    have_peephole2_flag = 1;
308	    gen_peephole2 (desc);
309	    break;
310
311	  case DEFINE_PEEPHOLE:
312	    have_peephole_flag = 1;
313	    gen_peephole (desc);
314	    break;
315
316	  default:
317	    break;
318	}
319    }
320
321  printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
322  printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
323
324  /* This is conditionally defined, in case the user writes code which emits
325     more splits than we can readily see (and knows s/he does it).  */
326  printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
327  printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
328  printf ("#endif\n");
329
330  if (have_cc0_flag)
331    {
332      printf ("#define HAVE_cc0 1\n");
333      printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
334    }
335  else
336    {
337      /* We output CC0_P this way to make sure that X is declared
338	 somewhere.  */
339      printf ("#define CC0_P(X) ((X) ? 0 : 0)\n");
340    }
341
342  if (have_cmove_flag)
343    printf ("#define HAVE_conditional_move 1\n");
344
345  if (have_cond_exec_flag)
346    printf ("#define HAVE_conditional_execution 1\n");
347
348  if (have_lo_sum_flag)
349    printf ("#define HAVE_lo_sum 1\n");
350
351  if (have_peephole_flag)
352    printf ("#define HAVE_peephole 1\n");
353
354  if (have_peephole2_flag)
355    {
356      printf ("#define HAVE_peephole2 1\n");
357      printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
358    }
359
360  puts("\n#endif /* GCC_INSN_CONFIG_H */");
361
362  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
363    return FATAL_EXIT_CODE;
364
365  return SUCCESS_EXIT_CODE;
366}
367