xref: /openbsd/gnu/usr.bin/gcc/gcc/genconfig.c (revision c87b03e5)
1*c87b03e5Sespie /* Generate from machine description:
2*c87b03e5Sespie    - some #define configuration flags.
3*c87b03e5Sespie    Copyright (C) 1987, 1991, 1997, 1998,
4*c87b03e5Sespie    1999, 2000 Free Software Foundation, Inc.
5*c87b03e5Sespie 
6*c87b03e5Sespie This file is part of GCC.
7*c87b03e5Sespie 
8*c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it under
9*c87b03e5Sespie the terms of the GNU General Public License as published by the Free
10*c87b03e5Sespie Software Foundation; either version 2, or (at your option) any later
11*c87b03e5Sespie version.
12*c87b03e5Sespie 
13*c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*c87b03e5Sespie WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*c87b03e5Sespie FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*c87b03e5Sespie for more details.
17*c87b03e5Sespie 
18*c87b03e5Sespie You should have received a copy of the GNU General Public License
19*c87b03e5Sespie along with GCC; see the file COPYING.  If not, write to the Free
20*c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21*c87b03e5Sespie 02111-1307, USA.  */
22*c87b03e5Sespie 
23*c87b03e5Sespie 
24*c87b03e5Sespie #include "hconfig.h"
25*c87b03e5Sespie #include "system.h"
26*c87b03e5Sespie #include "rtl.h"
27*c87b03e5Sespie #include "errors.h"
28*c87b03e5Sespie #include "gensupport.h"
29*c87b03e5Sespie 
30*c87b03e5Sespie 
31*c87b03e5Sespie /* flags to determine output of machine description dependent #define's.  */
32*c87b03e5Sespie static int max_recog_operands;  /* Largest operand number seen.  */
33*c87b03e5Sespie static int max_dup_operands;    /* Largest number of match_dup in any insn.  */
34*c87b03e5Sespie static int max_clobbers_per_insn;
35*c87b03e5Sespie static int have_cc0_flag;
36*c87b03e5Sespie static int have_cmove_flag;
37*c87b03e5Sespie static int have_cond_exec_flag;
38*c87b03e5Sespie static int have_lo_sum_flag;
39*c87b03e5Sespie static int have_peephole_flag;
40*c87b03e5Sespie static int have_peephole2_flag;
41*c87b03e5Sespie 
42*c87b03e5Sespie /* Maximum number of insns seen in a split.  */
43*c87b03e5Sespie static int max_insns_per_split = 1;
44*c87b03e5Sespie 
45*c87b03e5Sespie /* Maximum number of input insns for peephole2.  */
46*c87b03e5Sespie static int max_insns_per_peep2;
47*c87b03e5Sespie 
48*c87b03e5Sespie static int clobbers_seen_this_insn;
49*c87b03e5Sespie static int dup_operands_seen_this_insn;
50*c87b03e5Sespie 
51*c87b03e5Sespie static void walk_insn_part PARAMS ((rtx, int, int));
52*c87b03e5Sespie static void gen_insn PARAMS ((rtx));
53*c87b03e5Sespie static void gen_expand PARAMS ((rtx));
54*c87b03e5Sespie static void gen_split PARAMS ((rtx));
55*c87b03e5Sespie static void gen_peephole PARAMS ((rtx));
56*c87b03e5Sespie static void gen_peephole2 PARAMS ((rtx));
57*c87b03e5Sespie 
58*c87b03e5Sespie /* RECOG_P will be nonzero if this pattern was seen in a context where it will
59*c87b03e5Sespie    be used to recognize, rather than just generate an insn.
60*c87b03e5Sespie 
61*c87b03e5Sespie    NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC
62*c87b03e5Sespie    of a SET whose destination is not (pc).  */
63*c87b03e5Sespie 
64*c87b03e5Sespie static void
walk_insn_part(part,recog_p,non_pc_set_src)65*c87b03e5Sespie walk_insn_part (part, recog_p, non_pc_set_src)
66*c87b03e5Sespie      rtx part;
67*c87b03e5Sespie      int recog_p;
68*c87b03e5Sespie      int non_pc_set_src;
69*c87b03e5Sespie {
70*c87b03e5Sespie   int i, j;
71*c87b03e5Sespie   RTX_CODE code;
72*c87b03e5Sespie   const char *format_ptr;
73*c87b03e5Sespie 
74*c87b03e5Sespie   if (part == 0)
75*c87b03e5Sespie     return;
76*c87b03e5Sespie 
77*c87b03e5Sespie   code = GET_CODE (part);
78*c87b03e5Sespie   switch (code)
79*c87b03e5Sespie     {
80*c87b03e5Sespie     case CLOBBER:
81*c87b03e5Sespie       clobbers_seen_this_insn++;
82*c87b03e5Sespie       break;
83*c87b03e5Sespie 
84*c87b03e5Sespie     case MATCH_OPERAND:
85*c87b03e5Sespie       if (XINT (part, 0) > max_recog_operands)
86*c87b03e5Sespie 	max_recog_operands = XINT (part, 0);
87*c87b03e5Sespie       return;
88*c87b03e5Sespie 
89*c87b03e5Sespie     case MATCH_OP_DUP:
90*c87b03e5Sespie     case MATCH_PAR_DUP:
91*c87b03e5Sespie       ++dup_operands_seen_this_insn;
92*c87b03e5Sespie     case MATCH_SCRATCH:
93*c87b03e5Sespie     case MATCH_PARALLEL:
94*c87b03e5Sespie     case MATCH_OPERATOR:
95*c87b03e5Sespie       if (XINT (part, 0) > max_recog_operands)
96*c87b03e5Sespie 	max_recog_operands = XINT (part, 0);
97*c87b03e5Sespie       /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
98*c87b03e5Sespie 	 MATCH_PARALLEL.  */
99*c87b03e5Sespie       break;
100*c87b03e5Sespie 
101*c87b03e5Sespie     case LABEL_REF:
102*c87b03e5Sespie       if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
103*c87b03e5Sespie 	break;
104*c87b03e5Sespie       return;
105*c87b03e5Sespie 
106*c87b03e5Sespie     case MATCH_DUP:
107*c87b03e5Sespie       ++dup_operands_seen_this_insn;
108*c87b03e5Sespie       if (XINT (part, 0) > max_recog_operands)
109*c87b03e5Sespie 	max_recog_operands = XINT (part, 0);
110*c87b03e5Sespie       return;
111*c87b03e5Sespie 
112*c87b03e5Sespie     case CC0:
113*c87b03e5Sespie       if (recog_p)
114*c87b03e5Sespie 	have_cc0_flag = 1;
115*c87b03e5Sespie       return;
116*c87b03e5Sespie 
117*c87b03e5Sespie     case LO_SUM:
118*c87b03e5Sespie       if (recog_p)
119*c87b03e5Sespie 	have_lo_sum_flag = 1;
120*c87b03e5Sespie       return;
121*c87b03e5Sespie 
122*c87b03e5Sespie     case SET:
123*c87b03e5Sespie       walk_insn_part (SET_DEST (part), 0, recog_p);
124*c87b03e5Sespie       walk_insn_part (SET_SRC (part), recog_p,
125*c87b03e5Sespie 		      GET_CODE (SET_DEST (part)) != PC);
126*c87b03e5Sespie       return;
127*c87b03e5Sespie 
128*c87b03e5Sespie     case IF_THEN_ELSE:
129*c87b03e5Sespie       /* Only consider this machine as having a conditional move if the
130*c87b03e5Sespie 	 two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
131*c87b03e5Sespie 	 we have some specific IF_THEN_ELSE construct (like the doz
132*c87b03e5Sespie 	 instruction on the RS/6000) that can't be used in the general
133*c87b03e5Sespie 	 context we want it for.  */
134*c87b03e5Sespie 
135*c87b03e5Sespie       if (recog_p && non_pc_set_src
136*c87b03e5Sespie 	  && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
137*c87b03e5Sespie 	  && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
138*c87b03e5Sespie 	have_cmove_flag = 1;
139*c87b03e5Sespie       break;
140*c87b03e5Sespie 
141*c87b03e5Sespie     case COND_EXEC:
142*c87b03e5Sespie       if (recog_p)
143*c87b03e5Sespie 	have_cond_exec_flag = 1;
144*c87b03e5Sespie       break;
145*c87b03e5Sespie 
146*c87b03e5Sespie     case REG: case CONST_INT: case SYMBOL_REF:
147*c87b03e5Sespie     case PC:
148*c87b03e5Sespie       return;
149*c87b03e5Sespie 
150*c87b03e5Sespie     default:
151*c87b03e5Sespie       break;
152*c87b03e5Sespie     }
153*c87b03e5Sespie 
154*c87b03e5Sespie   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
155*c87b03e5Sespie 
156*c87b03e5Sespie   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
157*c87b03e5Sespie     switch (*format_ptr++)
158*c87b03e5Sespie       {
159*c87b03e5Sespie       case 'e':
160*c87b03e5Sespie       case 'u':
161*c87b03e5Sespie 	walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
162*c87b03e5Sespie 	break;
163*c87b03e5Sespie       case 'E':
164*c87b03e5Sespie 	if (XVEC (part, i) != NULL)
165*c87b03e5Sespie 	  for (j = 0; j < XVECLEN (part, i); j++)
166*c87b03e5Sespie 	    walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
167*c87b03e5Sespie 	break;
168*c87b03e5Sespie       }
169*c87b03e5Sespie }
170*c87b03e5Sespie 
171*c87b03e5Sespie static void
gen_insn(insn)172*c87b03e5Sespie gen_insn (insn)
173*c87b03e5Sespie      rtx insn;
174*c87b03e5Sespie {
175*c87b03e5Sespie   int i;
176*c87b03e5Sespie 
177*c87b03e5Sespie   /* Walk the insn pattern to gather the #define's status.  */
178*c87b03e5Sespie   clobbers_seen_this_insn = 0;
179*c87b03e5Sespie   dup_operands_seen_this_insn = 0;
180*c87b03e5Sespie   if (XVEC (insn, 1) != 0)
181*c87b03e5Sespie     for (i = 0; i < XVECLEN (insn, 1); i++)
182*c87b03e5Sespie       walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
183*c87b03e5Sespie 
184*c87b03e5Sespie   if (clobbers_seen_this_insn > max_clobbers_per_insn)
185*c87b03e5Sespie     max_clobbers_per_insn = clobbers_seen_this_insn;
186*c87b03e5Sespie   if (dup_operands_seen_this_insn > max_dup_operands)
187*c87b03e5Sespie     max_dup_operands = dup_operands_seen_this_insn;
188*c87b03e5Sespie }
189*c87b03e5Sespie 
190*c87b03e5Sespie /* Similar but scan a define_expand.  */
191*c87b03e5Sespie 
192*c87b03e5Sespie static void
gen_expand(insn)193*c87b03e5Sespie gen_expand (insn)
194*c87b03e5Sespie      rtx insn;
195*c87b03e5Sespie {
196*c87b03e5Sespie   int i;
197*c87b03e5Sespie 
198*c87b03e5Sespie   /* Walk the insn pattern to gather the #define's status.  */
199*c87b03e5Sespie 
200*c87b03e5Sespie   /* Note that we don't bother recording the number of MATCH_DUPs
201*c87b03e5Sespie      that occur in a gen_expand, because only reload cares about that.  */
202*c87b03e5Sespie   if (XVEC (insn, 1) != 0)
203*c87b03e5Sespie     for (i = 0; i < XVECLEN (insn, 1); i++)
204*c87b03e5Sespie       {
205*c87b03e5Sespie 	/* Compute the maximum SETs and CLOBBERS
206*c87b03e5Sespie 	   in any one of the sub-insns;
207*c87b03e5Sespie 	   don't sum across all of them.  */
208*c87b03e5Sespie 	clobbers_seen_this_insn = 0;
209*c87b03e5Sespie 
210*c87b03e5Sespie 	walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
211*c87b03e5Sespie 
212*c87b03e5Sespie 	if (clobbers_seen_this_insn > max_clobbers_per_insn)
213*c87b03e5Sespie 	  max_clobbers_per_insn = clobbers_seen_this_insn;
214*c87b03e5Sespie       }
215*c87b03e5Sespie }
216*c87b03e5Sespie 
217*c87b03e5Sespie /* Similar but scan a define_split.  */
218*c87b03e5Sespie 
219*c87b03e5Sespie static void
gen_split(split)220*c87b03e5Sespie gen_split (split)
221*c87b03e5Sespie      rtx split;
222*c87b03e5Sespie {
223*c87b03e5Sespie   int i;
224*c87b03e5Sespie 
225*c87b03e5Sespie   /* Look through the patterns that are matched
226*c87b03e5Sespie      to compute the maximum operand number.  */
227*c87b03e5Sespie   for (i = 0; i < XVECLEN (split, 0); i++)
228*c87b03e5Sespie     walk_insn_part (XVECEXP (split, 0, i), 1, 0);
229*c87b03e5Sespie   /* Look at the number of insns this insn could split into.  */
230*c87b03e5Sespie   if (XVECLEN (split, 2) > max_insns_per_split)
231*c87b03e5Sespie     max_insns_per_split = XVECLEN (split, 2);
232*c87b03e5Sespie }
233*c87b03e5Sespie 
234*c87b03e5Sespie static void
gen_peephole(peep)235*c87b03e5Sespie gen_peephole (peep)
236*c87b03e5Sespie      rtx peep;
237*c87b03e5Sespie {
238*c87b03e5Sespie   int i;
239*c87b03e5Sespie 
240*c87b03e5Sespie   /* Look through the patterns that are matched
241*c87b03e5Sespie      to compute the maximum operand number.  */
242*c87b03e5Sespie   for (i = 0; i < XVECLEN (peep, 0); i++)
243*c87b03e5Sespie     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
244*c87b03e5Sespie }
245*c87b03e5Sespie 
246*c87b03e5Sespie static void
gen_peephole2(peep)247*c87b03e5Sespie gen_peephole2 (peep)
248*c87b03e5Sespie      rtx peep;
249*c87b03e5Sespie {
250*c87b03e5Sespie   int i, n;
251*c87b03e5Sespie 
252*c87b03e5Sespie   /* Look through the patterns that are matched
253*c87b03e5Sespie      to compute the maximum operand number.  */
254*c87b03e5Sespie   for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
255*c87b03e5Sespie     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
256*c87b03e5Sespie 
257*c87b03e5Sespie   /* Look at the number of insns this insn can be matched from.  */
258*c87b03e5Sespie   for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
259*c87b03e5Sespie     if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
260*c87b03e5Sespie 	&& GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
261*c87b03e5Sespie       n++;
262*c87b03e5Sespie   if (n > max_insns_per_peep2)
263*c87b03e5Sespie     max_insns_per_peep2 = n;
264*c87b03e5Sespie }
265*c87b03e5Sespie 
266*c87b03e5Sespie extern int main PARAMS ((int, char **));
267*c87b03e5Sespie 
268*c87b03e5Sespie int
main(argc,argv)269*c87b03e5Sespie main (argc, argv)
270*c87b03e5Sespie      int argc;
271*c87b03e5Sespie      char **argv;
272*c87b03e5Sespie {
273*c87b03e5Sespie   rtx desc;
274*c87b03e5Sespie 
275*c87b03e5Sespie   progname = "genconfig";
276*c87b03e5Sespie 
277*c87b03e5Sespie   if (argc <= 1)
278*c87b03e5Sespie     fatal ("no input file name");
279*c87b03e5Sespie 
280*c87b03e5Sespie   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
281*c87b03e5Sespie     return (FATAL_EXIT_CODE);
282*c87b03e5Sespie 
283*c87b03e5Sespie   puts ("/* Generated automatically by the program `genconfig'");
284*c87b03e5Sespie   puts ("   from the machine description file `md'.  */\n");
285*c87b03e5Sespie   puts ("#ifndef GCC_INSN_CONFIG_H");
286*c87b03e5Sespie   puts ("#define GCC_INSN_CONFIG_H\n");
287*c87b03e5Sespie 
288*c87b03e5Sespie   /* Allow at least 30 operands for the sake of asm constructs.  */
289*c87b03e5Sespie   /* ??? We *really* ought to reorganize things such that there
290*c87b03e5Sespie      is no fixed upper bound.  */
291*c87b03e5Sespie   max_recog_operands = 29;  /* We will add 1 later.  */
292*c87b03e5Sespie   max_dup_operands = 1;
293*c87b03e5Sespie 
294*c87b03e5Sespie   /* Read the machine description.  */
295*c87b03e5Sespie 
296*c87b03e5Sespie   while (1)
297*c87b03e5Sespie     {
298*c87b03e5Sespie       int line_no, insn_code_number = 0;
299*c87b03e5Sespie 
300*c87b03e5Sespie       desc = read_md_rtx (&line_no, &insn_code_number);
301*c87b03e5Sespie       if (desc == NULL)
302*c87b03e5Sespie 	break;
303*c87b03e5Sespie 
304*c87b03e5Sespie       switch (GET_CODE (desc))
305*c87b03e5Sespie 	{
306*c87b03e5Sespie   	  case DEFINE_INSN:
307*c87b03e5Sespie 	    gen_insn (desc);
308*c87b03e5Sespie 	    break;
309*c87b03e5Sespie 
310*c87b03e5Sespie 	  case DEFINE_EXPAND:
311*c87b03e5Sespie 	    gen_expand (desc);
312*c87b03e5Sespie 	    break;
313*c87b03e5Sespie 
314*c87b03e5Sespie 	  case DEFINE_SPLIT:
315*c87b03e5Sespie 	    gen_split (desc);
316*c87b03e5Sespie 	    break;
317*c87b03e5Sespie 
318*c87b03e5Sespie 	  case DEFINE_PEEPHOLE2:
319*c87b03e5Sespie 	    have_peephole2_flag = 1;
320*c87b03e5Sespie 	    gen_peephole2 (desc);
321*c87b03e5Sespie 	    break;
322*c87b03e5Sespie 
323*c87b03e5Sespie 	  case DEFINE_PEEPHOLE:
324*c87b03e5Sespie 	    have_peephole_flag = 1;
325*c87b03e5Sespie 	    gen_peephole (desc);
326*c87b03e5Sespie 	    break;
327*c87b03e5Sespie 
328*c87b03e5Sespie 	  default:
329*c87b03e5Sespie 	    break;
330*c87b03e5Sespie 	}
331*c87b03e5Sespie     }
332*c87b03e5Sespie 
333*c87b03e5Sespie   printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
334*c87b03e5Sespie   printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
335*c87b03e5Sespie 
336*c87b03e5Sespie   /* This is conditionally defined, in case the user writes code which emits
337*c87b03e5Sespie      more splits than we can readily see (and knows s/he does it).  */
338*c87b03e5Sespie   printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
339*c87b03e5Sespie   printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
340*c87b03e5Sespie   printf ("#endif\n");
341*c87b03e5Sespie 
342*c87b03e5Sespie   if (have_cc0_flag)
343*c87b03e5Sespie     printf ("#define HAVE_cc0 1\n");
344*c87b03e5Sespie 
345*c87b03e5Sespie   if (have_cmove_flag)
346*c87b03e5Sespie     printf ("#define HAVE_conditional_move 1\n");
347*c87b03e5Sespie 
348*c87b03e5Sespie   if (have_cond_exec_flag)
349*c87b03e5Sespie     printf ("#define HAVE_conditional_execution 1\n");
350*c87b03e5Sespie 
351*c87b03e5Sespie   if (have_lo_sum_flag)
352*c87b03e5Sespie     printf ("#define HAVE_lo_sum 1\n");
353*c87b03e5Sespie 
354*c87b03e5Sespie   if (have_peephole_flag)
355*c87b03e5Sespie     printf ("#define HAVE_peephole 1\n");
356*c87b03e5Sespie 
357*c87b03e5Sespie   if (have_peephole2_flag)
358*c87b03e5Sespie     {
359*c87b03e5Sespie       printf ("#define HAVE_peephole2 1\n");
360*c87b03e5Sespie       printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
361*c87b03e5Sespie     }
362*c87b03e5Sespie 
363*c87b03e5Sespie   puts("\n#endif /* GCC_INSN_CONFIG_H */");
364*c87b03e5Sespie 
365*c87b03e5Sespie   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
366*c87b03e5Sespie     return FATAL_EXIT_CODE;
367*c87b03e5Sespie 
368*c87b03e5Sespie   return SUCCESS_EXIT_CODE;
369*c87b03e5Sespie }
370*c87b03e5Sespie 
371*c87b03e5Sespie /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
372*c87b03e5Sespie const char *
get_insn_name(code)373*c87b03e5Sespie get_insn_name (code)
374*c87b03e5Sespie      int code ATTRIBUTE_UNUSED;
375*c87b03e5Sespie {
376*c87b03e5Sespie   return NULL;
377*c87b03e5Sespie }
378