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