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