118334Speter/* Generate from machine description:
218334Speter   - some flags HAVE_... saying which simple standard instructions are
318334Speter   available for this machine.
490075Sobrien   Copyright (C) 1987, 1991, 1995, 1998,
5132718Skan   1999, 2000, 2003, 2004 Free Software Foundation, Inc.
618334Speter
790075SobrienThis file is part of GCC.
818334Speter
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1318334Speter
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1818334Speter
1918334SpeterYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22169689Skan02110-1301, USA.  */
2318334Speter
2418334Speter
25132718Skan#include "bconfig.h"
2650397Sobrien#include "system.h"
27132718Skan#include "coretypes.h"
28132718Skan#include "tm.h"
2918334Speter#include "rtl.h"
3018334Speter#include "obstack.h"
3190075Sobrien#include "errors.h"
3290075Sobrien#include "gensupport.h"
3318334Speter
3490075Sobrien/* Obstack to remember insns with.  */
3590075Sobrienstatic struct obstack obstack;
3618334Speter
3718334Speter/* Max size of names encountered.  */
3818334Speterstatic int max_id_len;
3918334Speter
4090075Sobrien/* Max operand encountered in a scan over some insn.  */
4190075Sobrienstatic int max_opno;
4250397Sobrien
43132718Skanstatic void max_operand_1 (rtx);
44132718Skanstatic int num_operands (rtx);
45132718Skanstatic void gen_proto (rtx);
46132718Skanstatic void gen_macro (const char *, int, int);
47132718Skanstatic void gen_insn (rtx);
4850397Sobrien
4918334Speter/* Count the number of match_operand's found.  */
5050397Sobrien
5190075Sobrienstatic void
52132718Skanmax_operand_1 (rtx x)
5318334Speter{
5490075Sobrien  RTX_CODE code;
5590075Sobrien  int i;
5690075Sobrien  int len;
5790075Sobrien  const char *fmt;
5818334Speter
5990075Sobrien  if (x == 0)
6090075Sobrien    return;
6118334Speter
6290075Sobrien  code = GET_CODE (x);
6318334Speter
6490075Sobrien  if (code == MATCH_OPERAND || code == MATCH_OPERATOR
6590075Sobrien      || code == MATCH_PARALLEL)
6690075Sobrien    max_opno = MAX (max_opno, XINT (x, 0));
6790075Sobrien
6890075Sobrien  fmt = GET_RTX_FORMAT (code);
6990075Sobrien  len = GET_RTX_LENGTH (code);
7090075Sobrien  for (i = 0; i < len; i++)
7118334Speter    {
7290075Sobrien      if (fmt[i] == 'e' || fmt[i] == 'u')
7390075Sobrien	max_operand_1 (XEXP (x, i));
7490075Sobrien      else if (fmt[i] == 'E')
7518334Speter	{
7690075Sobrien	  int j;
7790075Sobrien	  for (j = 0; j < XVECLEN (x, i); j++)
7890075Sobrien	    max_operand_1 (XVECEXP (x, i, j));
7918334Speter	}
8018334Speter    }
8190075Sobrien}
8218334Speter
8390075Sobrienstatic int
84132718Skannum_operands (rtx insn)
8590075Sobrien{
8690075Sobrien  int len = XVECLEN (insn, 1);
8790075Sobrien  int i;
8890075Sobrien
8990075Sobrien  max_opno = -1;
9090075Sobrien
9190075Sobrien  for (i = 0; i < len; i++)
9290075Sobrien    max_operand_1 (XVECEXP (insn, 1, i));
9390075Sobrien
9490075Sobrien  return max_opno + 1;
9518334Speter}
9618334Speter
9790075Sobrien/* Print out a wrapper macro for a function which corrects the number
9890075Sobrien   of arguments it takes.  Any missing arguments are assumed to be at
9990075Sobrien   the end.  */
10090075Sobrienstatic void
101132718Skangen_macro (const char *name, int real, int expect)
10290075Sobrien{
10390075Sobrien  int i;
10490075Sobrien
105169689Skan  gcc_assert (real <= expect);
106169689Skan  gcc_assert (real);
10790075Sobrien
10890075Sobrien  /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
10990075Sobrien  fputs ("#define GEN_", stdout);
11090075Sobrien  for (i = 0; name[i]; i++)
11190075Sobrien    putchar (TOUPPER (name[i]));
11290075Sobrien
11390075Sobrien  putchar('(');
11490075Sobrien  for (i = 0; i < expect - 1; i++)
11590075Sobrien    printf ("%c, ", i + 'A');
11690075Sobrien  printf ("%c) gen_%s (", i + 'A', name);
11790075Sobrien
11890075Sobrien  for (i = 0; i < real - 1; i++)
11990075Sobrien    printf ("(%c), ", i + 'A');
12090075Sobrien  printf ("(%c))\n", i + 'A');
12190075Sobrien}
12290075Sobrien
123117395Skan/* Print out prototype information for a generator function.  If the
124117395Skan   insn pattern has been elided, print out a dummy generator that
125117395Skan   does nothing.  */
12650397Sobrien
12718334Speterstatic void
128132718Skangen_proto (rtx insn)
12918334Speter{
13018334Speter  int num = num_operands (insn);
131117395Skan  int i;
13290075Sobrien  const char *name = XSTR (insn, 0);
133117395Skan  int truth = maybe_eval_c_test (XSTR (insn, 2));
13418334Speter
13590075Sobrien  /* Many md files don't refer to the last two operands passed to the
13690075Sobrien     call patterns.  This means their generator functions will be two
13790075Sobrien     arguments too short.  Instead of changing every md file to touch
13890075Sobrien     those operands, we wrap the prototypes in macros that take the
13990075Sobrien     correct number of arguments.  */
14090075Sobrien  if (name[0] == 'c' || name[0] == 's')
14190075Sobrien    {
14290075Sobrien      if (!strcmp (name, "call")
14390075Sobrien	  || !strcmp (name, "call_pop")
14490075Sobrien	  || !strcmp (name, "sibcall")
14590075Sobrien	  || !strcmp (name, "sibcall_pop"))
14690075Sobrien	gen_macro (name, num, 4);
14790075Sobrien      else if (!strcmp (name, "call_value")
14890075Sobrien	       || !strcmp (name, "call_value_pop")
14990075Sobrien	       || !strcmp (name, "sibcall_value")
15090075Sobrien	       || !strcmp (name, "sibcall_value_pop"))
15190075Sobrien	gen_macro (name, num, 5);
15290075Sobrien    }
15390075Sobrien
154117395Skan  if (truth != 0)
155132718Skan    printf ("extern rtx        gen_%-*s (", max_id_len, name);
156117395Skan  else
157132718Skan    printf ("static inline rtx gen_%-*s (", max_id_len, name);
15890075Sobrien
15918334Speter  if (num == 0)
160117395Skan    fputs ("void", stdout);
16118334Speter  else
16218334Speter    {
163117395Skan      for (i = 1; i < num; i++)
164117395Skan	fputs ("rtx, ", stdout);
165132718Skan
166117395Skan      fputs ("rtx", stdout);
167117395Skan    }
16818334Speter
169132718Skan  puts (");");
170117395Skan
171117395Skan  /* Some back ends want to take the address of generator functions,
172117395Skan     so we cannot simply use #define for these dummy definitions.  */
173117395Skan  if (truth == 0)
174117395Skan    {
175117395Skan      printf ("static inline rtx\ngen_%s", name);
176117395Skan      if (num > 0)
177117395Skan	{
178117395Skan	  putchar ('(');
179117395Skan	  for (i = 0; i < num-1; i++)
180169689Skan	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
181169689Skan	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
182117395Skan	}
183117395Skan      else
184132718Skan	puts ("(void)");
185117395Skan      puts ("{\n  return 0;\n}");
18618334Speter    }
18718334Speter
18818334Speter}
18918334Speter
19018334Speterstatic void
191132718Skangen_insn (rtx insn)
19218334Speter{
19390075Sobrien  const char *name = XSTR (insn, 0);
19490075Sobrien  const char *p;
19518334Speter  int len;
196117395Skan  int truth = maybe_eval_c_test (XSTR (insn, 2));
19718334Speter
19818334Speter  /* Don't mention instructions whose names are the null string
19918334Speter     or begin with '*'.  They are in the machine description just
20018334Speter     to be recognized.  */
20118334Speter  if (name[0] == 0 || name[0] == '*')
20218334Speter    return;
20318334Speter
20418334Speter  len = strlen (name);
20518334Speter
20618334Speter  if (len > max_id_len)
20718334Speter    max_id_len = len;
20818334Speter
209117395Skan  if (truth == 0)
210132718Skan    /* Emit nothing.  */;
211117395Skan  else if (truth == 1)
212117395Skan    printf ("#define HAVE_%s 1\n", name);
21318334Speter  else
21418334Speter    {
21518334Speter      /* Write the macro definition, putting \'s at the end of each line,
21618334Speter	 if more than one.  */
217117395Skan      printf ("#define HAVE_%s (", name);
21818334Speter      for (p = XSTR (insn, 2); *p; p++)
21918334Speter	{
22096263Sobrien	  if (IS_VSPACE (*p))
221117395Skan	    fputs (" \\\n", stdout);
22218334Speter	  else
223117395Skan	    putchar (*p);
22418334Speter	}
225117395Skan      fputs (")\n", stdout);
22618334Speter    }
22718334Speter
22890075Sobrien  obstack_grow (&obstack, &insn, sizeof (rtx));
22918334Speter}
23018334Speter
23118334Speterint
232132718Skanmain (int argc, char **argv)
23318334Speter{
23418334Speter  rtx desc;
23518334Speter  rtx dummy;
23690075Sobrien  rtx *insns;
23718334Speter  rtx *insn_ptr;
23818334Speter
23990075Sobrien  progname = "genflags";
24090075Sobrien  obstack_init (&obstack);
24118334Speter
242117395Skan  /* We need to see all the possibilities.  Elided insns may have
243117395Skan     direct calls to their generators in C code.  */
244117395Skan  insn_elision = 0;
245117395Skan
24690075Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
24790075Sobrien    return (FATAL_EXIT_CODE);
248132718Skan
24990075Sobrien  puts ("/* Generated automatically by the program `genflags'");
25090075Sobrien  puts ("   from the machine description file `md'.  */\n");
25190075Sobrien  puts ("#ifndef GCC_INSN_FLAGS_H");
25290075Sobrien  puts ("#define GCC_INSN_FLAGS_H\n");
25318334Speter
25418334Speter  /* Read the machine description.  */
25518334Speter
25618334Speter  while (1)
25718334Speter    {
25890075Sobrien      int line_no, insn_code_number = 0;
25990075Sobrien
26090075Sobrien      desc = read_md_rtx (&line_no, &insn_code_number);
26190075Sobrien      if (desc == NULL)
26218334Speter	break;
26318334Speter      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
26418334Speter	gen_insn (desc);
26518334Speter    }
26618334Speter
26718334Speter  /* Print out the prototypes now.  */
26850397Sobrien  dummy = (rtx) 0;
26990075Sobrien  obstack_grow (&obstack, &dummy, sizeof (rtx));
270169689Skan  insns = XOBFINISH (&obstack, rtx *);
27118334Speter
27290075Sobrien  for (insn_ptr = insns; *insn_ptr; insn_ptr++)
27318334Speter    gen_proto (*insn_ptr);
27418334Speter
27590075Sobrien  puts("\n#endif /* GCC_INSN_FLAGS_H */");
27618334Speter
27790075Sobrien  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
27890075Sobrien    return FATAL_EXIT_CODE;
27918334Speter
28090075Sobrien  return SUCCESS_EXIT_CODE;
28190075Sobrien}
282