118334Speter/* Generate from machine description:
218334Speter   - some #define configuration flags.
3169689Skan   Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004
4132718Skan   Free Software Foundation, Inc.
518334Speter
690075SobrienThis file is part of GCC.
718334Speter
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1218334Speter
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2218334Speter
2318334Speter
24132718Skan#include "bconfig.h"
2550397Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2818334Speter#include "rtl.h"
2990075Sobrien#include "errors.h"
3090075Sobrien#include "gensupport.h"
3118334Speter
3218334Speter
3318334Speter/* flags to determine output of machine description dependent #define's.  */
3418334Speterstatic int max_recog_operands;  /* Largest operand number seen.  */
3518334Speterstatic int max_dup_operands;    /* Largest number of match_dup in any insn.  */
3618334Speterstatic int max_clobbers_per_insn;
3718334Speterstatic int have_cc0_flag;
3818334Speterstatic int have_cmove_flag;
3990075Sobrienstatic int have_cond_exec_flag;
4018334Speterstatic int have_lo_sum_flag;
4190075Sobrienstatic int have_peephole_flag;
4290075Sobrienstatic int have_peephole2_flag;
4318334Speter
4418334Speter/* Maximum number of insns seen in a split.  */
4518334Speterstatic int max_insns_per_split = 1;
4618334Speter
4790075Sobrien/* Maximum number of input insns for peephole2.  */
4890075Sobrienstatic int max_insns_per_peep2;
4990075Sobrien
5018334Speterstatic int clobbers_seen_this_insn;
5118334Speterstatic int dup_operands_seen_this_insn;
5218334Speter
53132718Skanstatic void walk_insn_part (rtx, int, int);
54132718Skanstatic void gen_insn (rtx);
55132718Skanstatic void gen_expand (rtx);
56132718Skanstatic void gen_split (rtx);
57132718Skanstatic void gen_peephole (rtx);
58132718Skanstatic void gen_peephole2 (rtx);
5918334Speter
60117395Skan/* RECOG_P will be nonzero if this pattern was seen in a context where it will
6118334Speter   be used to recognize, rather than just generate an insn.
6218334Speter
63117395Skan   NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC
6418334Speter   of a SET whose destination is not (pc).  */
6518334Speter
6618334Speterstatic void
67132718Skanwalk_insn_part (rtx part, int recog_p, int non_pc_set_src)
6818334Speter{
6990075Sobrien  int i, j;
7090075Sobrien  RTX_CODE code;
7190075Sobrien  const char *format_ptr;
7218334Speter
7318334Speter  if (part == 0)
7418334Speter    return;
7518334Speter
7618334Speter  code = GET_CODE (part);
7718334Speter  switch (code)
7818334Speter    {
7918334Speter    case CLOBBER:
8018334Speter      clobbers_seen_this_insn++;
8118334Speter      break;
8218334Speter
8318334Speter    case MATCH_OPERAND:
8418334Speter      if (XINT (part, 0) > max_recog_operands)
8518334Speter	max_recog_operands = XINT (part, 0);
8618334Speter      return;
8718334Speter
8818334Speter    case MATCH_OP_DUP:
8918334Speter    case MATCH_PAR_DUP:
9018334Speter      ++dup_operands_seen_this_insn;
9118334Speter    case MATCH_SCRATCH:
9218334Speter    case MATCH_PARALLEL:
9318334Speter    case MATCH_OPERATOR:
9418334Speter      if (XINT (part, 0) > max_recog_operands)
9518334Speter	max_recog_operands = XINT (part, 0);
9618334Speter      /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
9718334Speter	 MATCH_PARALLEL.  */
9818334Speter      break;
9918334Speter
10018334Speter    case LABEL_REF:
101169689Skan      if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND
102169689Skan	  || GET_CODE (XEXP (part, 0)) == MATCH_DUP)
10318334Speter	break;
10418334Speter      return;
10518334Speter
10618334Speter    case MATCH_DUP:
10718334Speter      ++dup_operands_seen_this_insn;
10818334Speter      if (XINT (part, 0) > max_recog_operands)
10918334Speter	max_recog_operands = XINT (part, 0);
11018334Speter      return;
11118334Speter
11218334Speter    case CC0:
11318334Speter      if (recog_p)
11418334Speter	have_cc0_flag = 1;
11518334Speter      return;
11618334Speter
11718334Speter    case LO_SUM:
11818334Speter      if (recog_p)
11918334Speter	have_lo_sum_flag = 1;
12018334Speter      return;
12118334Speter
12218334Speter    case SET:
12318334Speter      walk_insn_part (SET_DEST (part), 0, recog_p);
12418334Speter      walk_insn_part (SET_SRC (part), recog_p,
12518334Speter		      GET_CODE (SET_DEST (part)) != PC);
12618334Speter      return;
12718334Speter
12818334Speter    case IF_THEN_ELSE:
12918334Speter      /* Only consider this machine as having a conditional move if the
13018334Speter	 two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
13118334Speter	 we have some specific IF_THEN_ELSE construct (like the doz
13218334Speter	 instruction on the RS/6000) that can't be used in the general
13318334Speter	 context we want it for.  */
13418334Speter
13518334Speter      if (recog_p && non_pc_set_src
13618334Speter	  && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
13718334Speter	  && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
13818334Speter	have_cmove_flag = 1;
13918334Speter      break;
14018334Speter
14190075Sobrien    case COND_EXEC:
14290075Sobrien      if (recog_p)
14390075Sobrien	have_cond_exec_flag = 1;
14490075Sobrien      break;
14590075Sobrien
14618334Speter    case REG: case CONST_INT: case SYMBOL_REF:
14718334Speter    case PC:
14818334Speter      return;
14950397Sobrien
15050397Sobrien    default:
15150397Sobrien      break;
15218334Speter    }
15318334Speter
15418334Speter  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
15518334Speter
15618334Speter  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
15718334Speter    switch (*format_ptr++)
15818334Speter      {
15918334Speter      case 'e':
16018334Speter      case 'u':
16118334Speter	walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
16218334Speter	break;
16318334Speter      case 'E':
16418334Speter	if (XVEC (part, i) != NULL)
16518334Speter	  for (j = 0; j < XVECLEN (part, i); j++)
16618334Speter	    walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
16718334Speter	break;
16818334Speter      }
16918334Speter}
17018334Speter
17118334Speterstatic void
172132718Skangen_insn (rtx insn)
17318334Speter{
17418334Speter  int i;
17518334Speter
17618334Speter  /* Walk the insn pattern to gather the #define's status.  */
17718334Speter  clobbers_seen_this_insn = 0;
17818334Speter  dup_operands_seen_this_insn = 0;
17918334Speter  if (XVEC (insn, 1) != 0)
18018334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
18118334Speter      walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
18218334Speter
18318334Speter  if (clobbers_seen_this_insn > max_clobbers_per_insn)
18418334Speter    max_clobbers_per_insn = clobbers_seen_this_insn;
18518334Speter  if (dup_operands_seen_this_insn > max_dup_operands)
18618334Speter    max_dup_operands = dup_operands_seen_this_insn;
18718334Speter}
18818334Speter
18918334Speter/* Similar but scan a define_expand.  */
19018334Speter
19118334Speterstatic void
192132718Skangen_expand (rtx insn)
19318334Speter{
19418334Speter  int i;
19518334Speter
19618334Speter  /* Walk the insn pattern to gather the #define's status.  */
19718334Speter
19818334Speter  /* Note that we don't bother recording the number of MATCH_DUPs
19918334Speter     that occur in a gen_expand, because only reload cares about that.  */
20018334Speter  if (XVEC (insn, 1) != 0)
20118334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
20218334Speter      {
20318334Speter	/* Compute the maximum SETs and CLOBBERS
20418334Speter	   in any one of the sub-insns;
20518334Speter	   don't sum across all of them.  */
20618334Speter	clobbers_seen_this_insn = 0;
20718334Speter
20818334Speter	walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
20918334Speter
21018334Speter	if (clobbers_seen_this_insn > max_clobbers_per_insn)
21118334Speter	  max_clobbers_per_insn = clobbers_seen_this_insn;
21218334Speter      }
21318334Speter}
21418334Speter
21518334Speter/* Similar but scan a define_split.  */
21618334Speter
21718334Speterstatic void
218132718Skangen_split (rtx split)
21918334Speter{
22018334Speter  int i;
22118334Speter
22218334Speter  /* Look through the patterns that are matched
22318334Speter     to compute the maximum operand number.  */
22418334Speter  for (i = 0; i < XVECLEN (split, 0); i++)
22518334Speter    walk_insn_part (XVECEXP (split, 0, i), 1, 0);
22618334Speter  /* Look at the number of insns this insn could split into.  */
22718334Speter  if (XVECLEN (split, 2) > max_insns_per_split)
22818334Speter    max_insns_per_split = XVECLEN (split, 2);
22918334Speter}
23018334Speter
23118334Speterstatic void
232132718Skangen_peephole (rtx peep)
23318334Speter{
23418334Speter  int i;
23518334Speter
23618334Speter  /* Look through the patterns that are matched
23718334Speter     to compute the maximum operand number.  */
23818334Speter  for (i = 0; i < XVECLEN (peep, 0); i++)
23918334Speter    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
24018334Speter}
24118334Speter
24290075Sobrienstatic void
243132718Skangen_peephole2 (rtx peep)
24418334Speter{
24590075Sobrien  int i, n;
24618334Speter
24790075Sobrien  /* Look through the patterns that are matched
24890075Sobrien     to compute the maximum operand number.  */
24990075Sobrien  for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
25090075Sobrien    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
25150397Sobrien
25290075Sobrien  /* Look at the number of insns this insn can be matched from.  */
25390075Sobrien  for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
25490075Sobrien    if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
25590075Sobrien	&& GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
25690075Sobrien      n++;
25790075Sobrien  if (n > max_insns_per_peep2)
25890075Sobrien    max_insns_per_peep2 = n;
25918334Speter}
26018334Speter
26118334Speterint
262132718Skanmain (int argc, char **argv)
26318334Speter{
26418334Speter  rtx desc;
26518334Speter
26690075Sobrien  progname = "genconfig";
26718334Speter
26890075Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
26990075Sobrien    return (FATAL_EXIT_CODE);
27018334Speter
27190075Sobrien  puts ("/* Generated automatically by the program `genconfig'");
27290075Sobrien  puts ("   from the machine description file `md'.  */\n");
27390075Sobrien  puts ("#ifndef GCC_INSN_CONFIG_H");
27490075Sobrien  puts ("#define GCC_INSN_CONFIG_H\n");
27518334Speter
27690075Sobrien  /* Allow at least 30 operands for the sake of asm constructs.  */
27790075Sobrien  /* ??? We *really* ought to reorganize things such that there
27890075Sobrien     is no fixed upper bound.  */
27990075Sobrien  max_recog_operands = 29;  /* We will add 1 later.  */
28018334Speter  max_dup_operands = 1;
28118334Speter
28218334Speter  /* Read the machine description.  */
28318334Speter
28418334Speter  while (1)
28518334Speter    {
28690075Sobrien      int line_no, insn_code_number = 0;
28790075Sobrien
28890075Sobrien      desc = read_md_rtx (&line_no, &insn_code_number);
28990075Sobrien      if (desc == NULL)
29018334Speter	break;
29190075Sobrien
29290075Sobrien      switch (GET_CODE (desc))
29390075Sobrien	{
29490075Sobrien  	  case DEFINE_INSN:
29590075Sobrien	    gen_insn (desc);
29690075Sobrien	    break;
29790075Sobrien
29890075Sobrien	  case DEFINE_EXPAND:
29990075Sobrien	    gen_expand (desc);
30090075Sobrien	    break;
30118334Speter
30290075Sobrien	  case DEFINE_SPLIT:
30390075Sobrien	    gen_split (desc);
30490075Sobrien	    break;
30590075Sobrien
30690075Sobrien	  case DEFINE_PEEPHOLE2:
30790075Sobrien	    have_peephole2_flag = 1;
30890075Sobrien	    gen_peephole2 (desc);
30990075Sobrien	    break;
31090075Sobrien
31190075Sobrien	  case DEFINE_PEEPHOLE:
31290075Sobrien	    have_peephole_flag = 1;
31390075Sobrien	    gen_peephole (desc);
31490075Sobrien	    break;
31590075Sobrien
31690075Sobrien	  default:
31790075Sobrien	    break;
31890075Sobrien	}
31918334Speter    }
32018334Speter
32190075Sobrien  printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
32290075Sobrien  printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
32318334Speter
32418334Speter  /* This is conditionally defined, in case the user writes code which emits
32518334Speter     more splits than we can readily see (and knows s/he does it).  */
32690075Sobrien  printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
32790075Sobrien  printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
32890075Sobrien  printf ("#endif\n");
32918334Speter
33018334Speter  if (have_cc0_flag)
331132718Skan    {
332132718Skan      printf ("#define HAVE_cc0 1\n");
333132718Skan      printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
334132718Skan    }
335132718Skan  else
336132718Skan    {
337169689Skan      /* We output CC0_P this way to make sure that X is declared
338169689Skan	 somewhere.  */
339169689Skan      printf ("#define CC0_P(X) ((X) ? 0 : 0)\n");
340132718Skan    }
34118334Speter
34218334Speter  if (have_cmove_flag)
34390075Sobrien    printf ("#define HAVE_conditional_move 1\n");
34418334Speter
34590075Sobrien  if (have_cond_exec_flag)
34690075Sobrien    printf ("#define HAVE_conditional_execution 1\n");
34790075Sobrien
34818334Speter  if (have_lo_sum_flag)
34990075Sobrien    printf ("#define HAVE_lo_sum 1\n");
35018334Speter
35190075Sobrien  if (have_peephole_flag)
35290075Sobrien    printf ("#define HAVE_peephole 1\n");
35390075Sobrien
35490075Sobrien  if (have_peephole2_flag)
35590075Sobrien    {
35690075Sobrien      printf ("#define HAVE_peephole2 1\n");
35790075Sobrien      printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
35890075Sobrien    }
35990075Sobrien
36090075Sobrien  puts("\n#endif /* GCC_INSN_CONFIG_H */");
36190075Sobrien
36290075Sobrien  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
36390075Sobrien    return FATAL_EXIT_CODE;
36490075Sobrien
36590075Sobrien  return SUCCESS_EXIT_CODE;
36618334Speter}
367