xref: /openbsd/gnu/usr.bin/gcc/gcc/genoutput.c (revision c87b03e5)
1*c87b03e5Sespie /* Generate code from to output assembler insns as recognized from rtl.
2*c87b03e5Sespie    Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000
3*c87b03e5Sespie    Free Software Foundation, Inc.
4*c87b03e5Sespie 
5*c87b03e5Sespie This file is part of GCC.
6*c87b03e5Sespie 
7*c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it under
8*c87b03e5Sespie the terms of the GNU General Public License as published by the Free
9*c87b03e5Sespie Software Foundation; either version 2, or (at your option) any later
10*c87b03e5Sespie version.
11*c87b03e5Sespie 
12*c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*c87b03e5Sespie WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*c87b03e5Sespie FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*c87b03e5Sespie for more details.
16*c87b03e5Sespie 
17*c87b03e5Sespie You should have received a copy of the GNU General Public License
18*c87b03e5Sespie along with GCC; see the file COPYING.  If not, write to the Free
19*c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20*c87b03e5Sespie 02111-1307, USA.  */
21*c87b03e5Sespie 
22*c87b03e5Sespie 
23*c87b03e5Sespie /* This program reads the machine description for the compiler target machine
24*c87b03e5Sespie    and produces a file containing these things:
25*c87b03e5Sespie 
26*c87b03e5Sespie    1. An array of `struct insn_data', which is indexed by insn code number,
27*c87b03e5Sespie    which contains:
28*c87b03e5Sespie 
29*c87b03e5Sespie      a. `name' is the name for that pattern.  Nameless patterns are
30*c87b03e5Sespie      given a name.
31*c87b03e5Sespie 
32*c87b03e5Sespie      b. `output' hold either the output template, an array of output
33*c87b03e5Sespie      templates, or an output function.
34*c87b03e5Sespie 
35*c87b03e5Sespie      c. `genfun' is the function to generate a body for that pattern,
36*c87b03e5Sespie      given operands as arguments.
37*c87b03e5Sespie 
38*c87b03e5Sespie      d. `n_operands' is the number of distinct operands in the pattern
39*c87b03e5Sespie      for that insn,
40*c87b03e5Sespie 
41*c87b03e5Sespie      e. `n_dups' is the number of match_dup's that appear in the insn's
42*c87b03e5Sespie      pattern.  This says how many elements of `recog_data.dup_loc' are
43*c87b03e5Sespie      significant after an insn has been recognized.
44*c87b03e5Sespie 
45*c87b03e5Sespie      f. `n_alternatives' is the number of alternatives in the constraints
46*c87b03e5Sespie      of each pattern.
47*c87b03e5Sespie 
48*c87b03e5Sespie      g. `output_format' tells what type of thing `output' is.
49*c87b03e5Sespie 
50*c87b03e5Sespie      h. `operand' is the base of an array of operand data for the insn.
51*c87b03e5Sespie 
52*c87b03e5Sespie    2. An array of `struct insn_operand data', used by `operand' above.
53*c87b03e5Sespie 
54*c87b03e5Sespie      a. `predicate', an int-valued function, is the match_operand predicate
55*c87b03e5Sespie      for this operand.
56*c87b03e5Sespie 
57*c87b03e5Sespie      b. `constraint' is the constraint for this operand.  This exists
58*c87b03e5Sespie      only if register constraints appear in match_operand rtx's.
59*c87b03e5Sespie 
60*c87b03e5Sespie      c. `address_p' indicates that the operand appears within ADDRESS
61*c87b03e5Sespie      rtx's.  This exists only if there are *no* register constraints
62*c87b03e5Sespie      in the match_operand rtx's.
63*c87b03e5Sespie 
64*c87b03e5Sespie      d. `mode' is the machine mode that that operand is supposed to have.
65*c87b03e5Sespie 
66*c87b03e5Sespie      e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART.
67*c87b03e5Sespie 
68*c87b03e5Sespie      f. `eliminable', is nonzero for operands that are matched normally by
69*c87b03e5Sespie      MATCH_OPERAND; it is zero for operands that should not be changed during
70*c87b03e5Sespie      register elimination such as MATCH_OPERATORs.
71*c87b03e5Sespie 
72*c87b03e5Sespie   The code number of an insn is simply its position in the machine
73*c87b03e5Sespie   description; code numbers are assigned sequentially to entries in
74*c87b03e5Sespie   the description, starting with code number 0.
75*c87b03e5Sespie 
76*c87b03e5Sespie   Thus, the following entry in the machine description
77*c87b03e5Sespie 
78*c87b03e5Sespie     (define_insn "clrdf"
79*c87b03e5Sespie       [(set (match_operand:DF 0 "general_operand" "")
80*c87b03e5Sespie 	    (const_int 0))]
81*c87b03e5Sespie       ""
82*c87b03e5Sespie       "clrd %0")
83*c87b03e5Sespie 
84*c87b03e5Sespie   assuming it is the 25th entry present, would cause
85*c87b03e5Sespie   insn_data[24].template to be "clrd %0", and
86*c87b03e5Sespie   insn_data[24].n_operands to be 1.  */
87*c87b03e5Sespie 
88*c87b03e5Sespie #include "hconfig.h"
89*c87b03e5Sespie #include "system.h"
90*c87b03e5Sespie #include "rtl.h"
91*c87b03e5Sespie #include "errors.h"
92*c87b03e5Sespie #include "gensupport.h"
93*c87b03e5Sespie 
94*c87b03e5Sespie /* No instruction can have more operands than this.  Sorry for this
95*c87b03e5Sespie    arbitrary limit, but what machine will have an instruction with
96*c87b03e5Sespie    this many operands?  */
97*c87b03e5Sespie 
98*c87b03e5Sespie #define MAX_MAX_OPERANDS 40
99*c87b03e5Sespie 
100*c87b03e5Sespie static int n_occurrences		PARAMS ((int, const char *));
101*c87b03e5Sespie static const char *strip_whitespace	PARAMS ((const char *));
102*c87b03e5Sespie 
103*c87b03e5Sespie /* insns in the machine description are assigned sequential code numbers
104*c87b03e5Sespie    that are used by insn-recog.c (produced by genrecog) to communicate
105*c87b03e5Sespie    to insn-output.c (produced by this program).  */
106*c87b03e5Sespie 
107*c87b03e5Sespie static int next_code_number;
108*c87b03e5Sespie 
109*c87b03e5Sespie /* This counts all definitions in the md file,
110*c87b03e5Sespie    for the sake of error messages.  */
111*c87b03e5Sespie 
112*c87b03e5Sespie static int next_index_number;
113*c87b03e5Sespie 
114*c87b03e5Sespie /* This counts all operands used in the md file.  The first is null.  */
115*c87b03e5Sespie 
116*c87b03e5Sespie static int next_operand_number = 1;
117*c87b03e5Sespie 
118*c87b03e5Sespie /* Record in this chain all information about the operands we will output.  */
119*c87b03e5Sespie 
120*c87b03e5Sespie struct operand_data
121*c87b03e5Sespie {
122*c87b03e5Sespie   struct operand_data *next;
123*c87b03e5Sespie   int index;
124*c87b03e5Sespie   const char *predicate;
125*c87b03e5Sespie   const char *constraint;
126*c87b03e5Sespie   enum machine_mode mode;
127*c87b03e5Sespie   unsigned char n_alternatives;
128*c87b03e5Sespie   char address_p;
129*c87b03e5Sespie   char strict_low;
130*c87b03e5Sespie   char eliminable;
131*c87b03e5Sespie   char seen;
132*c87b03e5Sespie };
133*c87b03e5Sespie 
134*c87b03e5Sespie /* Begin with a null operand at index 0.  */
135*c87b03e5Sespie 
136*c87b03e5Sespie static struct operand_data null_operand =
137*c87b03e5Sespie {
138*c87b03e5Sespie   0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0
139*c87b03e5Sespie };
140*c87b03e5Sespie 
141*c87b03e5Sespie static struct operand_data *odata = &null_operand;
142*c87b03e5Sespie static struct operand_data **odata_end = &null_operand.next;
143*c87b03e5Sespie 
144*c87b03e5Sespie /* Must match the constants in recog.h.  */
145*c87b03e5Sespie 
146*c87b03e5Sespie #define INSN_OUTPUT_FORMAT_NONE         0       /* abort */
147*c87b03e5Sespie #define INSN_OUTPUT_FORMAT_SINGLE       1       /* const char * */
148*c87b03e5Sespie #define INSN_OUTPUT_FORMAT_MULTI        2       /* const char * const * */
149*c87b03e5Sespie #define INSN_OUTPUT_FORMAT_FUNCTION     3       /* const char * (*)(...) */
150*c87b03e5Sespie 
151*c87b03e5Sespie /* Record in this chain all information that we will output,
152*c87b03e5Sespie    associated with the code number of the insn.  */
153*c87b03e5Sespie 
154*c87b03e5Sespie struct data
155*c87b03e5Sespie {
156*c87b03e5Sespie   struct data *next;
157*c87b03e5Sespie   const char *name;
158*c87b03e5Sespie   const char *template;
159*c87b03e5Sespie   int code_number;
160*c87b03e5Sespie   int index_number;
161*c87b03e5Sespie   int lineno;
162*c87b03e5Sespie   int n_operands;		/* Number of operands this insn recognizes */
163*c87b03e5Sespie   int n_dups;			/* Number times match_dup appears in pattern */
164*c87b03e5Sespie   int n_alternatives;		/* Number of alternatives in each constraint */
165*c87b03e5Sespie   int operand_number;		/* Operand index in the big array.  */
166*c87b03e5Sespie   int output_format;		/* INSN_OUTPUT_FORMAT_*.  */
167*c87b03e5Sespie   struct operand_data operand[MAX_MAX_OPERANDS];
168*c87b03e5Sespie };
169*c87b03e5Sespie 
170*c87b03e5Sespie /* This variable points to the first link in the insn chain.  */
171*c87b03e5Sespie 
172*c87b03e5Sespie static struct data *idata, **idata_end = &idata;
173*c87b03e5Sespie 
174*c87b03e5Sespie static void output_prologue PARAMS ((void));
175*c87b03e5Sespie static void output_predicate_decls PARAMS ((void));
176*c87b03e5Sespie static void output_operand_data PARAMS ((void));
177*c87b03e5Sespie static void output_insn_data PARAMS ((void));
178*c87b03e5Sespie static void output_get_insn_name PARAMS ((void));
179*c87b03e5Sespie static void scan_operands PARAMS ((struct data *, rtx, int, int));
180*c87b03e5Sespie static int compare_operands PARAMS ((struct operand_data *,
181*c87b03e5Sespie 				   struct operand_data *));
182*c87b03e5Sespie static void place_operands PARAMS ((struct data *));
183*c87b03e5Sespie static void process_template PARAMS ((struct data *, const char *));
184*c87b03e5Sespie static void validate_insn_alternatives PARAMS ((struct data *));
185*c87b03e5Sespie static void validate_insn_operands PARAMS ((struct data *));
186*c87b03e5Sespie static void gen_insn PARAMS ((rtx, int));
187*c87b03e5Sespie static void gen_peephole PARAMS ((rtx, int));
188*c87b03e5Sespie static void gen_expand PARAMS ((rtx, int));
189*c87b03e5Sespie static void gen_split PARAMS ((rtx, int));
190*c87b03e5Sespie 
191*c87b03e5Sespie const char *
get_insn_name(index)192*c87b03e5Sespie get_insn_name (index)
193*c87b03e5Sespie      int index;
194*c87b03e5Sespie {
195*c87b03e5Sespie   static char buf[100];
196*c87b03e5Sespie 
197*c87b03e5Sespie   struct data *i, *last_named = NULL;
198*c87b03e5Sespie   for (i = idata; i ; i = i->next)
199*c87b03e5Sespie     {
200*c87b03e5Sespie       if (i->index_number == index)
201*c87b03e5Sespie 	return i->name;
202*c87b03e5Sespie       if (i->name)
203*c87b03e5Sespie 	last_named = i;
204*c87b03e5Sespie     }
205*c87b03e5Sespie 
206*c87b03e5Sespie   if (last_named)
207*c87b03e5Sespie     sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number);
208*c87b03e5Sespie   else
209*c87b03e5Sespie     sprintf(buf, "insn %d", index);
210*c87b03e5Sespie 
211*c87b03e5Sespie   return buf;
212*c87b03e5Sespie }
213*c87b03e5Sespie 
214*c87b03e5Sespie static void
output_prologue()215*c87b03e5Sespie output_prologue ()
216*c87b03e5Sespie {
217*c87b03e5Sespie   printf ("/* Generated automatically by the program `genoutput'\n\
218*c87b03e5Sespie    from the machine description file `md'.  */\n\n");
219*c87b03e5Sespie 
220*c87b03e5Sespie   printf ("#include \"config.h\"\n");
221*c87b03e5Sespie   printf ("#include \"system.h\"\n");
222*c87b03e5Sespie   printf ("#include \"flags.h\"\n");
223*c87b03e5Sespie   printf ("#include \"ggc.h\"\n");
224*c87b03e5Sespie   printf ("#include \"rtl.h\"\n");
225*c87b03e5Sespie   printf ("#include \"expr.h\"\n");
226*c87b03e5Sespie   printf ("#include \"insn-codes.h\"\n");
227*c87b03e5Sespie   printf ("#include \"tm_p.h\"\n");
228*c87b03e5Sespie   printf ("#include \"function.h\"\n");
229*c87b03e5Sespie   printf ("#include \"regs.h\"\n");
230*c87b03e5Sespie   printf ("#include \"hard-reg-set.h\"\n");
231*c87b03e5Sespie   printf ("#include \"real.h\"\n");
232*c87b03e5Sespie   printf ("#include \"insn-config.h\"\n\n");
233*c87b03e5Sespie   printf ("#include \"conditions.h\"\n");
234*c87b03e5Sespie   printf ("#include \"insn-attr.h\"\n\n");
235*c87b03e5Sespie   printf ("#include \"recog.h\"\n\n");
236*c87b03e5Sespie   printf ("#include \"toplev.h\"\n");
237*c87b03e5Sespie   printf ("#include \"output.h\"\n");
238*c87b03e5Sespie }
239*c87b03e5Sespie 
240*c87b03e5Sespie 
241*c87b03e5Sespie /* We need to define all predicates used.  Keep a list of those we
242*c87b03e5Sespie    have defined so far.  There normally aren't very many predicates
243*c87b03e5Sespie    used, so a linked list should be fast enough.  */
244*c87b03e5Sespie struct predicate { const char *name; struct predicate *next; };
245*c87b03e5Sespie 
246*c87b03e5Sespie static void
output_predicate_decls()247*c87b03e5Sespie output_predicate_decls ()
248*c87b03e5Sespie {
249*c87b03e5Sespie   struct predicate *predicates = 0;
250*c87b03e5Sespie   struct operand_data *d;
251*c87b03e5Sespie   struct predicate *p, *next;
252*c87b03e5Sespie 
253*c87b03e5Sespie   for (d = odata; d; d = d->next)
254*c87b03e5Sespie     if (d->predicate && d->predicate[0])
255*c87b03e5Sespie       {
256*c87b03e5Sespie 	for (p = predicates; p; p = p->next)
257*c87b03e5Sespie 	  if (strcmp (p->name, d->predicate) == 0)
258*c87b03e5Sespie 	    break;
259*c87b03e5Sespie 
260*c87b03e5Sespie 	if (p == 0)
261*c87b03e5Sespie 	  {
262*c87b03e5Sespie 	    printf ("extern int %s PARAMS ((rtx, enum machine_mode));\n",
263*c87b03e5Sespie 		    d->predicate);
264*c87b03e5Sespie 	    p = (struct predicate *) xmalloc (sizeof (struct predicate));
265*c87b03e5Sespie 	    p->name = d->predicate;
266*c87b03e5Sespie 	    p->next = predicates;
267*c87b03e5Sespie 	    predicates = p;
268*c87b03e5Sespie 	  }
269*c87b03e5Sespie       }
270*c87b03e5Sespie 
271*c87b03e5Sespie   printf ("\n\n");
272*c87b03e5Sespie   for (p = predicates; p; p = next)
273*c87b03e5Sespie     {
274*c87b03e5Sespie       next = p->next;
275*c87b03e5Sespie       free (p);
276*c87b03e5Sespie     }
277*c87b03e5Sespie }
278*c87b03e5Sespie 
279*c87b03e5Sespie static void
output_operand_data()280*c87b03e5Sespie output_operand_data ()
281*c87b03e5Sespie {
282*c87b03e5Sespie   struct operand_data *d;
283*c87b03e5Sespie 
284*c87b03e5Sespie   printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n");
285*c87b03e5Sespie 
286*c87b03e5Sespie   for (d = odata; d; d = d->next)
287*c87b03e5Sespie     {
288*c87b03e5Sespie       printf ("  {\n");
289*c87b03e5Sespie 
290*c87b03e5Sespie       printf ("    %s,\n",
291*c87b03e5Sespie 	      d->predicate && d->predicate[0] ? d->predicate : "0");
292*c87b03e5Sespie 
293*c87b03e5Sespie       printf ("    \"%s\",\n", d->constraint ? d->constraint : "");
294*c87b03e5Sespie 
295*c87b03e5Sespie       printf ("    %smode,\n", GET_MODE_NAME (d->mode));
296*c87b03e5Sespie 
297*c87b03e5Sespie       printf ("    %d,\n", d->strict_low);
298*c87b03e5Sespie 
299*c87b03e5Sespie       printf ("    %d\n", d->eliminable);
300*c87b03e5Sespie 
301*c87b03e5Sespie       printf("  },\n");
302*c87b03e5Sespie     }
303*c87b03e5Sespie   printf("};\n\n\n");
304*c87b03e5Sespie }
305*c87b03e5Sespie 
306*c87b03e5Sespie static void
output_insn_data()307*c87b03e5Sespie output_insn_data ()
308*c87b03e5Sespie {
309*c87b03e5Sespie   struct data *d;
310*c87b03e5Sespie   int name_offset = 0;
311*c87b03e5Sespie   int next_name_offset;
312*c87b03e5Sespie   const char * last_name = 0;
313*c87b03e5Sespie   const char * next_name = 0;
314*c87b03e5Sespie   struct data *n;
315*c87b03e5Sespie 
316*c87b03e5Sespie   for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++)
317*c87b03e5Sespie     if (n->name)
318*c87b03e5Sespie       {
319*c87b03e5Sespie 	next_name = n->name;
320*c87b03e5Sespie 	break;
321*c87b03e5Sespie       }
322*c87b03e5Sespie 
323*c87b03e5Sespie   printf ("\nconst struct insn_data insn_data[] = \n{\n");
324*c87b03e5Sespie 
325*c87b03e5Sespie   for (d = idata; d; d = d->next)
326*c87b03e5Sespie     {
327*c87b03e5Sespie       printf ("  {\n");
328*c87b03e5Sespie 
329*c87b03e5Sespie       if (d->name)
330*c87b03e5Sespie 	{
331*c87b03e5Sespie 	  printf ("    \"%s\",\n", d->name);
332*c87b03e5Sespie 	  name_offset = 0;
333*c87b03e5Sespie 	  last_name = d->name;
334*c87b03e5Sespie 	  next_name = 0;
335*c87b03e5Sespie 	  for (n = d->next, next_name_offset = 1; n;
336*c87b03e5Sespie 	       n = n->next, next_name_offset++)
337*c87b03e5Sespie 	    {
338*c87b03e5Sespie 	      if (n->name)
339*c87b03e5Sespie 		{
340*c87b03e5Sespie 		  next_name = n->name;
341*c87b03e5Sespie 		  break;
342*c87b03e5Sespie 		}
343*c87b03e5Sespie 	    }
344*c87b03e5Sespie 	}
345*c87b03e5Sespie       else
346*c87b03e5Sespie 	{
347*c87b03e5Sespie 	  name_offset++;
348*c87b03e5Sespie 	  if (next_name && (last_name == 0
349*c87b03e5Sespie 			    || name_offset > next_name_offset / 2))
350*c87b03e5Sespie 	    printf ("    \"%s-%d\",\n", next_name,
351*c87b03e5Sespie 		    next_name_offset - name_offset);
352*c87b03e5Sespie 	  else
353*c87b03e5Sespie 	    printf ("    \"%s+%d\",\n", last_name, name_offset);
354*c87b03e5Sespie 	}
355*c87b03e5Sespie 
356*c87b03e5Sespie       switch (d->output_format)
357*c87b03e5Sespie 	{
358*c87b03e5Sespie 	case INSN_OUTPUT_FORMAT_NONE:
359*c87b03e5Sespie 	  printf ("    0,\n");
360*c87b03e5Sespie 	  break;
361*c87b03e5Sespie 	case INSN_OUTPUT_FORMAT_SINGLE:
362*c87b03e5Sespie 	  {
363*c87b03e5Sespie 	    const char *p = d->template;
364*c87b03e5Sespie 	    char prev = 0;
365*c87b03e5Sespie 
366*c87b03e5Sespie 	    printf ("    \"");
367*c87b03e5Sespie 	    while (*p)
368*c87b03e5Sespie 	      {
369*c87b03e5Sespie 		if (IS_VSPACE (*p) && prev != '\\')
370*c87b03e5Sespie 		  {
371*c87b03e5Sespie 		    /* Preserve two consecutive \n's or \r's, but treat \r\n
372*c87b03e5Sespie 		       as a single newline.  */
373*c87b03e5Sespie 		    if (*p == '\n' && prev != '\r')
374*c87b03e5Sespie 		      printf ("\\n\\\n");
375*c87b03e5Sespie 		  }
376*c87b03e5Sespie 		else
377*c87b03e5Sespie 		  putchar (*p);
378*c87b03e5Sespie 		prev = *p;
379*c87b03e5Sespie 		++p;
380*c87b03e5Sespie 	      }
381*c87b03e5Sespie 	    printf ("\",\n");
382*c87b03e5Sespie 	  }
383*c87b03e5Sespie 	  break;
384*c87b03e5Sespie 	case INSN_OUTPUT_FORMAT_MULTI:
385*c87b03e5Sespie 	case INSN_OUTPUT_FORMAT_FUNCTION:
386*c87b03e5Sespie 	  printf ("    (const PTR) output_%d,\n", d->code_number);
387*c87b03e5Sespie 	  break;
388*c87b03e5Sespie 	default:
389*c87b03e5Sespie 	  abort ();
390*c87b03e5Sespie 	}
391*c87b03e5Sespie 
392*c87b03e5Sespie       if (d->name && d->name[0] != '*')
393*c87b03e5Sespie 	printf ("    (insn_gen_fn) gen_%s,\n", d->name);
394*c87b03e5Sespie       else
395*c87b03e5Sespie 	printf ("    0,\n");
396*c87b03e5Sespie 
397*c87b03e5Sespie       printf ("    &operand_data[%d],\n", d->operand_number);
398*c87b03e5Sespie       printf ("    %d,\n", d->n_operands);
399*c87b03e5Sespie       printf ("    %d,\n", d->n_dups);
400*c87b03e5Sespie       printf ("    %d,\n", d->n_alternatives);
401*c87b03e5Sespie       printf ("    %d\n", d->output_format);
402*c87b03e5Sespie 
403*c87b03e5Sespie       printf("  },\n");
404*c87b03e5Sespie     }
405*c87b03e5Sespie   printf ("};\n\n\n");
406*c87b03e5Sespie }
407*c87b03e5Sespie 
408*c87b03e5Sespie static void
output_get_insn_name()409*c87b03e5Sespie output_get_insn_name ()
410*c87b03e5Sespie {
411*c87b03e5Sespie   printf ("const char *\n");
412*c87b03e5Sespie   printf ("get_insn_name (code)\n");
413*c87b03e5Sespie   printf ("     int code;\n");
414*c87b03e5Sespie   printf ("{\n");
415*c87b03e5Sespie   printf ("  return insn_data[code].name;\n");
416*c87b03e5Sespie   printf ("}\n");
417*c87b03e5Sespie }
418*c87b03e5Sespie 
419*c87b03e5Sespie 
420*c87b03e5Sespie /* Stores in max_opno the largest operand number present in `part', if
421*c87b03e5Sespie    that is larger than the previous value of max_opno, and the rest of
422*c87b03e5Sespie    the operand data into `d->operand[i]'.
423*c87b03e5Sespie 
424*c87b03e5Sespie    THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
425*c87b03e5Sespie    THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART.  */
426*c87b03e5Sespie 
427*c87b03e5Sespie static int max_opno;
428*c87b03e5Sespie static int num_dups;
429*c87b03e5Sespie 
430*c87b03e5Sespie static void
scan_operands(d,part,this_address_p,this_strict_low)431*c87b03e5Sespie scan_operands (d, part, this_address_p, this_strict_low)
432*c87b03e5Sespie      struct data *d;
433*c87b03e5Sespie      rtx part;
434*c87b03e5Sespie      int this_address_p;
435*c87b03e5Sespie      int this_strict_low;
436*c87b03e5Sespie {
437*c87b03e5Sespie   int i, j;
438*c87b03e5Sespie   const char *format_ptr;
439*c87b03e5Sespie   int opno;
440*c87b03e5Sespie 
441*c87b03e5Sespie   if (part == 0)
442*c87b03e5Sespie     return;
443*c87b03e5Sespie 
444*c87b03e5Sespie   switch (GET_CODE (part))
445*c87b03e5Sespie     {
446*c87b03e5Sespie     case MATCH_OPERAND:
447*c87b03e5Sespie       opno = XINT (part, 0);
448*c87b03e5Sespie       if (opno > max_opno)
449*c87b03e5Sespie 	max_opno = opno;
450*c87b03e5Sespie       if (max_opno >= MAX_MAX_OPERANDS)
451*c87b03e5Sespie 	{
452*c87b03e5Sespie 	  message_with_line (d->lineno,
453*c87b03e5Sespie 			     "maximum number of operands exceeded");
454*c87b03e5Sespie 	  have_error = 1;
455*c87b03e5Sespie 	  return;
456*c87b03e5Sespie 	}
457*c87b03e5Sespie       if (d->operand[opno].seen)
458*c87b03e5Sespie 	{
459*c87b03e5Sespie 	  message_with_line (d->lineno,
460*c87b03e5Sespie 			     "repeated operand number %d\n", opno);
461*c87b03e5Sespie 	  have_error = 1;
462*c87b03e5Sespie 	}
463*c87b03e5Sespie 
464*c87b03e5Sespie       d->operand[opno].seen = 1;
465*c87b03e5Sespie       d->operand[opno].mode = GET_MODE (part);
466*c87b03e5Sespie       d->operand[opno].strict_low = this_strict_low;
467*c87b03e5Sespie       d->operand[opno].predicate = XSTR (part, 1);
468*c87b03e5Sespie       d->operand[opno].constraint = strip_whitespace (XSTR (part, 2));
469*c87b03e5Sespie       d->operand[opno].n_alternatives
470*c87b03e5Sespie 	= n_occurrences (',', d->operand[opno].constraint) + 1;
471*c87b03e5Sespie       d->operand[opno].address_p = this_address_p;
472*c87b03e5Sespie       d->operand[opno].eliminable = 1;
473*c87b03e5Sespie       return;
474*c87b03e5Sespie 
475*c87b03e5Sespie     case MATCH_SCRATCH:
476*c87b03e5Sespie       opno = XINT (part, 0);
477*c87b03e5Sespie       if (opno > max_opno)
478*c87b03e5Sespie 	max_opno = opno;
479*c87b03e5Sespie       if (max_opno >= MAX_MAX_OPERANDS)
480*c87b03e5Sespie 	{
481*c87b03e5Sespie 	  message_with_line (d->lineno,
482*c87b03e5Sespie 			     "maximum number of operands exceeded");
483*c87b03e5Sespie 	  have_error = 1;
484*c87b03e5Sespie 	  return;
485*c87b03e5Sespie 	}
486*c87b03e5Sespie       if (d->operand[opno].seen)
487*c87b03e5Sespie 	{
488*c87b03e5Sespie 	  message_with_line (d->lineno,
489*c87b03e5Sespie 			     "repeated operand number %d\n", opno);
490*c87b03e5Sespie 	  have_error = 1;
491*c87b03e5Sespie 	}
492*c87b03e5Sespie 
493*c87b03e5Sespie       d->operand[opno].seen = 1;
494*c87b03e5Sespie       d->operand[opno].mode = GET_MODE (part);
495*c87b03e5Sespie       d->operand[opno].strict_low = 0;
496*c87b03e5Sespie       d->operand[opno].predicate = "scratch_operand";
497*c87b03e5Sespie       d->operand[opno].constraint = strip_whitespace (XSTR (part, 1));
498*c87b03e5Sespie       d->operand[opno].n_alternatives
499*c87b03e5Sespie 	= n_occurrences (',', d->operand[opno].constraint) + 1;
500*c87b03e5Sespie       d->operand[opno].address_p = 0;
501*c87b03e5Sespie       d->operand[opno].eliminable = 0;
502*c87b03e5Sespie       return;
503*c87b03e5Sespie 
504*c87b03e5Sespie     case MATCH_OPERATOR:
505*c87b03e5Sespie     case MATCH_PARALLEL:
506*c87b03e5Sespie       opno = XINT (part, 0);
507*c87b03e5Sespie       if (opno > max_opno)
508*c87b03e5Sespie 	max_opno = opno;
509*c87b03e5Sespie       if (max_opno >= MAX_MAX_OPERANDS)
510*c87b03e5Sespie 	{
511*c87b03e5Sespie 	  message_with_line (d->lineno,
512*c87b03e5Sespie 			     "maximum number of operands exceeded");
513*c87b03e5Sespie 	  have_error = 1;
514*c87b03e5Sespie 	  return;
515*c87b03e5Sespie 	}
516*c87b03e5Sespie       if (d->operand[opno].seen)
517*c87b03e5Sespie 	{
518*c87b03e5Sespie 	  message_with_line (d->lineno,
519*c87b03e5Sespie 			     "repeated operand number %d\n", opno);
520*c87b03e5Sespie 	  have_error = 1;
521*c87b03e5Sespie 	}
522*c87b03e5Sespie 
523*c87b03e5Sespie       d->operand[opno].seen = 1;
524*c87b03e5Sespie       d->operand[opno].mode = GET_MODE (part);
525*c87b03e5Sespie       d->operand[opno].strict_low = 0;
526*c87b03e5Sespie       d->operand[opno].predicate = XSTR (part, 1);
527*c87b03e5Sespie       d->operand[opno].constraint = 0;
528*c87b03e5Sespie       d->operand[opno].address_p = 0;
529*c87b03e5Sespie       d->operand[opno].eliminable = 0;
530*c87b03e5Sespie       for (i = 0; i < XVECLEN (part, 2); i++)
531*c87b03e5Sespie 	scan_operands (d, XVECEXP (part, 2, i), 0, 0);
532*c87b03e5Sespie       return;
533*c87b03e5Sespie 
534*c87b03e5Sespie     case MATCH_DUP:
535*c87b03e5Sespie     case MATCH_OP_DUP:
536*c87b03e5Sespie     case MATCH_PAR_DUP:
537*c87b03e5Sespie       ++num_dups;
538*c87b03e5Sespie       break;
539*c87b03e5Sespie 
540*c87b03e5Sespie     case ADDRESS:
541*c87b03e5Sespie       scan_operands (d, XEXP (part, 0), 1, 0);
542*c87b03e5Sespie       return;
543*c87b03e5Sespie 
544*c87b03e5Sespie     case STRICT_LOW_PART:
545*c87b03e5Sespie       scan_operands (d, XEXP (part, 0), 0, 1);
546*c87b03e5Sespie       return;
547*c87b03e5Sespie 
548*c87b03e5Sespie     default:
549*c87b03e5Sespie       break;
550*c87b03e5Sespie     }
551*c87b03e5Sespie 
552*c87b03e5Sespie   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
553*c87b03e5Sespie 
554*c87b03e5Sespie   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
555*c87b03e5Sespie     switch (*format_ptr++)
556*c87b03e5Sespie       {
557*c87b03e5Sespie       case 'e':
558*c87b03e5Sespie       case 'u':
559*c87b03e5Sespie 	scan_operands (d, XEXP (part, i), 0, 0);
560*c87b03e5Sespie 	break;
561*c87b03e5Sespie       case 'E':
562*c87b03e5Sespie 	if (XVEC (part, i) != NULL)
563*c87b03e5Sespie 	  for (j = 0; j < XVECLEN (part, i); j++)
564*c87b03e5Sespie 	    scan_operands (d, XVECEXP (part, i, j), 0, 0);
565*c87b03e5Sespie 	break;
566*c87b03e5Sespie       }
567*c87b03e5Sespie }
568*c87b03e5Sespie 
569*c87b03e5Sespie /* Compare two operands for content equality.  */
570*c87b03e5Sespie 
571*c87b03e5Sespie static int
compare_operands(d0,d1)572*c87b03e5Sespie compare_operands (d0, d1)
573*c87b03e5Sespie      struct operand_data *d0, *d1;
574*c87b03e5Sespie {
575*c87b03e5Sespie   const char *p0, *p1;
576*c87b03e5Sespie 
577*c87b03e5Sespie   p0 = d0->predicate;
578*c87b03e5Sespie   if (!p0)
579*c87b03e5Sespie     p0 = "";
580*c87b03e5Sespie   p1 = d1->predicate;
581*c87b03e5Sespie   if (!p1)
582*c87b03e5Sespie     p1 = "";
583*c87b03e5Sespie   if (strcmp (p0, p1) != 0)
584*c87b03e5Sespie     return 0;
585*c87b03e5Sespie 
586*c87b03e5Sespie   p0 = d0->constraint;
587*c87b03e5Sespie   if (!p0)
588*c87b03e5Sespie     p0 = "";
589*c87b03e5Sespie   p1 = d1->constraint;
590*c87b03e5Sespie   if (!p1)
591*c87b03e5Sespie     p1 = "";
592*c87b03e5Sespie   if (strcmp (p0, p1) != 0)
593*c87b03e5Sespie     return 0;
594*c87b03e5Sespie 
595*c87b03e5Sespie   if (d0->mode != d1->mode)
596*c87b03e5Sespie     return 0;
597*c87b03e5Sespie 
598*c87b03e5Sespie   if (d0->strict_low != d1->strict_low)
599*c87b03e5Sespie     return 0;
600*c87b03e5Sespie 
601*c87b03e5Sespie   if (d0->eliminable != d1->eliminable)
602*c87b03e5Sespie     return 0;
603*c87b03e5Sespie 
604*c87b03e5Sespie   return 1;
605*c87b03e5Sespie }
606*c87b03e5Sespie 
607*c87b03e5Sespie /* Scan the list of operands we've already committed to output and either
608*c87b03e5Sespie    find a subsequence that is the same, or allocate a new one at the end.  */
609*c87b03e5Sespie 
610*c87b03e5Sespie static void
place_operands(d)611*c87b03e5Sespie place_operands (d)
612*c87b03e5Sespie      struct data *d;
613*c87b03e5Sespie {
614*c87b03e5Sespie   struct operand_data *od, *od2;
615*c87b03e5Sespie   int i;
616*c87b03e5Sespie 
617*c87b03e5Sespie   if (d->n_operands == 0)
618*c87b03e5Sespie     {
619*c87b03e5Sespie       d->operand_number = 0;
620*c87b03e5Sespie       return;
621*c87b03e5Sespie     }
622*c87b03e5Sespie 
623*c87b03e5Sespie   /* Brute force substring search.  */
624*c87b03e5Sespie   for (od = odata, i = 0; od; od = od->next, i = 0)
625*c87b03e5Sespie     if (compare_operands (od, &d->operand[0]))
626*c87b03e5Sespie       {
627*c87b03e5Sespie 	od2 = od->next;
628*c87b03e5Sespie 	i = 1;
629*c87b03e5Sespie 	while (1)
630*c87b03e5Sespie 	  {
631*c87b03e5Sespie 	    if (i == d->n_operands)
632*c87b03e5Sespie 	      goto full_match;
633*c87b03e5Sespie 	    if (od2 == NULL)
634*c87b03e5Sespie 	      goto partial_match;
635*c87b03e5Sespie 	    if (! compare_operands (od2, &d->operand[i]))
636*c87b03e5Sespie 	      break;
637*c87b03e5Sespie 	    ++i, od2 = od2->next;
638*c87b03e5Sespie 	  }
639*c87b03e5Sespie       }
640*c87b03e5Sespie 
641*c87b03e5Sespie   /* Either partial match at the end of the list, or no match.  In either
642*c87b03e5Sespie      case, we tack on what operands are remaining to the end of the list.  */
643*c87b03e5Sespie  partial_match:
644*c87b03e5Sespie   d->operand_number = next_operand_number - i;
645*c87b03e5Sespie   for (; i < d->n_operands; ++i)
646*c87b03e5Sespie     {
647*c87b03e5Sespie       od2 = &d->operand[i];
648*c87b03e5Sespie       *odata_end = od2;
649*c87b03e5Sespie       odata_end = &od2->next;
650*c87b03e5Sespie       od2->index = next_operand_number++;
651*c87b03e5Sespie     }
652*c87b03e5Sespie   *odata_end = NULL;
653*c87b03e5Sespie   return;
654*c87b03e5Sespie 
655*c87b03e5Sespie  full_match:
656*c87b03e5Sespie   d->operand_number = od->index;
657*c87b03e5Sespie   return;
658*c87b03e5Sespie }
659*c87b03e5Sespie 
660*c87b03e5Sespie 
661*c87b03e5Sespie /* Process an assembler template from a define_insn or a define_peephole.
662*c87b03e5Sespie    It is either the assembler code template, a list of assembler code
663*c87b03e5Sespie    templates, or C code to generate the assembler code template.  */
664*c87b03e5Sespie 
665*c87b03e5Sespie static void
process_template(d,template)666*c87b03e5Sespie process_template (d, template)
667*c87b03e5Sespie     struct data *d;
668*c87b03e5Sespie     const char *template;
669*c87b03e5Sespie {
670*c87b03e5Sespie   const char *cp;
671*c87b03e5Sespie   int i;
672*c87b03e5Sespie 
673*c87b03e5Sespie   /* Templates starting with * contain straight code to be run.  */
674*c87b03e5Sespie   if (template[0] == '*')
675*c87b03e5Sespie     {
676*c87b03e5Sespie       d->template = 0;
677*c87b03e5Sespie       d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
678*c87b03e5Sespie 
679*c87b03e5Sespie       printf ("\nstatic const char *output_%d PARAMS ((rtx *, rtx));\n",
680*c87b03e5Sespie 	      d->code_number);
681*c87b03e5Sespie       puts ("\nstatic const char *");
682*c87b03e5Sespie       printf ("output_%d (operands, insn)\n", d->code_number);
683*c87b03e5Sespie       puts ("     rtx *operands ATTRIBUTE_UNUSED;");
684*c87b03e5Sespie       puts ("     rtx insn ATTRIBUTE_UNUSED;");
685*c87b03e5Sespie       puts ("{");
686*c87b03e5Sespie 
687*c87b03e5Sespie       puts (template + 1);
688*c87b03e5Sespie       puts ("}");
689*c87b03e5Sespie     }
690*c87b03e5Sespie 
691*c87b03e5Sespie   /* If the assembler code template starts with a @ it is a newline-separated
692*c87b03e5Sespie      list of assembler code templates, one for each alternative.  */
693*c87b03e5Sespie   else if (template[0] == '@')
694*c87b03e5Sespie     {
695*c87b03e5Sespie       d->template = 0;
696*c87b03e5Sespie       d->output_format = INSN_OUTPUT_FORMAT_MULTI;
697*c87b03e5Sespie 
698*c87b03e5Sespie       printf ("\nstatic const char * const output_%d[] = {\n", d->code_number);
699*c87b03e5Sespie 
700*c87b03e5Sespie       for (i = 0, cp = &template[1]; *cp; )
701*c87b03e5Sespie 	{
702*c87b03e5Sespie 	  while (ISSPACE (*cp))
703*c87b03e5Sespie 	    cp++;
704*c87b03e5Sespie 
705*c87b03e5Sespie 	  printf ("  \"");
706*c87b03e5Sespie 	  while (!IS_VSPACE (*cp) && *cp != '\0')
707*c87b03e5Sespie 	    {
708*c87b03e5Sespie 	      putchar (*cp);
709*c87b03e5Sespie 	      cp++;
710*c87b03e5Sespie 	    }
711*c87b03e5Sespie 
712*c87b03e5Sespie 	  printf ("\",\n");
713*c87b03e5Sespie 	  i++;
714*c87b03e5Sespie 	}
715*c87b03e5Sespie       if (i == 1)
716*c87b03e5Sespie 	message_with_line (d->lineno,
717*c87b03e5Sespie 			   "'@' is redundant for output template with single alternative");
718*c87b03e5Sespie       if (i != d->n_alternatives)
719*c87b03e5Sespie 	{
720*c87b03e5Sespie 	  message_with_line (d->lineno,
721*c87b03e5Sespie 			     "wrong number of alternatives in the output template");
722*c87b03e5Sespie 	  have_error = 1;
723*c87b03e5Sespie 	}
724*c87b03e5Sespie 
725*c87b03e5Sespie       printf ("};\n");
726*c87b03e5Sespie     }
727*c87b03e5Sespie   else
728*c87b03e5Sespie     {
729*c87b03e5Sespie       d->template = template;
730*c87b03e5Sespie       d->output_format = INSN_OUTPUT_FORMAT_SINGLE;
731*c87b03e5Sespie     }
732*c87b03e5Sespie }
733*c87b03e5Sespie 
734*c87b03e5Sespie /* Check insn D for consistency in number of constraint alternatives.  */
735*c87b03e5Sespie 
736*c87b03e5Sespie static void
validate_insn_alternatives(d)737*c87b03e5Sespie validate_insn_alternatives (d)
738*c87b03e5Sespie      struct data *d;
739*c87b03e5Sespie {
740*c87b03e5Sespie   int n = 0, start;
741*c87b03e5Sespie 
742*c87b03e5Sespie   /* Make sure all the operands have the same number of alternatives
743*c87b03e5Sespie      in their constraints.  Let N be that number.  */
744*c87b03e5Sespie   for (start = 0; start < d->n_operands; start++)
745*c87b03e5Sespie     if (d->operand[start].n_alternatives > 0)
746*c87b03e5Sespie       {
747*c87b03e5Sespie 	if (n == 0)
748*c87b03e5Sespie 	  n = d->operand[start].n_alternatives;
749*c87b03e5Sespie 	else if (n != d->operand[start].n_alternatives)
750*c87b03e5Sespie 	  {
751*c87b03e5Sespie 	    message_with_line (d->lineno,
752*c87b03e5Sespie 			       "wrong number of alternatives in operand %d",
753*c87b03e5Sespie 			       start);
754*c87b03e5Sespie 	    have_error = 1;
755*c87b03e5Sespie 	  }
756*c87b03e5Sespie       }
757*c87b03e5Sespie 
758*c87b03e5Sespie   /* Record the insn's overall number of alternatives.  */
759*c87b03e5Sespie   d->n_alternatives = n;
760*c87b03e5Sespie }
761*c87b03e5Sespie 
762*c87b03e5Sespie /* Verify that there are no gaps in operand numbers for INSNs.  */
763*c87b03e5Sespie 
764*c87b03e5Sespie static void
validate_insn_operands(d)765*c87b03e5Sespie validate_insn_operands (d)
766*c87b03e5Sespie      struct data *d;
767*c87b03e5Sespie {
768*c87b03e5Sespie   int i;
769*c87b03e5Sespie 
770*c87b03e5Sespie   for (i = 0; i < d->n_operands; ++i)
771*c87b03e5Sespie     if (d->operand[i].seen == 0)
772*c87b03e5Sespie       {
773*c87b03e5Sespie 	message_with_line (d->lineno, "missing operand %d", i);
774*c87b03e5Sespie 	have_error = 1;
775*c87b03e5Sespie       }
776*c87b03e5Sespie }
777*c87b03e5Sespie 
778*c87b03e5Sespie /* Look at a define_insn just read.  Assign its code number.  Record
779*c87b03e5Sespie    on idata the template and the number of arguments.  If the insn has
780*c87b03e5Sespie    a hairy output action, output a function for now.  */
781*c87b03e5Sespie 
782*c87b03e5Sespie static void
gen_insn(insn,lineno)783*c87b03e5Sespie gen_insn (insn, lineno)
784*c87b03e5Sespie      rtx insn;
785*c87b03e5Sespie      int lineno;
786*c87b03e5Sespie {
787*c87b03e5Sespie   struct data *d = (struct data *) xmalloc (sizeof (struct data));
788*c87b03e5Sespie   int i;
789*c87b03e5Sespie 
790*c87b03e5Sespie   d->code_number = next_code_number;
791*c87b03e5Sespie   d->index_number = next_index_number;
792*c87b03e5Sespie   d->lineno = lineno;
793*c87b03e5Sespie   if (XSTR (insn, 0)[0])
794*c87b03e5Sespie     d->name = XSTR (insn, 0);
795*c87b03e5Sespie   else
796*c87b03e5Sespie     d->name = 0;
797*c87b03e5Sespie 
798*c87b03e5Sespie   /* Build up the list in the same order as the insns are seen
799*c87b03e5Sespie      in the machine description.  */
800*c87b03e5Sespie   d->next = 0;
801*c87b03e5Sespie   *idata_end = d;
802*c87b03e5Sespie   idata_end = &d->next;
803*c87b03e5Sespie 
804*c87b03e5Sespie   max_opno = -1;
805*c87b03e5Sespie   num_dups = 0;
806*c87b03e5Sespie   memset (d->operand, 0, sizeof (d->operand));
807*c87b03e5Sespie 
808*c87b03e5Sespie   for (i = 0; i < XVECLEN (insn, 1); i++)
809*c87b03e5Sespie     scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
810*c87b03e5Sespie 
811*c87b03e5Sespie   d->n_operands = max_opno + 1;
812*c87b03e5Sespie   d->n_dups = num_dups;
813*c87b03e5Sespie 
814*c87b03e5Sespie   validate_insn_operands (d);
815*c87b03e5Sespie   validate_insn_alternatives (d);
816*c87b03e5Sespie   place_operands (d);
817*c87b03e5Sespie   process_template (d, XTMPL (insn, 3));
818*c87b03e5Sespie }
819*c87b03e5Sespie 
820*c87b03e5Sespie /* Look at a define_peephole just read.  Assign its code number.
821*c87b03e5Sespie    Record on idata the template and the number of arguments.
822*c87b03e5Sespie    If the insn has a hairy output action, output it now.  */
823*c87b03e5Sespie 
824*c87b03e5Sespie static void
gen_peephole(peep,lineno)825*c87b03e5Sespie gen_peephole (peep, lineno)
826*c87b03e5Sespie      rtx peep;
827*c87b03e5Sespie      int lineno;
828*c87b03e5Sespie {
829*c87b03e5Sespie   struct data *d = (struct data *) xmalloc (sizeof (struct data));
830*c87b03e5Sespie   int i;
831*c87b03e5Sespie 
832*c87b03e5Sespie   d->code_number = next_code_number;
833*c87b03e5Sespie   d->index_number = next_index_number;
834*c87b03e5Sespie   d->lineno = lineno;
835*c87b03e5Sespie   d->name = 0;
836*c87b03e5Sespie 
837*c87b03e5Sespie   /* Build up the list in the same order as the insns are seen
838*c87b03e5Sespie      in the machine description.  */
839*c87b03e5Sespie   d->next = 0;
840*c87b03e5Sespie   *idata_end = d;
841*c87b03e5Sespie   idata_end = &d->next;
842*c87b03e5Sespie 
843*c87b03e5Sespie   max_opno = -1;
844*c87b03e5Sespie   num_dups = 0;
845*c87b03e5Sespie   memset (d->operand, 0, sizeof (d->operand));
846*c87b03e5Sespie 
847*c87b03e5Sespie   /* Get the number of operands by scanning all the patterns of the
848*c87b03e5Sespie      peephole optimizer.  But ignore all the rest of the information
849*c87b03e5Sespie      thus obtained.  */
850*c87b03e5Sespie   for (i = 0; i < XVECLEN (peep, 0); i++)
851*c87b03e5Sespie     scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
852*c87b03e5Sespie 
853*c87b03e5Sespie   d->n_operands = max_opno + 1;
854*c87b03e5Sespie   d->n_dups = 0;
855*c87b03e5Sespie 
856*c87b03e5Sespie   validate_insn_alternatives (d);
857*c87b03e5Sespie   place_operands (d);
858*c87b03e5Sespie   process_template (d, XTMPL (peep, 2));
859*c87b03e5Sespie }
860*c87b03e5Sespie 
861*c87b03e5Sespie /* Process a define_expand just read.  Assign its code number,
862*c87b03e5Sespie    only for the purposes of `insn_gen_function'.  */
863*c87b03e5Sespie 
864*c87b03e5Sespie static void
gen_expand(insn,lineno)865*c87b03e5Sespie gen_expand (insn, lineno)
866*c87b03e5Sespie      rtx insn;
867*c87b03e5Sespie      int lineno;
868*c87b03e5Sespie {
869*c87b03e5Sespie   struct data *d = (struct data *) xmalloc (sizeof (struct data));
870*c87b03e5Sespie   int i;
871*c87b03e5Sespie 
872*c87b03e5Sespie   d->code_number = next_code_number;
873*c87b03e5Sespie   d->index_number = next_index_number;
874*c87b03e5Sespie   d->lineno = lineno;
875*c87b03e5Sespie   if (XSTR (insn, 0)[0])
876*c87b03e5Sespie     d->name = XSTR (insn, 0);
877*c87b03e5Sespie   else
878*c87b03e5Sespie     d->name = 0;
879*c87b03e5Sespie 
880*c87b03e5Sespie   /* Build up the list in the same order as the insns are seen
881*c87b03e5Sespie      in the machine description.  */
882*c87b03e5Sespie   d->next = 0;
883*c87b03e5Sespie   *idata_end = d;
884*c87b03e5Sespie   idata_end = &d->next;
885*c87b03e5Sespie 
886*c87b03e5Sespie   max_opno = -1;
887*c87b03e5Sespie   num_dups = 0;
888*c87b03e5Sespie   memset (d->operand, 0, sizeof (d->operand));
889*c87b03e5Sespie 
890*c87b03e5Sespie   /* Scan the operands to get the specified predicates and modes,
891*c87b03e5Sespie      since expand_binop needs to know them.  */
892*c87b03e5Sespie 
893*c87b03e5Sespie   if (XVEC (insn, 1))
894*c87b03e5Sespie     for (i = 0; i < XVECLEN (insn, 1); i++)
895*c87b03e5Sespie       scan_operands (d, XVECEXP (insn, 1, i), 0, 0);
896*c87b03e5Sespie 
897*c87b03e5Sespie   d->n_operands = max_opno + 1;
898*c87b03e5Sespie   d->n_dups = num_dups;
899*c87b03e5Sespie   d->template = 0;
900*c87b03e5Sespie   d->output_format = INSN_OUTPUT_FORMAT_NONE;
901*c87b03e5Sespie 
902*c87b03e5Sespie   validate_insn_alternatives (d);
903*c87b03e5Sespie   place_operands (d);
904*c87b03e5Sespie }
905*c87b03e5Sespie 
906*c87b03e5Sespie /* Process a define_split just read.  Assign its code number,
907*c87b03e5Sespie    only for reasons of consistency and to simplify genrecog.  */
908*c87b03e5Sespie 
909*c87b03e5Sespie static void
gen_split(split,lineno)910*c87b03e5Sespie gen_split (split, lineno)
911*c87b03e5Sespie      rtx split;
912*c87b03e5Sespie      int lineno;
913*c87b03e5Sespie {
914*c87b03e5Sespie   struct data *d = (struct data *) xmalloc (sizeof (struct data));
915*c87b03e5Sespie   int i;
916*c87b03e5Sespie 
917*c87b03e5Sespie   d->code_number = next_code_number;
918*c87b03e5Sespie   d->index_number = next_index_number;
919*c87b03e5Sespie   d->lineno = lineno;
920*c87b03e5Sespie   d->name = 0;
921*c87b03e5Sespie 
922*c87b03e5Sespie   /* Build up the list in the same order as the insns are seen
923*c87b03e5Sespie      in the machine description.  */
924*c87b03e5Sespie   d->next = 0;
925*c87b03e5Sespie   *idata_end = d;
926*c87b03e5Sespie   idata_end = &d->next;
927*c87b03e5Sespie 
928*c87b03e5Sespie   max_opno = -1;
929*c87b03e5Sespie   num_dups = 0;
930*c87b03e5Sespie   memset (d->operand, 0, sizeof (d->operand));
931*c87b03e5Sespie 
932*c87b03e5Sespie   /* Get the number of operands by scanning all the patterns of the
933*c87b03e5Sespie      split patterns.  But ignore all the rest of the information thus
934*c87b03e5Sespie      obtained.  */
935*c87b03e5Sespie   for (i = 0; i < XVECLEN (split, 0); i++)
936*c87b03e5Sespie     scan_operands (d, XVECEXP (split, 0, i), 0, 0);
937*c87b03e5Sespie 
938*c87b03e5Sespie   d->n_operands = max_opno + 1;
939*c87b03e5Sespie   d->n_dups = 0;
940*c87b03e5Sespie   d->n_alternatives = 0;
941*c87b03e5Sespie   d->template = 0;
942*c87b03e5Sespie   d->output_format = INSN_OUTPUT_FORMAT_NONE;
943*c87b03e5Sespie 
944*c87b03e5Sespie   place_operands (d);
945*c87b03e5Sespie }
946*c87b03e5Sespie 
947*c87b03e5Sespie extern int main PARAMS ((int, char **));
948*c87b03e5Sespie 
949*c87b03e5Sespie int
main(argc,argv)950*c87b03e5Sespie main (argc, argv)
951*c87b03e5Sespie      int argc;
952*c87b03e5Sespie      char **argv;
953*c87b03e5Sespie {
954*c87b03e5Sespie   rtx desc;
955*c87b03e5Sespie 
956*c87b03e5Sespie   progname = "genoutput";
957*c87b03e5Sespie 
958*c87b03e5Sespie   if (argc <= 1)
959*c87b03e5Sespie     fatal ("no input file name");
960*c87b03e5Sespie 
961*c87b03e5Sespie   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
962*c87b03e5Sespie     return (FATAL_EXIT_CODE);
963*c87b03e5Sespie 
964*c87b03e5Sespie   output_prologue ();
965*c87b03e5Sespie   next_code_number = 0;
966*c87b03e5Sespie   next_index_number = 0;
967*c87b03e5Sespie 
968*c87b03e5Sespie   /* Read the machine description.  */
969*c87b03e5Sespie 
970*c87b03e5Sespie   while (1)
971*c87b03e5Sespie     {
972*c87b03e5Sespie       int line_no;
973*c87b03e5Sespie 
974*c87b03e5Sespie       desc = read_md_rtx (&line_no, &next_code_number);
975*c87b03e5Sespie       if (desc == NULL)
976*c87b03e5Sespie 	break;
977*c87b03e5Sespie 
978*c87b03e5Sespie       if (GET_CODE (desc) == DEFINE_INSN)
979*c87b03e5Sespie 	gen_insn (desc, line_no);
980*c87b03e5Sespie       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
981*c87b03e5Sespie 	gen_peephole (desc, line_no);
982*c87b03e5Sespie       if (GET_CODE (desc) == DEFINE_EXPAND)
983*c87b03e5Sespie 	gen_expand (desc, line_no);
984*c87b03e5Sespie       if (GET_CODE (desc) == DEFINE_SPLIT
985*c87b03e5Sespie  	  || GET_CODE (desc) == DEFINE_PEEPHOLE2)
986*c87b03e5Sespie 	gen_split (desc, line_no);
987*c87b03e5Sespie       next_index_number++;
988*c87b03e5Sespie     }
989*c87b03e5Sespie 
990*c87b03e5Sespie   printf("\n\n");
991*c87b03e5Sespie   output_predicate_decls ();
992*c87b03e5Sespie   output_operand_data ();
993*c87b03e5Sespie   output_insn_data ();
994*c87b03e5Sespie   output_get_insn_name ();
995*c87b03e5Sespie 
996*c87b03e5Sespie   fflush (stdout);
997*c87b03e5Sespie   return (ferror (stdout) != 0 || have_error
998*c87b03e5Sespie 	? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
999*c87b03e5Sespie }
1000*c87b03e5Sespie 
1001*c87b03e5Sespie /* Return the number of occurrences of character C in string S or
1002*c87b03e5Sespie    -1 if S is the null string.  */
1003*c87b03e5Sespie 
1004*c87b03e5Sespie static int
n_occurrences(c,s)1005*c87b03e5Sespie n_occurrences (c, s)
1006*c87b03e5Sespie      int c;
1007*c87b03e5Sespie      const char *s;
1008*c87b03e5Sespie {
1009*c87b03e5Sespie   int n = 0;
1010*c87b03e5Sespie 
1011*c87b03e5Sespie   if (s == 0 || *s == '\0')
1012*c87b03e5Sespie     return -1;
1013*c87b03e5Sespie 
1014*c87b03e5Sespie   while (*s)
1015*c87b03e5Sespie     n += (*s++ == c);
1016*c87b03e5Sespie 
1017*c87b03e5Sespie   return n;
1018*c87b03e5Sespie }
1019*c87b03e5Sespie 
1020*c87b03e5Sespie /* Remove whitespace in `s' by moving up characters until the end.
1021*c87b03e5Sespie    Return a new string.  */
1022*c87b03e5Sespie 
1023*c87b03e5Sespie static const char *
strip_whitespace(s)1024*c87b03e5Sespie strip_whitespace (s)
1025*c87b03e5Sespie      const char *s;
1026*c87b03e5Sespie {
1027*c87b03e5Sespie   char *p, *q;
1028*c87b03e5Sespie   char ch;
1029*c87b03e5Sespie 
1030*c87b03e5Sespie   if (s == 0)
1031*c87b03e5Sespie     return 0;
1032*c87b03e5Sespie 
1033*c87b03e5Sespie   p = q = xmalloc (strlen (s) + 1);
1034*c87b03e5Sespie   while ((ch = *s++) != '\0')
1035*c87b03e5Sespie     if (! ISSPACE (ch))
1036*c87b03e5Sespie       *p++ = ch;
1037*c87b03e5Sespie 
1038*c87b03e5Sespie   *p = '\0';
1039*c87b03e5Sespie   return q;
1040*c87b03e5Sespie }
1041