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