genoutput.c revision 132718
118334Speter/* Generate code from to output assembler insns as recognized from rtl.
2132718Skan   Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002,
3132718Skan   2003, 2004 Free Software Foundation, Inc.
418334Speter
590075SobrienThis file is part of GCC.
618334Speter
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1118334Speter
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2090075Sobrien02111-1307, USA.  */
2118334Speter
2218334Speter
2318334Speter/* This program reads the machine description for the compiler target machine
2418334Speter   and produces a file containing these things:
2518334Speter
2690075Sobrien   1. An array of `struct insn_data', which is indexed by insn code number,
2790075Sobrien   which contains:
2818334Speter
2990075Sobrien     a. `name' is the name for that pattern.  Nameless patterns are
3090075Sobrien     given a name.
3118334Speter
3290075Sobrien     b. `output' hold either the output template, an array of output
3390075Sobrien     templates, or an output function.
3418334Speter
3590075Sobrien     c. `genfun' is the function to generate a body for that pattern,
3690075Sobrien     given operands as arguments.
3718334Speter
3890075Sobrien     d. `n_operands' is the number of distinct operands in the pattern
3990075Sobrien     for that insn,
4018334Speter
4190075Sobrien     e. `n_dups' is the number of match_dup's that appear in the insn's
4290075Sobrien     pattern.  This says how many elements of `recog_data.dup_loc' are
4390075Sobrien     significant after an insn has been recognized.
4418334Speter
4590075Sobrien     f. `n_alternatives' is the number of alternatives in the constraints
4690075Sobrien     of each pattern.
4718334Speter
4890075Sobrien     g. `output_format' tells what type of thing `output' is.
4918334Speter
5090075Sobrien     h. `operand' is the base of an array of operand data for the insn.
5118334Speter
5290075Sobrien   2. An array of `struct insn_operand data', used by `operand' above.
5318334Speter
5490075Sobrien     a. `predicate', an int-valued function, is the match_operand predicate
5590075Sobrien     for this operand.
5618334Speter
5790075Sobrien     b. `constraint' is the constraint for this operand.  This exists
5890075Sobrien     only if register constraints appear in match_operand rtx's.
5918334Speter
6090075Sobrien     c. `address_p' indicates that the operand appears within ADDRESS
6190075Sobrien     rtx's.  This exists only if there are *no* register constraints
6290075Sobrien     in the match_operand rtx's.
6318334Speter
6490075Sobrien     d. `mode' is the machine mode that that operand is supposed to have.
6590075Sobrien
6690075Sobrien     e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART.
6790075Sobrien
6890075Sobrien     f. `eliminable', is nonzero for operands that are matched normally by
6990075Sobrien     MATCH_OPERAND; it is zero for operands that should not be changed during
7090075Sobrien     register elimination such as MATCH_OPERATORs.
7190075Sobrien
7290075Sobrien  The code number of an insn is simply its position in the machine
7390075Sobrien  description; code numbers are assigned sequentially to entries in
7490075Sobrien  the description, starting with code number 0.
7590075Sobrien
7690075Sobrien  Thus, the following entry in the machine description
7790075Sobrien
7818334Speter    (define_insn "clrdf"
7918334Speter      [(set (match_operand:DF 0 "general_operand" "")
8018334Speter	    (const_int 0))]
8118334Speter      ""
8218334Speter      "clrd %0")
8318334Speter
8490075Sobrien  assuming it is the 25th entry present, would cause
8590075Sobrien  insn_data[24].template to be "clrd %0", and
8690075Sobrien  insn_data[24].n_operands to be 1.  */
8718334Speter
88132718Skan#include "bconfig.h"
8950397Sobrien#include "system.h"
90132718Skan#include "coretypes.h"
91132718Skan#include "tm.h"
9218334Speter#include "rtl.h"
9390075Sobrien#include "errors.h"
9490075Sobrien#include "gensupport.h"
9518334Speter
9690075Sobrien/* No instruction can have more operands than this.  Sorry for this
9790075Sobrien   arbitrary limit, but what machine will have an instruction with
9890075Sobrien   this many operands?  */
9918334Speter
10018334Speter#define MAX_MAX_OPERANDS 40
10118334Speter
102132718Skanstatic int n_occurrences		(int, const char *);
103132718Skanstatic const char *strip_whitespace	(const char *);
10418334Speter
10518334Speter/* insns in the machine description are assigned sequential code numbers
10618334Speter   that are used by insn-recog.c (produced by genrecog) to communicate
10718334Speter   to insn-output.c (produced by this program).  */
10818334Speter
10918334Speterstatic int next_code_number;
11018334Speter
11118334Speter/* This counts all definitions in the md file,
11218334Speter   for the sake of error messages.  */
11318334Speter
11418334Speterstatic int next_index_number;
11518334Speter
11690075Sobrien/* This counts all operands used in the md file.  The first is null.  */
11790075Sobrien
11890075Sobrienstatic int next_operand_number = 1;
11990075Sobrien
12090075Sobrien/* Record in this chain all information about the operands we will output.  */
12190075Sobrien
12290075Sobrienstruct operand_data
12390075Sobrien{
12490075Sobrien  struct operand_data *next;
12590075Sobrien  int index;
12690075Sobrien  const char *predicate;
12790075Sobrien  const char *constraint;
12890075Sobrien  enum machine_mode mode;
12990075Sobrien  unsigned char n_alternatives;
13090075Sobrien  char address_p;
13190075Sobrien  char strict_low;
13290075Sobrien  char eliminable;
13390075Sobrien  char seen;
13490075Sobrien};
13590075Sobrien
13690075Sobrien/* Begin with a null operand at index 0.  */
13790075Sobrien
13890075Sobrienstatic struct operand_data null_operand =
13990075Sobrien{
14090075Sobrien  0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0
14190075Sobrien};
14290075Sobrien
14390075Sobrienstatic struct operand_data *odata = &null_operand;
14490075Sobrienstatic struct operand_data **odata_end = &null_operand.next;
14590075Sobrien
14690075Sobrien/* Must match the constants in recog.h.  */
14790075Sobrien
14890075Sobrien#define INSN_OUTPUT_FORMAT_NONE         0       /* abort */
14990075Sobrien#define INSN_OUTPUT_FORMAT_SINGLE       1       /* const char * */
15090075Sobrien#define INSN_OUTPUT_FORMAT_MULTI        2       /* const char * const * */
15190075Sobrien#define INSN_OUTPUT_FORMAT_FUNCTION     3       /* const char * (*)(...) */
15290075Sobrien
15318334Speter/* Record in this chain all information that we will output,
15418334Speter   associated with the code number of the insn.  */
15518334Speter
15618334Speterstruct data
15718334Speter{
15890075Sobrien  struct data *next;
15990075Sobrien  const char *name;
16090075Sobrien  const char *template;
16118334Speter  int code_number;
16218334Speter  int index_number;
16390075Sobrien  int lineno;
16418334Speter  int n_operands;		/* Number of operands this insn recognizes */
16518334Speter  int n_dups;			/* Number times match_dup appears in pattern */
16618334Speter  int n_alternatives;		/* Number of alternatives in each constraint */
16790075Sobrien  int operand_number;		/* Operand index in the big array.  */
16890075Sobrien  int output_format;		/* INSN_OUTPUT_FORMAT_*.  */
16990075Sobrien  struct operand_data operand[MAX_MAX_OPERANDS];
17018334Speter};
17118334Speter
17290075Sobrien/* This variable points to the first link in the insn chain.  */
17318334Speter
17490075Sobrienstatic struct data *idata, **idata_end = &idata;
17518334Speter
176132718Skanstatic void output_prologue (void);
177132718Skanstatic void output_operand_data (void);
178132718Skanstatic void output_insn_data (void);
179132718Skanstatic void output_get_insn_name (void);
180132718Skanstatic void scan_operands (struct data *, rtx, int, int);
181132718Skanstatic int compare_operands (struct operand_data *,
182132718Skan			     struct operand_data *);
183132718Skanstatic void place_operands (struct data *);
184132718Skanstatic void process_template (struct data *, const char *);
185132718Skanstatic void validate_insn_alternatives (struct data *);
186132718Skanstatic void validate_insn_operands (struct data *);
187132718Skanstatic void gen_insn (rtx, int);
188132718Skanstatic void gen_peephole (rtx, int);
189132718Skanstatic void gen_expand (rtx, int);
190132718Skanstatic void gen_split (rtx, int);
191132718Skanstatic void check_constraint_len (void);
192132718Skanstatic int constraint_len (const char *, int);
19350397Sobrien
19490075Sobrienconst char *
195132718Skanget_insn_name (int index)
19652284Sobrien{
19752284Sobrien  static char buf[100];
19852284Sobrien
19952284Sobrien  struct data *i, *last_named = NULL;
20090075Sobrien  for (i = idata; i ; i = i->next)
20152284Sobrien    {
20252284Sobrien      if (i->index_number == index)
20352284Sobrien	return i->name;
20452284Sobrien      if (i->name)
20552284Sobrien	last_named = i;
20652284Sobrien    }
20752284Sobrien
20852284Sobrien  if (last_named)
20952284Sobrien    sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number);
21052284Sobrien  else
21152284Sobrien    sprintf(buf, "insn %d", index);
21252284Sobrien
21352284Sobrien  return buf;
21452284Sobrien}
21552284Sobrien
21618334Speterstatic void
217132718Skanoutput_prologue (void)
21818334Speter{
21918334Speter  printf ("/* Generated automatically by the program `genoutput'\n\
22090075Sobrien   from the machine description file `md'.  */\n\n");
22118334Speter
22218334Speter  printf ("#include \"config.h\"\n");
22350397Sobrien  printf ("#include \"system.h\"\n");
224132718Skan  printf ("#include \"coretypes.h\"\n");
225132718Skan  printf ("#include \"tm.h\"\n");
22650397Sobrien  printf ("#include \"flags.h\"\n");
22790075Sobrien  printf ("#include \"ggc.h\"\n");
22818334Speter  printf ("#include \"rtl.h\"\n");
22990075Sobrien  printf ("#include \"expr.h\"\n");
23090075Sobrien  printf ("#include \"insn-codes.h\"\n");
23190075Sobrien  printf ("#include \"tm_p.h\"\n");
23290075Sobrien  printf ("#include \"function.h\"\n");
23318334Speter  printf ("#include \"regs.h\"\n");
23418334Speter  printf ("#include \"hard-reg-set.h\"\n");
23518334Speter  printf ("#include \"real.h\"\n");
23618334Speter  printf ("#include \"insn-config.h\"\n\n");
23718334Speter  printf ("#include \"conditions.h\"\n");
23818334Speter  printf ("#include \"insn-attr.h\"\n\n");
23918334Speter  printf ("#include \"recog.h\"\n\n");
24090075Sobrien  printf ("#include \"toplev.h\"\n");
24118334Speter  printf ("#include \"output.h\"\n");
242132718Skan  printf ("#include \"target.h\"\n");
24318334Speter}
24418334Speter
24518334Speterstatic void
246132718Skanoutput_operand_data (void)
24718334Speter{
24890075Sobrien  struct operand_data *d;
24918334Speter
25090075Sobrien  printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n");
25190075Sobrien
25290075Sobrien  for (d = odata; d; d = d->next)
25318334Speter    {
25490075Sobrien      printf ("  {\n");
25518334Speter
25690075Sobrien      printf ("    %s,\n",
25790075Sobrien	      d->predicate && d->predicate[0] ? d->predicate : "0");
25890075Sobrien
25990075Sobrien      printf ("    \"%s\",\n", d->constraint ? d->constraint : "");
26090075Sobrien
26190075Sobrien      printf ("    %smode,\n", GET_MODE_NAME (d->mode));
26290075Sobrien
26390075Sobrien      printf ("    %d,\n", d->strict_low);
26490075Sobrien
26590075Sobrien      printf ("    %d\n", d->eliminable);
26690075Sobrien
26790075Sobrien      printf("  },\n");
26818334Speter    }
26990075Sobrien  printf("};\n\n\n");
27090075Sobrien}
27118334Speter
27290075Sobrienstatic void
273132718Skanoutput_insn_data (void)
27490075Sobrien{
27590075Sobrien  struct data *d;
27690075Sobrien  int name_offset = 0;
27790075Sobrien  int next_name_offset;
27890075Sobrien  const char * last_name = 0;
27990075Sobrien  const char * next_name = 0;
28090075Sobrien  struct data *n;
28118334Speter
28290075Sobrien  for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++)
28390075Sobrien    if (n->name)
28418334Speter      {
28590075Sobrien	next_name = n->name;
28690075Sobrien	break;
28718334Speter      }
28818334Speter
289132718Skan  printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n");
29090075Sobrien  printf ("\nconst struct insn_data insn_data[] = \n{\n");
29118334Speter
29290075Sobrien  for (d = idata; d; d = d->next)
29390075Sobrien    {
29490075Sobrien      printf ("  {\n");
29518334Speter
29690075Sobrien      if (d->name)
29718334Speter	{
29890075Sobrien	  printf ("    \"%s\",\n", d->name);
29990075Sobrien	  name_offset = 0;
30090075Sobrien	  last_name = d->name;
30190075Sobrien	  next_name = 0;
30290075Sobrien	  for (n = d->next, next_name_offset = 1; n;
30390075Sobrien	       n = n->next, next_name_offset++)
30418334Speter	    {
30590075Sobrien	      if (n->name)
30690075Sobrien		{
30790075Sobrien		  next_name = n->name;
30890075Sobrien		  break;
30990075Sobrien		}
31018334Speter	    }
31118334Speter	}
31290075Sobrien      else
31318334Speter	{
31490075Sobrien	  name_offset++;
31590075Sobrien	  if (next_name && (last_name == 0
31690075Sobrien			    || name_offset > next_name_offset / 2))
31790075Sobrien	    printf ("    \"%s-%d\",\n", next_name,
31890075Sobrien		    next_name_offset - name_offset);
31990075Sobrien	  else
32090075Sobrien	    printf ("    \"%s+%d\",\n", last_name, name_offset);
32118334Speter	}
32218334Speter
32390075Sobrien      switch (d->output_format)
32490075Sobrien	{
32590075Sobrien	case INSN_OUTPUT_FORMAT_NONE:
326132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
327132718Skan	  printf ("    { 0 },\n");
328132718Skan	  printf ("#else\n");
329132718Skan	  printf ("    { 0, 0, 0 },\n");
330132718Skan	  printf ("#endif\n");
33190075Sobrien	  break;
33290075Sobrien	case INSN_OUTPUT_FORMAT_SINGLE:
33318334Speter	  {
33490075Sobrien	    const char *p = d->template;
33590075Sobrien	    char prev = 0;
336132718Skan
337132718Skan	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
338132718Skan	    printf ("    { .single =\n");
339132718Skan	    printf ("#else\n");
340132718Skan	    printf ("    {\n");
341132718Skan	    printf ("#endif\n");
34290075Sobrien	    printf ("    \"");
34390075Sobrien	    while (*p)
34418334Speter	      {
34596263Sobrien		if (IS_VSPACE (*p) && prev != '\\')
34696263Sobrien		  {
34796263Sobrien		    /* Preserve two consecutive \n's or \r's, but treat \r\n
34896263Sobrien		       as a single newline.  */
34996263Sobrien		    if (*p == '\n' && prev != '\r')
35096263Sobrien		      printf ("\\n\\\n");
35196263Sobrien		  }
35290075Sobrien		else
35390075Sobrien		  putchar (*p);
35490075Sobrien		prev = *p;
35590075Sobrien		++p;
35618334Speter	      }
35790075Sobrien	    printf ("\",\n");
358132718Skan	    printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
359132718Skan	    printf ("    },\n");
360132718Skan	    printf ("#else\n");
361132718Skan	    printf ("    0, 0 },\n");
362132718Skan	    printf ("#endif\n");
36318334Speter	  }
36490075Sobrien	  break;
36590075Sobrien	case INSN_OUTPUT_FORMAT_MULTI:
366132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
367132718Skan	  printf ("    { .multi = output_%d },\n", d->code_number);
368132718Skan	  printf ("#else\n");
369132718Skan	  printf ("    { 0, output_%d, 0 },\n", d->code_number);
370132718Skan	  printf ("#endif\n");
371132718Skan	  break;
37290075Sobrien	case INSN_OUTPUT_FORMAT_FUNCTION:
373132718Skan	  printf ("#if HAVE_DESIGNATED_INITIALIZERS\n");
374132718Skan	  printf ("    { .function = output_%d },\n", d->code_number);
375132718Skan	  printf ("#else\n");
376132718Skan	  printf ("    { 0, 0, output_%d },\n", d->code_number);
377132718Skan	  printf ("#endif\n");
37890075Sobrien	  break;
37990075Sobrien	default:
38090075Sobrien	  abort ();
38190075Sobrien	}
38218334Speter
38390075Sobrien      if (d->name && d->name[0] != '*')
38490075Sobrien	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
38590075Sobrien      else
38690075Sobrien	printf ("    0,\n");
38790075Sobrien
38890075Sobrien      printf ("    &operand_data[%d],\n", d->operand_number);
38990075Sobrien      printf ("    %d,\n", d->n_operands);
39090075Sobrien      printf ("    %d,\n", d->n_dups);
39190075Sobrien      printf ("    %d,\n", d->n_alternatives);
39290075Sobrien      printf ("    %d\n", d->output_format);
39390075Sobrien
39490075Sobrien      printf("  },\n");
39590075Sobrien    }
39690075Sobrien  printf ("};\n\n\n");
39718334Speter}
39890075Sobrien
39990075Sobrienstatic void
400132718Skanoutput_get_insn_name (void)
40190075Sobrien{
40290075Sobrien  printf ("const char *\n");
403132718Skan  printf ("get_insn_name (int code)\n");
40490075Sobrien  printf ("{\n");
405132718Skan  printf ("  if (code == NOOP_MOVE_INSN_CODE)\n");
406132718Skan  printf ("    return \"NOOP_MOVE\";\n");
407132718Skan  printf ("  else\n");
408132718Skan  printf ("    return insn_data[code].name;\n");
40990075Sobrien  printf ("}\n");
41090075Sobrien}
41190075Sobrien
41218334Speter
41390075Sobrien/* Stores in max_opno the largest operand number present in `part', if
41490075Sobrien   that is larger than the previous value of max_opno, and the rest of
41590075Sobrien   the operand data into `d->operand[i]'.
41618334Speter
41718334Speter   THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
41818334Speter   THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART.  */
41918334Speter
42018334Speterstatic int max_opno;
42118334Speterstatic int num_dups;
42218334Speter
42318334Speterstatic void
424132718Skanscan_operands (struct data *d, rtx part, int this_address_p,
425132718Skan	       int this_strict_low)
42618334Speter{
42790075Sobrien  int i, j;
42890075Sobrien  const char *format_ptr;
42918334Speter  int opno;
43018334Speter
43118334Speter  if (part == 0)
43218334Speter    return;
43318334Speter
43418334Speter  switch (GET_CODE (part))
43518334Speter    {
43618334Speter    case MATCH_OPERAND:
43718334Speter      opno = XINT (part, 0);
43818334Speter      if (opno > max_opno)
43918334Speter	max_opno = opno;
44018334Speter      if (max_opno >= MAX_MAX_OPERANDS)
44118334Speter	{
44290075Sobrien	  message_with_line (d->lineno,
44390075Sobrien			     "maximum number of operands exceeded");
44490075Sobrien	  have_error = 1;
44518334Speter	  return;
44618334Speter	}
44790075Sobrien      if (d->operand[opno].seen)
44818334Speter	{
44990075Sobrien	  message_with_line (d->lineno,
45090075Sobrien			     "repeated operand number %d\n", opno);
45190075Sobrien	  have_error = 1;
45218334Speter	}
45390075Sobrien
45490075Sobrien      d->operand[opno].seen = 1;
45590075Sobrien      d->operand[opno].mode = GET_MODE (part);
45690075Sobrien      d->operand[opno].strict_low = this_strict_low;
45790075Sobrien      d->operand[opno].predicate = XSTR (part, 1);
45890075Sobrien      d->operand[opno].constraint = strip_whitespace (XSTR (part, 2));
45990075Sobrien      d->operand[opno].n_alternatives
46090075Sobrien	= n_occurrences (',', d->operand[opno].constraint) + 1;
46190075Sobrien      d->operand[opno].address_p = this_address_p;
46290075Sobrien      d->operand[opno].eliminable = 1;
46318334Speter      return;
46418334Speter
46518334Speter    case MATCH_SCRATCH:
46618334Speter      opno = XINT (part, 0);
46718334Speter      if (opno > max_opno)
46818334Speter	max_opno = opno;
46918334Speter      if (max_opno >= MAX_MAX_OPERANDS)
47018334Speter	{
47190075Sobrien	  message_with_line (d->lineno,
47290075Sobrien			     "maximum number of operands exceeded");
47390075Sobrien	  have_error = 1;
47418334Speter	  return;
47518334Speter	}
47690075Sobrien      if (d->operand[opno].seen)
47718334Speter	{
47890075Sobrien	  message_with_line (d->lineno,
47990075Sobrien			     "repeated operand number %d\n", opno);
48090075Sobrien	  have_error = 1;
48118334Speter	}
48290075Sobrien
48390075Sobrien      d->operand[opno].seen = 1;
48490075Sobrien      d->operand[opno].mode = GET_MODE (part);
48590075Sobrien      d->operand[opno].strict_low = 0;
48690075Sobrien      d->operand[opno].predicate = "scratch_operand";
48790075Sobrien      d->operand[opno].constraint = strip_whitespace (XSTR (part, 1));
48890075Sobrien      d->operand[opno].n_alternatives
48990075Sobrien	= n_occurrences (',', d->operand[opno].constraint) + 1;
49090075Sobrien      d->operand[opno].address_p = 0;
49190075Sobrien      d->operand[opno].eliminable = 0;
49218334Speter      return;
49318334Speter
49418334Speter    case MATCH_OPERATOR:
49518334Speter    case MATCH_PARALLEL:
49618334Speter      opno = XINT (part, 0);
49718334Speter      if (opno > max_opno)
49818334Speter	max_opno = opno;
49918334Speter      if (max_opno >= MAX_MAX_OPERANDS)
50018334Speter	{
50190075Sobrien	  message_with_line (d->lineno,
50290075Sobrien			     "maximum number of operands exceeded");
50390075Sobrien	  have_error = 1;
50418334Speter	  return;
50518334Speter	}
50690075Sobrien      if (d->operand[opno].seen)
50790075Sobrien	{
50890075Sobrien	  message_with_line (d->lineno,
50990075Sobrien			     "repeated operand number %d\n", opno);
51090075Sobrien	  have_error = 1;
51190075Sobrien	}
51290075Sobrien
51390075Sobrien      d->operand[opno].seen = 1;
51490075Sobrien      d->operand[opno].mode = GET_MODE (part);
51590075Sobrien      d->operand[opno].strict_low = 0;
51690075Sobrien      d->operand[opno].predicate = XSTR (part, 1);
51790075Sobrien      d->operand[opno].constraint = 0;
51890075Sobrien      d->operand[opno].address_p = 0;
51990075Sobrien      d->operand[opno].eliminable = 0;
52018334Speter      for (i = 0; i < XVECLEN (part, 2); i++)
52190075Sobrien	scan_operands (d, XVECEXP (part, 2, i), 0, 0);
52218334Speter      return;
52318334Speter
52418334Speter    case MATCH_DUP:
52518334Speter    case MATCH_OP_DUP:
52618334Speter    case MATCH_PAR_DUP:
52718334Speter      ++num_dups;
52896263Sobrien      break;
52918334Speter
53018334Speter    case ADDRESS:
53190075Sobrien      scan_operands (d, XEXP (part, 0), 1, 0);
53218334Speter      return;
53318334Speter
53418334Speter    case STRICT_LOW_PART:
53590075Sobrien      scan_operands (d, XEXP (part, 0), 0, 1);
53618334Speter      return;
537132718Skan
53850397Sobrien    default:
53950397Sobrien      break;
54018334Speter    }
54118334Speter
54218334Speter  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
54318334Speter
54418334Speter  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
54518334Speter    switch (*format_ptr++)
54618334Speter      {
54718334Speter      case 'e':
54850397Sobrien      case 'u':
54990075Sobrien	scan_operands (d, XEXP (part, i), 0, 0);
55018334Speter	break;
55118334Speter      case 'E':
55218334Speter	if (XVEC (part, i) != NULL)
55318334Speter	  for (j = 0; j < XVECLEN (part, i); j++)
55490075Sobrien	    scan_operands (d, XVECEXP (part, i, j), 0, 0);
55518334Speter	break;
55618334Speter      }
55718334Speter}
55890075Sobrien
55990075Sobrien/* Compare two operands for content equality.  */
56090075Sobrien
56190075Sobrienstatic int
562132718Skancompare_operands (struct operand_data *d0, struct operand_data *d1)
56390075Sobrien{
56490075Sobrien  const char *p0, *p1;
56590075Sobrien
56690075Sobrien  p0 = d0->predicate;
56790075Sobrien  if (!p0)
56890075Sobrien    p0 = "";
56990075Sobrien  p1 = d1->predicate;
57090075Sobrien  if (!p1)
57190075Sobrien    p1 = "";
57290075Sobrien  if (strcmp (p0, p1) != 0)
57390075Sobrien    return 0;
57490075Sobrien
57590075Sobrien  p0 = d0->constraint;
57690075Sobrien  if (!p0)
57790075Sobrien    p0 = "";
57890075Sobrien  p1 = d1->constraint;
57990075Sobrien  if (!p1)
58090075Sobrien    p1 = "";
58190075Sobrien  if (strcmp (p0, p1) != 0)
58290075Sobrien    return 0;
58390075Sobrien
58490075Sobrien  if (d0->mode != d1->mode)
58590075Sobrien    return 0;
58690075Sobrien
58790075Sobrien  if (d0->strict_low != d1->strict_low)
58890075Sobrien    return 0;
58990075Sobrien
59090075Sobrien  if (d0->eliminable != d1->eliminable)
59190075Sobrien    return 0;
59290075Sobrien
59390075Sobrien  return 1;
59490075Sobrien}
59590075Sobrien
59690075Sobrien/* Scan the list of operands we've already committed to output and either
59790075Sobrien   find a subsequence that is the same, or allocate a new one at the end.  */
59890075Sobrien
59990075Sobrienstatic void
600132718Skanplace_operands (struct data *d)
60190075Sobrien{
60290075Sobrien  struct operand_data *od, *od2;
60390075Sobrien  int i;
60490075Sobrien
60590075Sobrien  if (d->n_operands == 0)
60690075Sobrien    {
60790075Sobrien      d->operand_number = 0;
60890075Sobrien      return;
60990075Sobrien    }
61090075Sobrien
61190075Sobrien  /* Brute force substring search.  */
61290075Sobrien  for (od = odata, i = 0; od; od = od->next, i = 0)
61390075Sobrien    if (compare_operands (od, &d->operand[0]))
61490075Sobrien      {
61590075Sobrien	od2 = od->next;
61690075Sobrien	i = 1;
61790075Sobrien	while (1)
61890075Sobrien	  {
61990075Sobrien	    if (i == d->n_operands)
62090075Sobrien	      goto full_match;
62190075Sobrien	    if (od2 == NULL)
62290075Sobrien	      goto partial_match;
62390075Sobrien	    if (! compare_operands (od2, &d->operand[i]))
62490075Sobrien	      break;
62590075Sobrien	    ++i, od2 = od2->next;
62690075Sobrien	  }
62790075Sobrien      }
62890075Sobrien
62990075Sobrien  /* Either partial match at the end of the list, or no match.  In either
63090075Sobrien     case, we tack on what operands are remaining to the end of the list.  */
63190075Sobrien partial_match:
63290075Sobrien  d->operand_number = next_operand_number - i;
63390075Sobrien  for (; i < d->n_operands; ++i)
63490075Sobrien    {
63590075Sobrien      od2 = &d->operand[i];
63690075Sobrien      *odata_end = od2;
63790075Sobrien      odata_end = &od2->next;
63890075Sobrien      od2->index = next_operand_number++;
63990075Sobrien    }
64090075Sobrien  *odata_end = NULL;
64190075Sobrien  return;
64290075Sobrien
64390075Sobrien full_match:
64490075Sobrien  d->operand_number = od->index;
64590075Sobrien  return;
64690075Sobrien}
64790075Sobrien
64818334Speter
64918334Speter/* Process an assembler template from a define_insn or a define_peephole.
65018334Speter   It is either the assembler code template, a list of assembler code
65118334Speter   templates, or C code to generate the assembler code template.  */
65218334Speter
65318334Speterstatic void
654132718Skanprocess_template (struct data *d, const char *template)
65518334Speter{
65690075Sobrien  const char *cp;
65790075Sobrien  int i;
65818334Speter
65990075Sobrien  /* Templates starting with * contain straight code to be run.  */
66090075Sobrien  if (template[0] == '*')
66118334Speter    {
66290075Sobrien      d->template = 0;
66390075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
66418334Speter
665132718Skan      puts ("\nstatic const char *");
666132718Skan      printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
66790075Sobrien	      d->code_number);
66890075Sobrien      puts ("{");
66918334Speter
67090075Sobrien      puts (template + 1);
67190075Sobrien      puts ("}");
67290075Sobrien    }
67318334Speter
67418334Speter  /* If the assembler code template starts with a @ it is a newline-separated
67590075Sobrien     list of assembler code templates, one for each alternative.  */
67690075Sobrien  else if (template[0] == '@')
67718334Speter    {
67890075Sobrien      d->template = 0;
67990075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_MULTI;
68018334Speter
68190075Sobrien      printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
68218334Speter
68318334Speter      for (i = 0, cp = &template[1]; *cp; )
68418334Speter	{
68596263Sobrien	  while (ISSPACE (*cp))
68618334Speter	    cp++;
68718334Speter
68890075Sobrien	  printf ("  \"");
68996263Sobrien	  while (!IS_VSPACE (*cp) && *cp != '\0')
69050397Sobrien	    {
69150397Sobrien	      putchar (*cp);
69250397Sobrien	      cp++;
69350397Sobrien	    }
69418334Speter
69518334Speter	  printf ("\",\n");
69618334Speter	  i++;
69718334Speter	}
69890075Sobrien      if (i == 1)
69990075Sobrien	message_with_line (d->lineno,
70090075Sobrien			   "'@' is redundant for output template with single alternative");
70118334Speter      if (i != d->n_alternatives)
70290075Sobrien	{
70390075Sobrien	  message_with_line (d->lineno,
70490075Sobrien			     "wrong number of alternatives in the output template");
70590075Sobrien	  have_error = 1;
70690075Sobrien	}
70718334Speter
70890075Sobrien      printf ("};\n");
70918334Speter    }
71018334Speter  else
71118334Speter    {
71290075Sobrien      d->template = template;
71390075Sobrien      d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
71418334Speter    }
71518334Speter}
71618334Speter
71718334Speter/* Check insn D for consistency in number of constraint alternatives.  */
71818334Speter
71918334Speterstatic void
720132718Skanvalidate_insn_alternatives (struct data *d)
72118334Speter{
72290075Sobrien  int n = 0, start;
72390075Sobrien
72490075Sobrien  /* Make sure all the operands have the same number of alternatives
72590075Sobrien     in their constraints.  Let N be that number.  */
72618334Speter  for (start = 0; start < d->n_operands; start++)
72790075Sobrien    if (d->operand[start].n_alternatives > 0)
72818334Speter      {
729132718Skan	int len, i;
730132718Skan	const char *p;
731132718Skan	char c;
732132718Skan	int which_alternative = 0;
733132718Skan	int alternative_count_unsure = 0;
734132718Skan
735132718Skan	for (p = d->operand[start].constraint; (c = *p); p += len)
736132718Skan	  {
737132718Skan	    len = CONSTRAINT_LEN (c, p);
738132718Skan
739132718Skan	    if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
740132718Skan	      {
741132718Skan		message_with_line (d->lineno,
742132718Skan				   "invalid length %d for char '%c' in alternative %d of operand %d",
743132718Skan				    len, c, which_alternative, start);
744132718Skan		len = 1;
745132718Skan		have_error = 1;
746132718Skan	      }
747132718Skan
748132718Skan	    if (c == ',')
749132718Skan	      {
750132718Skan	        which_alternative++;
751132718Skan		continue;
752132718Skan	      }
753132718Skan
754132718Skan	    for (i = 1; i < len; i++)
755132718Skan	      if (p[i] == '\0')
756132718Skan		{
757132718Skan		  message_with_line (d->lineno,
758132718Skan				     "NUL in alternative %d of operand %d",
759132718Skan				     which_alternative, start);
760132718Skan		  alternative_count_unsure = 1;
761132718Skan		  break;
762132718Skan		}
763132718Skan	      else if (strchr (",#*", p[i]))
764132718Skan		{
765132718Skan		  message_with_line (d->lineno,
766132718Skan				     "'%c' in alternative %d of operand %d",
767132718Skan				     p[i], which_alternative, start);
768132718Skan		  alternative_count_unsure = 1;
769132718Skan		}
770132718Skan	  }
771132718Skan	if (alternative_count_unsure)
772132718Skan	  have_error = 1;
773132718Skan	else if (n == 0)
77490075Sobrien	  n = d->operand[start].n_alternatives;
77590075Sobrien	else if (n != d->operand[start].n_alternatives)
77690075Sobrien	  {
77790075Sobrien	    message_with_line (d->lineno,
77890075Sobrien			       "wrong number of alternatives in operand %d",
77990075Sobrien			       start);
78090075Sobrien	    have_error = 1;
78190075Sobrien	  }
78218334Speter      }
78390075Sobrien
78418334Speter  /* Record the insn's overall number of alternatives.  */
78518334Speter  d->n_alternatives = n;
78618334Speter}
78790075Sobrien
78890075Sobrien/* Verify that there are no gaps in operand numbers for INSNs.  */
78990075Sobrien
79090075Sobrienstatic void
791132718Skanvalidate_insn_operands (struct data *d)
79290075Sobrien{
79390075Sobrien  int i;
79490075Sobrien
79590075Sobrien  for (i = 0; i < d->n_operands; ++i)
79690075Sobrien    if (d->operand[i].seen == 0)
79790075Sobrien      {
79890075Sobrien	message_with_line (d->lineno, "missing operand %d", i);
79990075Sobrien	have_error = 1;
80090075Sobrien      }
80190075Sobrien}
80218334Speter
80390075Sobrien/* Look at a define_insn just read.  Assign its code number.  Record
80490075Sobrien   on idata the template and the number of arguments.  If the insn has
80590075Sobrien   a hairy output action, output a function for now.  */
80618334Speter
80718334Speterstatic void
808132718Skangen_insn (rtx insn, int lineno)
80918334Speter{
810132718Skan  struct data *d = xmalloc (sizeof (struct data));
81190075Sobrien  int i;
81218334Speter
81390075Sobrien  d->code_number = next_code_number;
81418334Speter  d->index_number = next_index_number;
81590075Sobrien  d->lineno = lineno;
81618334Speter  if (XSTR (insn, 0)[0])
81718334Speter    d->name = XSTR (insn, 0);
81818334Speter  else
81918334Speter    d->name = 0;
82018334Speter
82118334Speter  /* Build up the list in the same order as the insns are seen
82218334Speter     in the machine description.  */
82318334Speter  d->next = 0;
82490075Sobrien  *idata_end = d;
82590075Sobrien  idata_end = &d->next;
82618334Speter
82718334Speter  max_opno = -1;
82818334Speter  num_dups = 0;
82990075Sobrien  memset (d->operand, 0, sizeof (d->operand));
83018334Speter
83118334Speter  for (i = 0; i < XVECLEN (insn, 1); i++)
83290075Sobrien    scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
83318334Speter
83418334Speter  d->n_operands = max_opno + 1;
83518334Speter  d->n_dups = num_dups;
83618334Speter
837132718Skan  check_constraint_len ();
83890075Sobrien  validate_insn_operands (d);
83918334Speter  validate_insn_alternatives (d);
84090075Sobrien  place_operands (d);
84190075Sobrien  process_template (d, XTMPL (insn, 3));
84218334Speter}
84318334Speter
84418334Speter/* Look at a define_peephole just read.  Assign its code number.
84590075Sobrien   Record on idata the template and the number of arguments.
84618334Speter   If the insn has a hairy output action, output it now.  */
84718334Speter
84818334Speterstatic void
849132718Skangen_peephole (rtx peep, int lineno)
85018334Speter{
851132718Skan  struct data *d = xmalloc (sizeof (struct data));
85290075Sobrien  int i;
85318334Speter
85490075Sobrien  d->code_number = next_code_number;
85518334Speter  d->index_number = next_index_number;
85690075Sobrien  d->lineno = lineno;
85718334Speter  d->name = 0;
85818334Speter
85918334Speter  /* Build up the list in the same order as the insns are seen
86018334Speter     in the machine description.  */
86118334Speter  d->next = 0;
86290075Sobrien  *idata_end = d;
86390075Sobrien  idata_end = &d->next;
86418334Speter
86518334Speter  max_opno = -1;
86690075Sobrien  num_dups = 0;
86790075Sobrien  memset (d->operand, 0, sizeof (d->operand));
86818334Speter
86990075Sobrien  /* Get the number of operands by scanning all the patterns of the
87090075Sobrien     peephole optimizer.  But ignore all the rest of the information
87190075Sobrien     thus obtained.  */
87218334Speter  for (i = 0; i < XVECLEN (peep, 0); i++)
87390075Sobrien    scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
87418334Speter
87518334Speter  d->n_operands = max_opno + 1;
87618334Speter  d->n_dups = 0;
87718334Speter
87818334Speter  validate_insn_alternatives (d);
87990075Sobrien  place_operands (d);
88090075Sobrien  process_template (d, XTMPL (peep, 2));
88118334Speter}
88218334Speter
88318334Speter/* Process a define_expand just read.  Assign its code number,
88418334Speter   only for the purposes of `insn_gen_function'.  */
88518334Speter
88618334Speterstatic void
887132718Skangen_expand (rtx insn, int lineno)
88818334Speter{
889132718Skan  struct data *d = xmalloc (sizeof (struct data));
89090075Sobrien  int i;
89118334Speter
89290075Sobrien  d->code_number = next_code_number;
89318334Speter  d->index_number = next_index_number;
89490075Sobrien  d->lineno = lineno;
89518334Speter  if (XSTR (insn, 0)[0])
89618334Speter    d->name = XSTR (insn, 0);
89718334Speter  else
89818334Speter    d->name = 0;
89918334Speter
90018334Speter  /* Build up the list in the same order as the insns are seen
90118334Speter     in the machine description.  */
90218334Speter  d->next = 0;
90390075Sobrien  *idata_end = d;
90490075Sobrien  idata_end = &d->next;
90518334Speter
90618334Speter  max_opno = -1;
90718334Speter  num_dups = 0;
90890075Sobrien  memset (d->operand, 0, sizeof (d->operand));
90918334Speter
91018334Speter  /* Scan the operands to get the specified predicates and modes,
91118334Speter     since expand_binop needs to know them.  */
91218334Speter
91318334Speter  if (XVEC (insn, 1))
91418334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
91590075Sobrien      scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
91618334Speter
91718334Speter  d->n_operands = max_opno + 1;
91818334Speter  d->n_dups = num_dups;
91990075Sobrien  d->template = 0;
92090075Sobrien  d->output_format = INSN_OUTPUT_FORMAT_NONE;
92118334Speter
92218334Speter  validate_insn_alternatives (d);
92390075Sobrien  place_operands (d);
92418334Speter}
92518334Speter
92618334Speter/* Process a define_split just read.  Assign its code number,
92718334Speter   only for reasons of consistency and to simplify genrecog.  */
92818334Speter
92918334Speterstatic void
930132718Skangen_split (rtx split, int lineno)
93118334Speter{
932132718Skan  struct data *d = xmalloc (sizeof (struct data));
93390075Sobrien  int i;
93418334Speter
93590075Sobrien  d->code_number = next_code_number;
93618334Speter  d->index_number = next_index_number;
93790075Sobrien  d->lineno = lineno;
93818334Speter  d->name = 0;
93918334Speter
94018334Speter  /* Build up the list in the same order as the insns are seen
94118334Speter     in the machine description.  */
94218334Speter  d->next = 0;
94390075Sobrien  *idata_end = d;
94490075Sobrien  idata_end = &d->next;
94518334Speter
94618334Speter  max_opno = -1;
94718334Speter  num_dups = 0;
94890075Sobrien  memset (d->operand, 0, sizeof (d->operand));
94918334Speter
95090075Sobrien  /* Get the number of operands by scanning all the patterns of the
95190075Sobrien     split patterns.  But ignore all the rest of the information thus
95290075Sobrien     obtained.  */
95318334Speter  for (i = 0; i < XVECLEN (split, 0); i++)
95490075Sobrien    scan_operands (d, XVECEXP (split, 0, i), 0, 0);
95518334Speter
95618334Speter  d->n_operands = max_opno + 1;
95718334Speter  d->n_dups = 0;
95818334Speter  d->n_alternatives = 0;
95918334Speter  d->template = 0;
96090075Sobrien  d->output_format = INSN_OUTPUT_FORMAT_NONE;
96118334Speter
96290075Sobrien  place_operands (d);
96318334Speter}
96418334Speter
965132718Skanextern int main (int, char **);
96618334Speter
96718334Speterint
968132718Skanmain (int argc, char **argv)
96918334Speter{
97018334Speter  rtx desc;
97118334Speter
97290075Sobrien  progname = "genoutput";
97318334Speter
97418334Speter  if (argc <= 1)
97590075Sobrien    fatal ("no input file name");
97618334Speter
97790075Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
97890075Sobrien    return (FATAL_EXIT_CODE);
97918334Speter
98018334Speter  output_prologue ();
98118334Speter  next_code_number = 0;
98218334Speter  next_index_number = 0;
98318334Speter
98418334Speter  /* Read the machine description.  */
98518334Speter
98618334Speter  while (1)
98718334Speter    {
98890075Sobrien      int line_no;
98990075Sobrien
99090075Sobrien      desc = read_md_rtx (&line_no, &next_code_number);
99190075Sobrien      if (desc == NULL)
99218334Speter	break;
99318334Speter
99418334Speter      if (GET_CODE (desc) == DEFINE_INSN)
99590075Sobrien	gen_insn (desc, line_no);
99618334Speter      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
99790075Sobrien	gen_peephole (desc, line_no);
99818334Speter      if (GET_CODE (desc) == DEFINE_EXPAND)
99990075Sobrien	gen_expand (desc, line_no);
100090075Sobrien      if (GET_CODE (desc) == DEFINE_SPLIT
1001132718Skan	  || GET_CODE (desc) == DEFINE_PEEPHOLE2)
100290075Sobrien	gen_split (desc, line_no);
100318334Speter      next_index_number++;
100418334Speter    }
100518334Speter
100690075Sobrien  printf("\n\n");
100790075Sobrien  output_operand_data ();
100890075Sobrien  output_insn_data ();
100990075Sobrien  output_get_insn_name ();
101018334Speter
101118334Speter  fflush (stdout);
101290075Sobrien  return (ferror (stdout) != 0 || have_error
101318334Speter	? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
101418334Speter}
101518334Speter
101690075Sobrien/* Return the number of occurrences of character C in string S or
101790075Sobrien   -1 if S is the null string.  */
101890075Sobrien
101918334Speterstatic int
1020132718Skann_occurrences (int c, const char *s)
102118334Speter{
102218334Speter  int n = 0;
102390075Sobrien
102490075Sobrien  if (s == 0 || *s == '\0')
102590075Sobrien    return -1;
102690075Sobrien
102718334Speter  while (*s)
102818334Speter    n += (*s++ == c);
102990075Sobrien
103018334Speter  return n;
103118334Speter}
103290075Sobrien
103390075Sobrien/* Remove whitespace in `s' by moving up characters until the end.
103490075Sobrien   Return a new string.  */
103590075Sobrien
103690075Sobrienstatic const char *
1037132718Skanstrip_whitespace (const char *s)
103890075Sobrien{
103990075Sobrien  char *p, *q;
104090075Sobrien  char ch;
104190075Sobrien
104290075Sobrien  if (s == 0)
104390075Sobrien    return 0;
104490075Sobrien
104590075Sobrien  p = q = xmalloc (strlen (s) + 1);
104690075Sobrien  while ((ch = *s++) != '\0')
104790075Sobrien    if (! ISSPACE (ch))
104890075Sobrien      *p++ = ch;
104990075Sobrien
105090075Sobrien  *p = '\0';
105190075Sobrien  return q;
105290075Sobrien}
1053132718Skan
1054132718Skan/* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not
1055132718Skan   tampered with.  This isn't bullet-proof, but it should catch
1056132718Skan   most genuine mistakes.  */
1057132718Skanstatic void
1058132718Skancheck_constraint_len (void)
1059132718Skan{
1060132718Skan  const char *p;
1061132718Skan  int d;
1062132718Skan
1063132718Skan  for (p = ",#*+=&%!1234567890"; *p; p++)
1064132718Skan    for (d = -9; d < 9; d++)
1065132718Skan      if (constraint_len (p, d) != d)
1066132718Skan	abort ();
1067132718Skan}
1068132718Skan
1069132718Skanstatic int
1070132718Skanconstraint_len (const char *p, int genoutput_default_constraint_len)
1071132718Skan{
1072132718Skan  /* Check that we still match defaults.h .  First we do a generation-time
1073132718Skan     check that fails if the value is not the expected one...  */
1074132718Skan  if (DEFAULT_CONSTRAINT_LEN (*p, p) != 1)
1075132718Skan    abort ();
1076132718Skan  /* And now a compile-time check that should give a diagnostic if the
1077132718Skan     definition doesn't exactly match.  */
1078132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
1079132718Skan  /* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is
1080132718Skan     being used.  */
1081132718Skan#undef DEFAULT_CONSTRAINT_LEN
1082132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) \
1083132718Skan  ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len)
1084132718Skan  return CONSTRAINT_LEN (*p, p);
1085132718Skan  /* And set it back.  */
1086132718Skan#undef DEFAULT_CONSTRAINT_LEN
1087132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
1088132718Skan}
1089