|
|
1.1 root 1: /* Generate code from machine description to emit insns as rtl.
2: Copyright (C) 1987,1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This program is used to produce insn-recog.c, which contains
23: a function called `recog' plus its subroutines.
24: These functions contain a decision tree
25: that recognizes whether an rtx, the argument given to recog,
26: is a valid instruction.
27:
28: recog returns -1 if the rtx is not valid.
29: If the rtx is valid, recog returns a nonnegative number
30: which is the insn code number for the pattern that matched.
31: This is the same as the order in the machine description of the
32: entry that matched. This number can be used as an index into
33: insn_templates and insn_n_operands (found in insn-output.c)
34: or as an argument to output_insn_hairy (also in insn-output.c). */
35:
36: #include <stdio.h>
37: #include "config.h"
38: #include "rtl.h"
39: #include "obstack.h"
40:
41: struct obstack obstack;
42: struct obstack *rtl_obstack = &obstack;
43:
44: #define obstack_chunk_alloc xmalloc
45: #define obstack_chunk_free free
46: extern int xmalloc ();
47: extern void free ();
48:
49: /* Data structure for decision tree for recognizing
50: legitimate instructions. */
51:
52: struct decision
53: {
54: int number;
55: char *position;
56: RTX_CODE code;
57: char *exact;
58: enum machine_mode mode;
59: char *tests;
60: int insn_code_number;
61: struct decision *next;
62: struct decision *success;
63: int opno;
64: int dupno;
65: int dupcount;
66: int test_elt_zero_int;
67: int elt_zero_int;
68: int test_elt_one_int;
69: int elt_one_int;
70: int ignmode;
71: struct decision *afterward;
72: int label_needed;
73: char *c_test;
74: char *reg_class;
75: char enforce_mode;
76: int veclen;
77: int subroutine_number;
78: };
79:
80: #define SUBROUTINE_THRESHOLD 50
81:
82: int next_subroutine_number;
83:
84: /*
85: recognize (top)
86: {
87: staten:
88: x = XVECEXP (top, 0, 3);
89: if (test_code (GET_CODE (x))
90: && test_mode (MODE (x))
91: && whatever_else)
92: goto statep;
93: else if (next one...)
94: goto statem:
95: goto stater;
96:
97: statep:
98: actions...;
99: return 1;
100:
101: statem:
102: x = stack[depth--];
103: more tests...;
104:
105: stateq:
106: stack[++depth] = x;
107: x = XEXP (stack[depth], 0);
108: more tests...;
109:
110: stater:
111: x = XEXP (stack[depth], 1);
112: }
113:
114: */
115:
116: int next_number;
117:
118: int next_insn_code;
119:
120: /* Number of MATCH_DUP's seen so far in this instruction. */
121: int dupcount;
122:
123: struct decision *add_to_sequence ();
124: struct decision *try_merge_2 ();
125: void write_subroutine ();
126: void print_code ();
127: void clear_codes ();
128: void clear_modes ();
129: void change_state ();
130: void write_tree ();
131: char *copystr ();
132: char *concat ();
133: void fatal ();
134: void mybzero ();
135:
136: struct decision *first;
137:
138: /* Construct and return a sequence of decisions
139: that will recognize INSN. */
140:
141: struct decision *
142: make_insn_sequence (insn)
143: rtx insn;
144: {
145: rtx x;
146: char *c_test = XSTR (insn, 2);
147: struct decision *last;
148:
149: dupcount = 0;
150:
151: if (XVECLEN (insn, 1) == 1)
152: x = XVECEXP (insn, 1, 0);
153: else
154: {
155: x = rtx_alloc (PARALLEL);
156: XVEC (x, 0) = XVEC (insn, 1);
157: PUT_MODE (x, VOIDmode);
158: }
159:
160: last = add_to_sequence (x, 0, "");
161:
162: if (c_test[0])
163: last->c_test = c_test;
164: last->insn_code_number = next_insn_code++;
165:
166: return first;
167: }
168:
169: struct decision *
170: add_to_sequence (pattern, last, position)
171: rtx pattern;
172: struct decision *last;
173: char *position;
174: {
175: register RTX_CODE code;
176: register struct decision *new
177: = (struct decision *) xmalloc (sizeof (struct decision));
178: struct decision *this;
179: char *newpos;
180: register char *fmt;
181: register int i;
182: int depth;
183: int len;
184:
185: new->number = next_number++;
186: new->position = copystr (position);
187: new->exact = 0;
188: new->next = 0;
189: new->success = 0;
190: new->insn_code_number = -1;
191: new->tests = 0;
192: new->opno = -1;
193: new->dupno = -1;
194: new->dupcount = -1;
195: new->test_elt_zero_int = 0;
196: new->test_elt_one_int = 0;
197: new->elt_zero_int = 0;
198: new->elt_one_int = 0;
199: new->enforce_mode = 0;
200: new->ignmode = 0;
201: new->afterward = 0;
202: new->label_needed = 0;
203: new->c_test = 0;
204: new->reg_class = 0;
205: new->veclen = 0;
206: new->subroutine_number = 0;
207:
208: this = new;
209:
210: if (last == 0)
211: first = new;
212: else
213: last->success = new;
214:
215: depth = strlen (position);
216: newpos = (char *) alloca (depth + 2);
217: strcpy (newpos, position);
218: newpos[depth + 1] = 0;
219:
220: restart:
221:
222: if (pattern == 0)
223: {
224: new->exact = "0";
225: new->code = UNKNOWN;
226: new->mode = VOIDmode;
227: return new;
228: }
229:
230: switch (GET_MODE (pattern))
231: {
232: case 0:
233: new->mode = VOIDmode;
234: break;
235:
236: default:
237: new->mode = GET_MODE (pattern);
238: break;
239: }
240:
241: new->code = code = GET_CODE (pattern);;
242:
243: switch (code)
244: {
245: case MATCH_OPERAND:
246: new->opno = XINT (pattern, 0);
247: new->code = UNKNOWN;
248: new->tests = XSTR (pattern, 1);
249: if (*new->tests == 0)
250: new->tests = 0;
251: new->reg_class = XSTR (pattern, 2);
252: if (*new->reg_class == 0)
253: new->reg_class = 0;
254: return new;
255:
256: case MATCH_DUP:
257: new->dupno = XINT (pattern, 0);
258: new->dupcount = dupcount++;
259: new->code = UNKNOWN;
260: return new;
261:
262: case ADDRESS:
263: pattern = XEXP (pattern, 0);
264: goto restart;
265:
266: case PC:
267: new->exact = "pc_rtx";
268: return new;
269:
270: case CC0:
271: new->exact = "cc0_rtx";
272: return new;
273:
274: case CONST_INT:
275: if (INTVAL (pattern) == 0)
276: {
277: new->exact = "const0_rtx";
278: return new;
279: }
280: if (INTVAL (pattern) == 1)
281: {
282: new->exact = "const1_rtx";
283: return new;
284: }
285: break;
286:
287: case SET:
288: newpos[depth] = '0';
289: new = add_to_sequence (SET_DEST (pattern), new, newpos);
290: this->success->enforce_mode = 1;
291: newpos[depth] = '1';
292: new = add_to_sequence (SET_SRC (pattern), new, newpos);
293: return new;
294:
295: case STRICT_LOW_PART:
296: newpos[depth] = '0';
297: new = add_to_sequence (XEXP (pattern, 0), new, newpos);
298: this->success->enforce_mode = 1;
299: return new;
300:
301: case SUBREG:
302: this->test_elt_one_int = 1;
303: this->elt_one_int = XINT (pattern, 1);
304: newpos[depth] = '0';
305: new = add_to_sequence (XEXP (pattern, 0), new, newpos);
306: this->success->enforce_mode = 1;
307: return new;
308:
309: case ZERO_EXTRACT:
310: case SIGN_EXTRACT:
311: newpos[depth] = '0';
312: new = add_to_sequence (XEXP (pattern, 0), new, newpos);
313: this->success->enforce_mode = 1;
314: newpos[depth] = '1';
315: new = add_to_sequence (XEXP (pattern, 1), new, newpos);
316: newpos[depth] = '2';
317: new = add_to_sequence (XEXP (pattern, 2), new, newpos);
318: return new;
319: }
320:
321: fmt = GET_RTX_FORMAT (code);
322: len = GET_RTX_LENGTH (code);
323: for (i = 0; i < len; i++)
324: {
325: newpos[depth] = '0' + i;
326: if (fmt[i] == 'e' || fmt[i] == 'u')
327: new = add_to_sequence (XEXP (pattern, i), new, newpos);
328: else if (fmt[i] == 'i' && i == 0)
329: {
330: this->test_elt_zero_int = 1;
331: this->elt_zero_int = XINT (pattern, i);
332: }
333: else if (fmt[i] == 'i' && i == 1)
334: {
335: this->test_elt_one_int = 1;
336: this->elt_one_int = XINT (pattern, i);
337: }
338: else if (fmt[i] == 'E')
339: {
340: register int j;
341: /* We do not handle a vector appearing as other than
342: the first item, just because nothing uses them
343: and by handling only the special case
344: we can use one element in newpos for either
345: the item number of a subexpression
346: or the element number in a vector. */
347: if (i != 0)
348: abort ();
349: this->veclen = XVECLEN (pattern, i);
350: for (j = 0; j < XVECLEN (pattern, i); j++)
351: {
352: newpos[depth] = 'a' + j;
353: new = add_to_sequence (XVECEXP (pattern, i, j),
354: new, newpos);
355: }
356: }
357: else if (fmt[i] != '0')
358: abort ();
359: }
360: return new;
361: }
362:
363: /* Merge two decision trees OLD and ADD,
364: modifying OLD destructively,
365: and return the merged tree. */
366:
367: struct decision *
368: merge_trees (old, add)
369: register struct decision *old, *add;
370: {
371: while (add)
372: {
373: register struct decision *next = add->next;
374: add->next = 0;
375: if (!try_merge_1 (old, add))
376: old = try_merge_2 (old, add);
377: add = next;
378: }
379: return old;
380: }
381:
382: /* Merge ADD into the next-chain starting with OLD
383: only if it overlaps a condition already tested in OLD.
384: Returns 1 if successful (OLD is modified),
385: 0 if nothing has been done. */
386:
387: int
388: try_merge_1 (old, add)
389: register struct decision *old, *add;
390: {
391: while (old)
392: {
393: if ((old->position == add->position
394: || (old->position && add->position
395: && !strcmp (old->position, add->position)))
396: && (old->tests == add->tests
397: || (old->tests && add->tests && !strcmp (old->tests, add->tests)))
398: && (old->c_test == add->c_test
399: || (old->c_test && add->c_test && !strcmp (old->c_test, add->c_test)))
400: && old->test_elt_zero_int == add->test_elt_zero_int
401: && old->elt_zero_int == add->elt_zero_int
402: && old->test_elt_one_int == add->test_elt_one_int
403: && old->elt_one_int == add->elt_one_int
404: && old->veclen == add->veclen
405: && old->dupno == add->dupno
406: && old->opno == add->opno
407: && (old->tests == 0
408: || (add->enforce_mode ? no_same_mode (old) : old->next == 0))
409: && old->code == add->code
410: && old->mode == add->mode)
411: {
412: old->success = merge_trees (old->success, add->success);
413: if (old->insn_code_number >= 0 && add->insn_code_number >= 0)
414: fatal ("Two actions at one point in tree.");
415: if (old->insn_code_number == -1)
416: old->insn_code_number = add->insn_code_number;
417: return 1;
418: }
419: old = old->next;
420: }
421: return 0;
422: }
423:
424: /* Merge ADD into the next-chain that starts with OLD,
425: preferably after something that tests the same place
426: that ADD does.
427: The next-chain of ADD itself is ignored, and it is set
428: up for entering ADD into the new chain.
429: Returns the new chain. */
430:
431: struct decision *
432: try_merge_2 (old, add)
433: struct decision *old, *add;
434: {
435: register struct decision *p;
436: struct decision *last = 0;
437: struct decision *last_same_place = 0;
438:
439: /* Put this in after the others that test the same place,
440: if there are any. If not, find the last chain element
441: and insert there.
442:
443: One modification: if this one is NOT a MATCH_OPERAND,
444: put it before any MATCH_OPERANDS that test the same place.
445:
446: Another: if enforce_mode (i.e. this is first operand of a SET),
447: put this after the last thing that tests the same place for
448: the same mode. */
449:
450: int operand = 0 != add->tests;
451:
452: for (p = old; p; p = p->next)
453: {
454: if (p->position == add->position
455: || (p->position && add->position
456: && !strcmp (p->position, add->position)))
457: {
458: last_same_place = p;
459: /* If enforce_mode, segregate the modes in numerical order. */
460: if (p->enforce_mode && (int) add->mode < (int) p->mode)
461: break;
462: /* Keep explicit decompositions before those that test predicates.
463: If enforce_mode, do this separately within each mode. */
464: if (! p->enforce_mode || p->mode == add->mode)
465: if (!operand && p->tests)
466: break;
467: }
468: /* If this is past the end of the decisions at the same place as ADD,
469: stop looking now; add ADD before here. */
470: else if (last_same_place)
471: break;
472: last = p;
473: }
474:
475: /* Insert before P, which means after LAST. */
476:
477: if (last)
478: {
479: add->next = last->next;
480: last->next = add;
481: return old;
482: }
483:
484: add->next = old;
485: return add;
486: }
487:
488: int
489: no_same_mode (node)
490: struct decision *node;
491: {
492: register struct decision *p;
493: register enum machine_mode mode = node->mode;
494:
495: for (p = node->next; p; p = p->next)
496: if (p->mode == mode)
497: return 0;
498:
499: return 1;
500: }
501:
502: /* Count the number of subnodes of node NODE, assumed to be the start
503: of a next-chain. If the number is high enough, make NODE start
504: a separate subroutine in the C code that is generated. */
505:
506: int
507: break_out_subroutines (node)
508: struct decision *node;
509: {
510: int size = 0;
511: struct decision *sub;
512: for (sub = node; sub; sub = sub->next)
513: size += 1 + break_out_subroutines (sub->success);
514: if (size > SUBROUTINE_THRESHOLD)
515: {
516: node->subroutine_number = ++next_subroutine_number;
517: write_subroutine (node);
518: size = 1;
519: }
520: return size;
521: }
522:
523: void
524: write_subroutine (tree)
525: struct decision *tree;
526: {
527: printf ("int\nrecog_%d (x0, insn)\n register rtx x0;\n rtx insn;\n{\n",
528: tree->subroutine_number);
529: printf (" register rtx x1, x2, x3, x4, x5;\n rtx x6, x7, x8, x9, x10, x11;\n");
530: printf (" int tem;\n");
531: write_tree (tree, "", 0, "", 1);
532: printf (" ret0: return -1;\n}\n\n");
533: }
534:
535: /* Write out C code to perform the decisions in the tree. */
536:
537: void
538: write_tree (tree, prevpos, afterward, afterpos, initial)
539: struct decision *tree;
540: char *prevpos;
541: int afterward;
542: char *afterpos;
543: int initial;
544: {
545: register struct decision *p, *p1;
546: char *pos;
547: register int depth;
548: int ignmode;
549: enum { NO_SWITCH, CODE_SWITCH, MODE_SWITCH } in_switch = NO_SWITCH;
550: char modemap[NUM_MACHINE_MODES];
551: char codemap[NUM_RTX_CODE];
552:
553: pos = prevpos;
554:
555: if (tree->subroutine_number > 0 && ! initial)
556: {
557: printf (" L%d:\n", tree->number);
558:
559: if (afterward)
560: {
561: printf (" tem = recog_%d (x0, insn);\n",
562: tree->subroutine_number);
563: printf (" if (tem >= 0) return tem;\n");
564: change_state (pos, afterpos);
565: printf (" goto L%d;\n", afterward);
566: }
567: else
568: printf (" return recog_%d (x0, insn);\n",
569: tree->subroutine_number);
570: return;
571: }
572:
573: tree->label_needed = 1;
574: for (p = tree; p; p = p->next)
575: {
576: /* Find the next alternative to p
577: that might be true when p is true.
578: Test that one next if p's successors fail.
579: Note that when the `tests' field is nonzero
580: it is up to the specified test-function to compare machine modes
581: and some (such as general_operand) don't always do so.
582: But when inside a switch-on-modes we ignore this and
583: consider all modes mutually exclusive. */
584: for (p1 = p->next; p1; p1 = p1->next)
585: if (((p->code == UNKNOWN || p1->code == UNKNOWN || p->code == p1->code)
586: && (p->mode == VOIDmode || p1->mode == VOIDmode
587: || p->mode == p1->mode
588: || (in_switch != MODE_SWITCH && (p->tests || p1->tests))))
589: || strcmp (p1->position, p->position))
590: break;
591: p->afterward = p1;
592: if (p1) p1->label_needed = 1;
593:
594: if (in_switch == MODE_SWITCH
595: && (p->mode == VOIDmode || (! p->enforce_mode && p->tests != 0)))
596: {
597: in_switch = NO_SWITCH;
598: printf (" }\n");
599: }
600: if (in_switch == CODE_SWITCH && p->code == UNKNOWN)
601: {
602: in_switch = NO_SWITCH;
603: printf (" }\n");
604: }
605:
606: if (p->label_needed)
607: printf (" L%d:\n", p->number);
608:
609: if (p->success == 0 && p->insn_code_number < 0)
610: abort ();
611:
612: change_state (pos, p->position);
613: pos = p->position;
614: depth = strlen (pos);
615:
616: ignmode = p->ignmode || pos[depth - 1] == '*' || p->tests;
617:
618: if (in_switch == NO_SWITCH)
619: {
620: /* If p and its alternatives all want the same mode,
621: reject all others at once, first, then ignore the mode. */
622: if (!ignmode && p->mode != VOIDmode && p->next && same_modes (p, p->mode))
623: {
624: printf (" if (GET_MODE (x%d) != %smode)\n",
625: depth, GET_MODE_NAME (p->mode));
626: if (afterward)
627: {
628: printf (" {\n ");
629: change_state (pos, afterpos);
630: printf (" goto L%d;\n }\n", afterward);
631: }
632: else
633: printf (" goto ret0;\n");
634: clear_modes (p);
635: ignmode = 1;
636: }
637:
638: /* If p and its alternatives all want the same code,
639: reject all others at once, first, then ignore the code. */
640: if (p->code != UNKNOWN && p->next && same_codes (p, p->code))
641: {
642: printf (" if (GET_CODE (x%d) != ", depth);
643: print_code (p->code);
644: printf (")\n");
645: if (afterward)
646: {
647: printf (" {");
648: change_state (pos, afterpos);
649: printf (" goto L%d; }\n", afterward);
650: }
651: else
652: printf (" goto ret0;\n");
653: clear_codes (p);
654: }
655: }
656:
657: /* If p and its alternatives all have different modes
658: and there are at least 4 of them, make a switch. */
659: if (in_switch == NO_SWITCH && pos[depth-1] != '*')
660: {
661: register int i;
662: int lose = 0;
663:
664: mybzero (modemap, sizeof modemap);
665: for (p1 = p, i = 0;
666: (p1 && p1->mode != VOIDmode
667: && (p1->tests == 0 || p1->enforce_mode));
668: p1 = p1->next, i++)
669: {
670: if (! p->enforce_mode && modemap[(int) p1->mode])
671: {
672: lose = 1;
673: break;
674: }
675: modemap[(int) p1->mode] = 1;
676: }
677: if (!lose && i >= 4)
678: {
679: in_switch = MODE_SWITCH;
680: printf (" switch (GET_MODE (x%d))\n {\n", depth);
681: }
682: }
683:
684: if (in_switch == NO_SWITCH)
685: {
686: register int i;
687: mybzero (codemap, sizeof codemap);
688: for (p1 = p, i = 0; p1 && p1->code != UNKNOWN; p1 = p1->next, i++)
689: {
690: if (codemap[(int) p1->code])
691: break;
692: codemap[(int) p1->code] = 1;
693: }
694: if ((p1 == 0 || p1->code == UNKNOWN) && i >= 4)
695: {
696: in_switch = CODE_SWITCH;
697: printf (" switch (GET_CODE (x%d))\n {\n", depth);
698: }
699: }
700:
701: if (in_switch == MODE_SWITCH)
702: {
703: if (modemap[(int) p->mode])
704: {
705: printf (" case %smode:\n", GET_MODE_NAME (p->mode));
706: modemap[(int) p->mode] = 0;
707: }
708: }
709: if (in_switch == CODE_SWITCH)
710: {
711: if (codemap[(int) p->code])
712: {
713: printf (" case ");
714: print_code (p->code);
715: printf (":\n");
716: codemap[(int) p->code] = 0;
717: }
718: }
719:
720: printf (" if (");
721: if (p->exact || (p->code != UNKNOWN && in_switch != CODE_SWITCH))
722: {
723: if (p->exact)
724: printf ("x%d == %s", depth, p->exact);
725: else
726: {
727: printf ("GET_CODE (x%d) == ", depth);
728: print_code (p->code);
729: }
730: printf (" && ");
731: }
732: if (p->mode && !ignmode && in_switch != MODE_SWITCH)
733: printf ("GET_MODE (x%d) == %smode && ",
734: depth, GET_MODE_NAME (p->mode));
735: if (p->test_elt_zero_int)
736: printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);
737: if (p->veclen)
738: printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen);
739: if (p->test_elt_one_int)
740: printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);
741: if (p->dupno >= 0)
742: printf ("rtx_equal_p (x%d, recog_operand[%d]) && ", depth, p->dupno);
743: if (p->tests)
744: printf ("%s (x%d, %smode)", p->tests, depth,
745: GET_MODE_NAME (p->mode));
746: else
747: printf ("1");
748:
749: if (p->opno >= 0)
750: printf (")\n { recog_operand[%d] = x%d; ",
751: p->opno, depth);
752: else
753: printf (")\n ");
754:
755: if (p->c_test)
756: printf ("if (%s) ", p->c_test);
757:
758: if (p->insn_code_number >= 0)
759: printf ("return %d;", p->insn_code_number);
760: else
761: printf ("goto L%d;", p->success->number);
762:
763: if (p->opno >= 0)
764: printf (" }\n");
765: else
766: printf ("\n");
767:
768: /* Now, if inside a switch, branch to next switch member
769: that might also need to be tested if this one fails. */
770:
771: if (in_switch == CODE_SWITCH)
772: {
773: /* Find the next alternative to p
774: that might be applicable if p was applicable. */
775: for (p1 = p->next; p1; p1 = p1->next)
776: if (p1->code == UNKNOWN || p->code == p1->code)
777: break;
778: if (p1 == 0 || p1->code == UNKNOWN)
779: printf (" break;\n");
780: else if (p1 != p->next)
781: {
782: printf (" goto L%d;\n", p1->number);
783: p1->label_needed = 1;
784: }
785: }
786:
787: if (in_switch == MODE_SWITCH)
788: {
789: /* Find the next alternative to p
790: that might be applicable if p was applicable. */
791: for (p1 = p->next; p1; p1 = p1->next)
792: if (p1->mode == VOIDmode || p->mode == p1->mode)
793: break;
794: if (p1 == 0 || p1->mode == VOIDmode)
795: printf (" break;\n");
796: else if (p1 != p->next)
797: {
798: printf (" goto L%d;\n", p1->number);
799: p1->label_needed = 1;
800: }
801: }
802: }
803:
804: if (in_switch != NO_SWITCH)
805: printf (" }\n");
806:
807: if (afterward)
808: {
809: change_state (pos, afterpos);
810: printf (" goto L%d;\n", afterward);
811: }
812: else
813: printf (" goto ret0;\n");
814:
815: for (p = tree; p; p = p->next)
816: if (p->success)
817: {
818: {
819: pos = p->position;
820: write_tree (p->success, pos,
821: p->afterward ? p->afterward->number : afterward,
822: p->afterward ? pos : afterpos,
823: 0);
824: }
825: }
826: }
827:
828: void
829: print_code (code)
830: RTX_CODE code;
831: {
832: register char *p1;
833: for (p1 = GET_RTX_NAME (code); *p1; p1++)
834: {
835: if (*p1 >= 'a' && *p1 <= 'z')
836: putchar (*p1 + 'A' - 'a');
837: else
838: putchar (*p1);
839: }
840: }
841:
842: int
843: same_codes (p, code)
844: register struct decision *p;
845: register RTX_CODE code;
846: {
847: for (; p; p = p->next)
848: if (p->code != code)
849: return 0;
850:
851: return 1;
852: }
853:
854: void
855: clear_codes (p)
856: register struct decision *p;
857: {
858: for (; p; p = p->next)
859: p->code = UNKNOWN;
860: }
861:
862: int
863: same_modes (p, mode)
864: register struct decision *p;
865: register enum machine_mode mode;
866: {
867: for (; p; p = p->next)
868: if (p->mode != mode || p->tests)
869: return 0;
870:
871: return 1;
872: }
873:
874: void
875: clear_modes (p)
876: register struct decision *p;
877: {
878: for (; p; p = p->next)
879: p->ignmode = 1;
880: }
881:
882: void
883: change_state (oldpos, newpos)
884: char *oldpos;
885: char *newpos;
886: {
887: int odepth = strlen (oldpos);
888: int depth = odepth;
889: int ndepth = strlen (newpos);
890:
891: /* Pop up as many levels as necessary. */
892:
893: while (strncmp (oldpos, newpos, depth))
894: --depth;
895:
896: /* Go down to desired level. */
897:
898: while (depth < ndepth)
899: {
900: if (newpos[depth] == '*')
901: printf (" x%d = recog_addr_dummy;\n XEXP (x%d, 0) = x%d;\n",
902: depth + 1, depth + 1, depth);
903: else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
904: printf (" x%d = XVECEXP (x%d, 0, %c);\n",
905: depth + 1, depth, '0' + newpos[depth] - 'a');
906: else
907: printf (" x%d = XEXP (x%d, %c);\n",
908: depth + 1, depth, newpos[depth]);
909: ++depth;
910: }
911: }
912:
913: char *
914: copystr (s1)
915: char *s1;
916: {
917: register char *tem;
918:
919: if (s1 == 0)
920: return 0;
921:
922: tem = (char *) xmalloc (strlen (s1) + 1);
923: strcpy (tem, s1);
924:
925: return tem;
926: }
927:
928: void
929: mybzero (b, length)
930: register char *b;
931: register int length;
932: {
933: while (length-- > 0)
934: *b++ = 0;
935: }
936:
937: char *
938: concat (s1, s2)
939: char *s1, *s2;
940: {
941: register char *tem;
942:
943: if (s1 == 0)
944: return s2;
945: if (s2 == 0)
946: return s1;
947:
948: tem = (char *) xmalloc (strlen (s1) + strlen (s2) + 2);
949: strcpy (tem, s1);
950: strcat (tem, " ");
951: strcat (tem, s2);
952:
953: return tem;
954: }
955:
956: int
957: xrealloc (ptr, size)
958: char *ptr;
959: int size;
960: {
961: int result = realloc (ptr, size);
962: if (!result)
963: fatal ("virtual memory exhausted");
964: return result;
965: }
966:
967: int
968: xmalloc (size)
969: {
970: register int val = malloc (size);
971:
972: if (val == 0)
973: fatal ("virtual memory exhausted");
974: return val;
975: }
976:
977: void
978: fatal (s, a1, a2)
979: {
980: fprintf (stderr, "genrecog: ");
981: fprintf (stderr, s, a1, a2);
982: fprintf (stderr, "\n");
983: fprintf (stderr, "after %d instruction definitions\n",
984: next_insn_code);
985: exit (FATAL_EXIT_CODE);
986: }
987:
988: int
989: main (argc, argv)
990: int argc;
991: char **argv;
992: {
993: rtx desc;
994: struct decision *tree = 0;
995: FILE *infile;
996: extern rtx read_rtx ();
997: register int c;
998:
999: obstack_init (rtl_obstack);
1000:
1001: if (argc <= 1)
1002: fatal ("No input file name.");
1003:
1004: infile = fopen (argv[1], "r");
1005: if (infile == 0)
1006: {
1007: perror (argv[1]);
1008: exit (FATAL_EXIT_CODE);
1009: }
1010:
1011: init_rtl ();
1012: next_insn_code = 0;
1013:
1014: printf ("/* Generated automatically by the program `genrecog'\n\
1015: from the machine description file `md'. */\n\n");
1016:
1017: /* Read the machine description. */
1018:
1019: while (1)
1020: {
1021: c = read_skip_spaces (infile);
1022: if (c == EOF)
1023: break;
1024: ungetc (c, infile);
1025:
1026: desc = read_rtx (infile);
1027: if (GET_CODE (desc) == DEFINE_INSN)
1028: tree = merge_trees (tree, make_insn_sequence (desc));
1029: if (GET_CODE (desc) == DEFINE_PEEPHOLE
1030: || GET_CODE (desc) == DEFINE_EXPAND)
1031: next_insn_code++;
1032: }
1033:
1034: printf ("#include \"config.h\"\n");
1035: printf ("#include \"rtl.h\"\n");
1036: printf ("#include \"insn-config.h\"\n");
1037: printf ("#include \"recog.h\"\n");
1038: printf ("\n\
1039: /* `recog' contains a decision tree\n\
1040: that recognizes whether the rtx X0 is a valid instruction.\n\
1041: \n\
1042: recog returns -1 if the rtx is not valid.\n\
1043: If the rtx is valid, recog returns a nonnegative number\n\
1044: which is the insn code number for the pattern that matched.\n");
1045: printf (" This is the same as the order in the machine description of\n\
1046: the entry that matched. This number can be used as an index into\n\
1047: insn_templates and insn_n_operands (found in insn-output.c)\n\
1048: or as an argument to output_insn_hairy (also in insn-output.c). */\n\n");
1049:
1050: printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n");
1051: printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n");
1052: printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n");
1053: printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n");
1054: printf ("extern rtx recog_addr_dummy;\n\n");
1055: printf ("#define operands recog_operand\n\n");
1056:
1057: break_out_subroutines (tree);
1058:
1059: printf ("int\nrecog (x0, insn)\n register rtx x0;\n rtx insn;\n{\n");
1060: printf (" register rtx x1, x2, x3, x4, x5;\n rtx x6, x7, x8, x9, x10, x11;\n");
1061: printf (" int tem;\n");
1062:
1063: write_tree (tree, "", 0, "", 1);
1064: printf (" ret0: return -1;\n}\n");
1065:
1066: fflush (stdout);
1067: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
1068: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.