source: trunk/src/gcc/gcc/genemit.c@ 1392

Last change on this file since 1392 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 24.2 KB
Line 
1/* Generate code from machine description to emit insns as rtl.
2 Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
21
22
23#include "hconfig.h"
24#include "system.h"
25#include "rtl.h"
26#include "errors.h"
27#include "gensupport.h"
28
29
30static int max_opno;
31static int max_dup_opno;
32static int max_scratch_opno;
33static int register_constraints;
34static int insn_code_number;
35static int insn_index_number;
36
37/* Data structure for recording the patterns of insns that have CLOBBERs.
38 We use this to output a function that adds these CLOBBERs to a
39 previously-allocated PARALLEL expression. */
40
41struct clobber_pat
42{
43 struct clobber_ent *insns;
44 rtx pattern;
45 int first_clobber;
46 struct clobber_pat *next;
47 int has_hard_reg;
48} *clobber_list;
49
50/* Records one insn that uses the clobber list. */
51
52struct clobber_ent
53{
54 int code_number; /* Counts only insns. */
55 struct clobber_ent *next;
56};
57
58static void max_operand_1 PARAMS ((rtx));
59static int max_operand_vec PARAMS ((rtx, int));
60static void print_code PARAMS ((RTX_CODE));
61static void gen_exp PARAMS ((rtx, enum rtx_code, char *));
62static void gen_insn PARAMS ((rtx, int));
63static void gen_expand PARAMS ((rtx));
64static void gen_split PARAMS ((rtx));
65static void output_add_clobbers PARAMS ((void));
66static void output_added_clobbers_hard_reg_p PARAMS ((void));
67static void gen_rtx_scratch PARAMS ((rtx, enum rtx_code));
68static void output_peephole2_scratches PARAMS ((rtx));
69
70
71
72static void
73max_operand_1 (x)
74 rtx x;
75{
76 RTX_CODE code;
77 int i;
78 int len;
79 const char *fmt;
80
81 if (x == 0)
82 return;
83
84 code = GET_CODE (x);
85
86 if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0')
87 register_constraints = 1;
88 if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0')
89 register_constraints = 1;
90 if (code == MATCH_OPERAND || code == MATCH_OPERATOR
91 || code == MATCH_PARALLEL)
92 max_opno = MAX (max_opno, XINT (x, 0));
93 if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)
94 max_dup_opno = MAX (max_dup_opno, XINT (x, 0));
95 if (code == MATCH_SCRATCH)
96 max_scratch_opno = MAX (max_scratch_opno, XINT (x, 0));
97
98 fmt = GET_RTX_FORMAT (code);
99 len = GET_RTX_LENGTH (code);
100 for (i = 0; i < len; i++)
101 {
102 if (fmt[i] == 'e' || fmt[i] == 'u')
103 max_operand_1 (XEXP (x, i));
104 else if (fmt[i] == 'E')
105 {
106 int j;
107 for (j = 0; j < XVECLEN (x, i); j++)
108 max_operand_1 (XVECEXP (x, i, j));
109 }
110 }
111}
112
113static int
114max_operand_vec (insn, arg)
115 rtx insn;
116 int arg;
117{
118 int len = XVECLEN (insn, arg);
119 int i;
120
121 max_opno = -1;
122 max_dup_opno = -1;
123 max_scratch_opno = -1;
124
125 for (i = 0; i < len; i++)
126 max_operand_1 (XVECEXP (insn, arg, i));
127
128 return max_opno + 1;
129}
130
131
132static void
133print_code (code)
134 RTX_CODE code;
135{
136 const char *p1;
137 for (p1 = GET_RTX_NAME (code); *p1; p1++)
138 putchar (TOUPPER(*p1));
139}
140
141static void
142gen_rtx_scratch (x, subroutine_type)
143 rtx x;
144 enum rtx_code subroutine_type;
145{
146 if (subroutine_type == DEFINE_PEEPHOLE2)
147 {
148 printf ("operand%d", XINT (x, 0));
149 }
150 else
151 {
152 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
153 }
154}
155
156/* Print a C expression to construct an RTX just like X,
157 substituting any operand references appearing within. */
158
159static void
160gen_exp (x, subroutine_type, used)
161 rtx x;
162 enum rtx_code subroutine_type;
163 char *used;
164{
165 RTX_CODE code;
166 int i;
167 int len;
168 const char *fmt;
169
170 if (x == 0)
171 {
172 printf ("NULL_RTX");
173 return;
174 }
175
176 code = GET_CODE (x);
177
178 switch (code)
179 {
180 case MATCH_OPERAND:
181 case MATCH_DUP:
182 if (used)
183 {
184 if (used[XINT (x, 0)])
185 {
186 printf ("copy_rtx (operand%d)", XINT (x, 0));
187 return;
188 }
189 used[XINT (x, 0)] = 1;
190 }
191 printf ("operand%d", XINT (x, 0));
192 return;
193
194 case MATCH_OP_DUP:
195 printf ("gen_rtx (GET_CODE (operand%d), ", XINT (x, 0));
196 if (GET_MODE (x) == VOIDmode)
197 printf ("GET_MODE (operand%d)", XINT (x, 0));
198 else
199 printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
200 for (i = 0; i < XVECLEN (x, 1); i++)
201 {
202 printf (",\n\t\t");
203 gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
204 }
205 printf (")");
206 return;
207
208 case MATCH_OPERATOR:
209 printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
210 printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
211 for (i = 0; i < XVECLEN (x, 2); i++)
212 {
213 printf (",\n\t\t");
214 gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
215 }
216 printf (")");
217 return;
218
219 case MATCH_PARALLEL:
220 case MATCH_PAR_DUP:
221 printf ("operand%d", XINT (x, 0));
222 return;
223
224 case MATCH_SCRATCH:
225 gen_rtx_scratch (x, subroutine_type);
226 return;
227
228 case ADDRESS:
229 fatal ("ADDRESS expression code used in named instruction pattern");
230
231 case PC:
232 printf ("pc_rtx");
233 return;
234
235 case CC0:
236 printf ("cc0_rtx");
237 return;
238
239 case CONST_INT:
240 if (INTVAL (x) == 0)
241 printf ("const0_rtx");
242 else if (INTVAL (x) == 1)
243 printf ("const1_rtx");
244 else if (INTVAL (x) == -1)
245 printf ("constm1_rtx");
246 else if (INTVAL (x) == STORE_FLAG_VALUE)
247 printf ("const_true_rtx");
248 else
249 {
250 printf ("GEN_INT (");
251 printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
252 printf (")");
253 }
254 return;
255
256 case CONST_DOUBLE:
257 /* These shouldn't be written in MD files. Instead, the appropriate
258 routines in varasm.c should be called. */
259 abort ();
260
261 default:
262 break;
263 }
264
265 printf ("gen_rtx_");
266 print_code (code);
267 printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
268
269 fmt = GET_RTX_FORMAT (code);
270 len = GET_RTX_LENGTH (code);
271 for (i = 0; i < len; i++)
272 {
273 if (fmt[i] == '0')
274 break;
275 printf (",\n\t");
276 if (fmt[i] == 'e' || fmt[i] == 'u')
277 gen_exp (XEXP (x, i), subroutine_type, used);
278 else if (fmt[i] == 'i')
279 printf ("%u", XINT (x, i));
280 else if (fmt[i] == 's')
281 printf ("\"%s\"", XSTR (x, i));
282 else if (fmt[i] == 'E')
283 {
284 int j;
285 printf ("gen_rtvec (%d", XVECLEN (x, i));
286 for (j = 0; j < XVECLEN (x, i); j++)
287 {
288 printf (",\n\t\t");
289 gen_exp (XVECEXP (x, i, j), subroutine_type, used);
290 }
291 printf (")");
292 }
293 else
294 abort ();
295 }
296 printf (")");
297}
298
299
300/* Generate the `gen_...' function for a DEFINE_INSN. */
301
302static void
303gen_insn (insn, lineno)
304 rtx insn;
305 int lineno;
306{
307 int operands;
308 int i;
309
310 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
311 registers or MATCH_SCRATCHes. If so, store away the information for
312 later. */
313
314 if (XVEC (insn, 1))
315 {
316 int has_hard_reg = 0;
317
318 for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
319 {
320 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
321 break;
322
323 if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) == REG)
324 has_hard_reg = 1;
325 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
326 break;
327 }
328
329 if (i != XVECLEN (insn, 1) - 1)
330 {
331 struct clobber_pat *p;
332 struct clobber_ent *link
333 = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
334 int j;
335
336 link->code_number = insn_code_number;
337
338 /* See if any previous CLOBBER_LIST entry is the same as this
339 one. */
340
341 for (p = clobber_list; p; p = p->next)
342 {
343 if (p->first_clobber != i + 1
344 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
345 continue;
346
347 for (j = i + 1; j < XVECLEN (insn, 1); j++)
348 {
349 rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
350 rtx new = XEXP (XVECEXP (insn, 1, j), 0);
351
352 /* OLD and NEW are the same if both are to be a SCRATCH
353 of the same mode,
354 or if both are registers of the same mode and number. */
355 if (! (GET_MODE (old) == GET_MODE (new)
356 && ((GET_CODE (old) == MATCH_SCRATCH
357 && GET_CODE (new) == MATCH_SCRATCH)
358 || (GET_CODE (old) == REG && GET_CODE (new) == REG
359 && REGNO (old) == REGNO (new)))))
360 break;
361 }
362
363 if (j == XVECLEN (insn, 1))
364 break;
365 }
366
367 if (p == 0)
368 {
369 p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
370
371 p->insns = 0;
372 p->pattern = insn;
373 p->first_clobber = i + 1;
374 p->next = clobber_list;
375 p->has_hard_reg = has_hard_reg;
376 clobber_list = p;
377 }
378
379 link->next = p->insns;
380 p->insns = link;
381 }
382 }
383
384 /* Don't mention instructions whose names are the null string
385 or begin with '*'. They are in the machine description just
386 to be recognized. */
387 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
388 return;
389
390 printf ("/* %s:%d */\n", read_rtx_filename, lineno);
391
392 /* Find out how many operands this function has,
393 and also whether any of them have register constraints. */
394 register_constraints = 0;
395 operands = max_operand_vec (insn, 1);
396 if (max_dup_opno >= operands)
397 fatal ("match_dup operand number has no match_operand");
398
399 /* Output the function name and argument declarations. */
400 printf ("rtx\ngen_%s (", XSTR (insn, 0));
401 for (i = 0; i < operands; i++)
402 if (i)
403 printf (", operand%d", i);
404 else
405 printf ("operand%d", i);
406 printf (")\n");
407 for (i = 0; i < operands; i++)
408 printf (" rtx operand%d;\n", i);
409 printf ("{\n");
410
411 /* Output code to construct and return the rtl for the instruction body */
412
413 if (XVECLEN (insn, 1) == 1)
414 {
415 printf (" return ");
416 gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
417 printf (";\n}\n\n");
418 }
419 else
420 {
421 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
422 XVECLEN (insn, 1));
423
424 for (i = 0; i < XVECLEN (insn, 1); i++)
425 {
426 printf (",\n\t\t");
427 gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, NULL);
428 }
429 printf ("));\n}\n\n");
430 }
431}
432
433
434/* Generate the `gen_...' function for a DEFINE_EXPAND. */
435
436static void
437gen_expand (expand)
438 rtx expand;
439{
440 int operands;
441 int i;
442
443 if (strlen (XSTR (expand, 0)) == 0)
444 fatal ("define_expand lacks a name");
445 if (XVEC (expand, 1) == 0)
446 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
447
448 /* Find out how many operands this function has,
449 and also whether any of them have register constraints. */
450 register_constraints = 0;
451
452 operands = max_operand_vec (expand, 1);
453
454 /* Output the function name and argument declarations. */
455 printf ("rtx\ngen_%s (", XSTR (expand, 0));
456 for (i = 0; i < operands; i++)
457 if (i)
458 printf (", operand%d", i);
459 else
460 printf ("operand%d", i);
461 printf (")\n");
462 for (i = 0; i < operands; i++)
463 printf (" rtx operand%d;\n", i);
464 printf ("{\n");
465
466 /* If we don't have any C code to write, only one insn is being written,
467 and no MATCH_DUPs are present, we can just return the desired insn
468 like we do for a DEFINE_INSN. This saves memory. */
469 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
470 && operands > max_dup_opno
471 && XVECLEN (expand, 1) == 1)
472 {
473 printf (" return ");
474 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
475 printf (";\n}\n\n");
476 return;
477 }
478
479 /* For each operand referred to only with MATCH_DUPs,
480 make a local variable. */
481 for (i = operands; i <= max_dup_opno; i++)
482 printf (" rtx operand%d;\n", i);
483 for (; i <= max_scratch_opno; i++)
484 printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
485 printf (" rtx _val = 0;\n");
486 printf (" start_sequence ();\n");
487
488 /* The fourth operand of DEFINE_EXPAND is some code to be executed
489 before the actual construction.
490 This code expects to refer to `operands'
491 just as the output-code in a DEFINE_INSN does,
492 but here `operands' is an automatic array.
493 So copy the operand values there before executing it. */
494 if (XSTR (expand, 3) && *XSTR (expand, 3))
495 {
496 printf (" {\n");
497 if (operands > 0 || max_dup_opno >= 0 || max_scratch_opno >= 0)
498 printf (" rtx operands[%d];\n",
499 MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1));
500 /* Output code to copy the arguments into `operands'. */
501 for (i = 0; i < operands; i++)
502 printf (" operands[%d] = operand%d;\n", i, i);
503
504 /* Output the special code to be executed before the sequence
505 is generated. */
506 printf ("%s\n", XSTR (expand, 3));
507
508 /* Output code to copy the arguments back out of `operands'
509 (unless we aren't going to use them at all). */
510 if (XVEC (expand, 1) != 0)
511 {
512 for (i = 0; i < operands; i++)
513 printf (" operand%d = operands[%d];\n", i, i);
514 for (; i <= max_dup_opno; i++)
515 printf (" operand%d = operands[%d];\n", i, i);
516 for (; i <= max_scratch_opno; i++)
517 printf (" operand%d = operands[%d];\n", i, i);
518 }
519 printf (" }\n");
520 }
521
522 /* Output code to construct the rtl for the instruction bodies.
523 Use emit_insn to add them to the sequence being accumulated.
524 But don't do this if the user's code has set `no_more' nonzero. */
525
526 for (i = 0; i < XVECLEN (expand, 1); i++)
527 {
528 rtx next = XVECEXP (expand, 1, i);
529 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
530 || (GET_CODE (next) == PARALLEL
531 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
532 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
533 || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
534 || GET_CODE (next) == RETURN)
535 printf (" emit_jump_insn (");
536 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
537 || GET_CODE (next) == CALL
538 || (GET_CODE (next) == PARALLEL
539 && GET_CODE (XVECEXP (next, 0, 0)) == SET
540 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
541 || (GET_CODE (next) == PARALLEL
542 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
543 printf (" emit_call_insn (");
544 else if (GET_CODE (next) == CODE_LABEL)
545 printf (" emit_label (");
546 else if (GET_CODE (next) == MATCH_OPERAND
547 || GET_CODE (next) == MATCH_DUP
548 || GET_CODE (next) == MATCH_OPERATOR
549 || GET_CODE (next) == MATCH_OP_DUP
550 || GET_CODE (next) == MATCH_PARALLEL
551 || GET_CODE (next) == MATCH_PAR_DUP
552 || GET_CODE (next) == PARALLEL)
553 printf (" emit (");
554 else
555 printf (" emit_insn (");
556 gen_exp (next, DEFINE_EXPAND, NULL);
557 printf (");\n");
558 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
559 && GET_CODE (SET_SRC (next)) == LABEL_REF)
560 printf (" emit_barrier ();");
561 }
562
563 /* Call `get_insns' to extract the list of all the
564 insns emitted within this gen_... function. */
565
566 printf (" _val = get_insns ();\n");
567 printf (" end_sequence ();\n");
568 printf (" return _val;\n}\n\n");
569}
570
571/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
572
573static void
574gen_split (split)
575 rtx split;
576{
577 int i;
578 int operands;
579 const char *const name =
580 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
581 const char *unused;
582 char *used;
583
584 if (XVEC (split, 0) == 0)
585 fatal ("define_%s (definition %d) lacks a pattern", name,
586 insn_index_number);
587 else if (XVEC (split, 2) == 0)
588 fatal ("define_%s (definition %d) lacks a replacement pattern", name,
589 insn_index_number);
590
591 /* Find out how many operands this function has. */
592
593 max_operand_vec (split, 2);
594 operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1;
595 unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : "");
596 used = xcalloc (1, operands);
597
598 /* Output the prototype, function name and argument declarations. */
599 if (GET_CODE (split) == DEFINE_PEEPHOLE2)
600 {
601 printf ("extern rtx gen_%s_%d PARAMS ((rtx, rtx *));\n",
602 name, insn_code_number);
603 printf ("rtx\ngen_%s_%d (curr_insn, operands)\n",
604 name, insn_code_number);
605 printf (" rtx curr_insn ATTRIBUTE_UNUSED;\n");
606 printf (" rtx *operands%s;\n", unused);
607 }
608 else
609 {
610 printf ("extern rtx gen_split_%d PARAMS ((rtx *));\n", insn_code_number);
611 printf ("rtx\ngen_%s_%d (operands)\n", name, insn_code_number);
612 printf (" rtx *operands%s;\n", unused);
613 }
614 printf ("{\n");
615
616 /* Declare all local variables. */
617 for (i = 0; i < operands; i++)
618 printf (" rtx operand%d;\n", i);
619 printf (" rtx _val = 0;\n");
620
621 if (GET_CODE (split) == DEFINE_PEEPHOLE2)
622 output_peephole2_scratches (split);
623
624 printf (" start_sequence ();\n");
625
626 /* The fourth operand of DEFINE_SPLIT is some code to be executed
627 before the actual construction. */
628
629 if (XSTR (split, 3))
630 printf ("%s\n", XSTR (split, 3));
631
632 /* Output code to copy the arguments back out of `operands' */
633 for (i = 0; i < operands; i++)
634 printf (" operand%d = operands[%d];\n", i, i);
635
636 /* Output code to construct the rtl for the instruction bodies.
637 Use emit_insn to add them to the sequence being accumulated.
638 But don't do this if the user's code has set `no_more' nonzero. */
639
640 for (i = 0; i < XVECLEN (split, 2); i++)
641 {
642 rtx next = XVECEXP (split, 2, i);
643 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
644 || (GET_CODE (next) == PARALLEL
645 && GET_CODE (XVECEXP (next, 0, 0)) == SET
646 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
647 || GET_CODE (next) == RETURN)
648 printf (" emit_jump_insn (");
649 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
650 || GET_CODE (next) == CALL
651 || (GET_CODE (next) == PARALLEL
652 && GET_CODE (XVECEXP (next, 0, 0)) == SET
653 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
654 || (GET_CODE (next) == PARALLEL
655 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
656 printf (" emit_call_insn (");
657 else if (GET_CODE (next) == CODE_LABEL)
658 printf (" emit_label (");
659 else if (GET_CODE (next) == MATCH_OPERAND
660 || GET_CODE (next) == MATCH_OPERATOR
661 || GET_CODE (next) == MATCH_PARALLEL
662 || GET_CODE (next) == MATCH_OP_DUP
663 || GET_CODE (next) == MATCH_DUP
664 || GET_CODE (next) == PARALLEL)
665 printf (" emit (");
666 else
667 printf (" emit_insn (");
668 gen_exp (next, GET_CODE (split), used);
669 printf (");\n");
670 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
671 && GET_CODE (SET_SRC (next)) == LABEL_REF)
672 printf (" emit_barrier ();");
673 }
674
675 /* Call `get_insns' to make a list of all the
676 insns emitted within this gen_... function. */
677
678 printf (" _val = get_insns ();\n");
679 printf (" end_sequence ();\n");
680 printf (" return _val;\n}\n\n");
681
682 free (used);
683}
684
685
686/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
687 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
688 the end of the vector. */
689
690static void
691output_add_clobbers ()
692{
693 struct clobber_pat *clobber;
694 struct clobber_ent *ent;
695 int i;
696
697 printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
698 printf (" rtx pattern ATTRIBUTE_UNUSED;\n int insn_code_number;\n");
699 printf ("{\n");
700 printf (" switch (insn_code_number)\n");
701 printf (" {\n");
702
703 for (clobber = clobber_list; clobber; clobber = clobber->next)
704 {
705 for (ent = clobber->insns; ent; ent = ent->next)
706 printf (" case %d:\n", ent->code_number);
707
708 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
709 {
710 printf (" XVECEXP (pattern, 0, %d) = ", i);
711 gen_exp (XVECEXP (clobber->pattern, 1, i),
712 GET_CODE (clobber->pattern), NULL);
713 printf (";\n");
714 }
715
716 printf (" break;\n\n");
717 }
718
719 printf (" default:\n");
720 printf (" abort ();\n");
721 printf (" }\n");
722 printf ("}\n");
723}
724
725
726/* Write a function, `added_clobbers_hard_reg_p' this is given an insn_code
727 number that needs clobbers and returns 1 if they include a clobber of a
728 hard reg and 0 if they just clobber SCRATCH. */
729
730static void
731output_added_clobbers_hard_reg_p ()
732{
733 struct clobber_pat *clobber;
734 struct clobber_ent *ent;
735 int clobber_p, used;
736
737 printf ("\n\nint\nadded_clobbers_hard_reg_p (insn_code_number)\n");
738 printf (" int insn_code_number;\n");
739 printf ("{\n");
740 printf (" switch (insn_code_number)\n");
741 printf (" {\n");
742
743 for (clobber_p = 0; clobber_p <= 1; clobber_p++)
744 {
745 used = 0;
746 for (clobber = clobber_list; clobber; clobber = clobber->next)
747 if (clobber->has_hard_reg == clobber_p)
748 for (ent = clobber->insns; ent; ent = ent->next)
749 {
750 printf (" case %d:\n", ent->code_number);
751 used++;
752 }
753
754 if (used)
755 printf (" return %d;\n\n", clobber_p);
756 }
757
758 printf (" default:\n");
759 printf (" abort ();\n");
760 printf (" }\n");
761 printf ("}\n");
762}
763
764
765/* Generate code to invoke find_free_register () as needed for the
766 scratch registers used by the peephole2 pattern in SPLIT. */
767
768static void
769output_peephole2_scratches (split)
770 rtx split;
771{
772 int i;
773 int insn_nr = 0;
774
775 printf (" HARD_REG_SET _regs_allocated;\n");
776 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
777
778 for (i = 0; i < XVECLEN (split, 0); i++)
779 {
780 rtx elt = XVECEXP (split, 0, i);
781 if (GET_CODE (elt) == MATCH_SCRATCH)
782 {
783 int last_insn_nr = insn_nr;
784 int cur_insn_nr = insn_nr;
785 int j;
786 for (j = i + 1; j < XVECLEN (split, 0); j++)
787 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
788 {
789 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
790 last_insn_nr = cur_insn_nr;
791 }
792 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
793 cur_insn_nr++;
794
795 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
796 return NULL;\n",
797 XINT (elt, 0),
798 insn_nr, last_insn_nr,
799 XSTR (elt, 1),
800 GET_MODE_NAME (GET_MODE (elt)));
801
802 }
803 else if (GET_CODE (elt) != MATCH_DUP)
804 insn_nr++;
805 }
806}
807
808extern int main PARAMS ((int, char **));
809
810int
811main (argc, argv)
812 int argc;
813 char **argv;
814{
815 rtx desc;
816
817 progname = "genemit";
818
819 if (argc <= 1)
820 fatal ("no input file name");
821
822 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
823 return (FATAL_EXIT_CODE);
824
825 /* Assign sequential codes to all entries in the machine description
826 in parallel with the tables in insn-output.c. */
827
828 insn_code_number = 0;
829 insn_index_number = 0;
830
831 printf ("/* Generated automatically by the program `genemit'\n\
832from the machine description file `md'. */\n\n");
833
834 printf ("#include \"config.h\"\n");
835 printf ("#include \"system.h\"\n");
836 printf ("#include \"rtl.h\"\n");
837 printf ("#include \"tm_p.h\"\n");
838 printf ("#include \"function.h\"\n");
839 printf ("#include \"expr.h\"\n");
840 printf ("#include \"optabs.h\"\n");
841 printf ("#include \"real.h\"\n");
842 printf ("#include \"flags.h\"\n");
843 printf ("#include \"output.h\"\n");
844 printf ("#include \"insn-config.h\"\n");
845 printf ("#include \"hard-reg-set.h\"\n");
846 printf ("#include \"recog.h\"\n");
847 printf ("#include \"resource.h\"\n");
848 printf ("#include \"reload.h\"\n");
849 printf ("#include \"toplev.h\"\n");
850 printf ("#include \"ggc.h\"\n\n");
851 printf ("#define FAIL return (end_sequence (), _val)\n");
852 printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
853
854 /* Read the machine description. */
855
856 while (1)
857 {
858 int line_no;
859
860 desc = read_md_rtx (&line_no, &insn_code_number);
861 if (desc == NULL)
862 break;
863
864 switch (GET_CODE (desc))
865 {
866 case DEFINE_INSN:
867 gen_insn (desc, line_no);
868 break;
869
870 case DEFINE_EXPAND:
871 printf ("/* %s:%d */\n", read_rtx_filename, line_no);
872 gen_expand (desc);
873 break;
874
875 case DEFINE_SPLIT:
876 printf ("/* %s:%d */\n", read_rtx_filename, line_no);
877 gen_split (desc);
878 break;
879
880 case DEFINE_PEEPHOLE2:
881 printf ("/* %s:%d */\n", read_rtx_filename, line_no);
882 gen_split (desc);
883 break;
884
885 default:
886 break;
887 }
888 ++insn_index_number;
889 }
890
891 /* Write out the routines to add CLOBBERs to a pattern and say whether they
892 clobber a hard reg. */
893 output_add_clobbers ();
894 output_added_clobbers_hard_reg_p ();
895
896 fflush (stdout);
897 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
898}
899
900/* Define this so we can link with print-rtl.o to get debug_rtx function. */
901const char *
902get_insn_name (code)
903 int code ATTRIBUTE_UNUSED;
904{
905 return NULL;
906}
Note: See TracBrowser for help on using the repository browser.