|
|
1.1 root 1: /* Generate from machine description:
2:
3: - some #define configuration flags.
4: Copyright (C) 1987, 1991 Free Software Foundation, Inc.
5:
6: This file is part of GNU CC.
7:
8: GNU CC is free software; you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation; either version 2, or (at your option)
11: any later version.
12:
13: GNU CC is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with GNU CC; see the file COPYING. If not, write to
20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21:
22:
23: #include <stdio.h>
24: #include "hconfig.h"
25: #include "rtl.h"
26: #include "obstack.h"
27:
28: static struct obstack obstack;
29: struct obstack *rtl_obstack = &obstack;
30:
31: #define obstack_chunk_alloc xmalloc
32: #define obstack_chunk_free free
33:
34: extern void free ();
35: extern rtx read_rtx ();
36:
37: /* flags to determine output of machine description dependent #define's. */
38: static int max_recog_operands; /* Largest operand number seen. */
39: static int max_dup_operands; /* Largest number of match_dup in any insn. */
40: static int max_clobbers_per_insn;
41: static int register_constraint_flag;
42: static int have_cc0_flag;
43: static int have_cmove_flag;
44: static int have_lo_sum_flag;
45:
46: /* Maximum number of insns seen in a split. */
47: static int max_insns_per_split = 1;
48:
49: static int clobbers_seen_this_insn;
50: static int dup_operands_seen_this_insn;
51:
52: char *xmalloc ();
53: static void fatal ();
54: void fancy_abort ();
55:
56: /* RECOG_P will be non-zero if this pattern was seen in a context where it will
57: be used to recognize, rather than just generate an insn.
58:
59: NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
60: of a SET whose destination is not (pc). */
61:
62: static void
63: walk_insn_part (part, recog_p, non_pc_set_src)
64: rtx part;
65: int recog_p;
66: int non_pc_set_src;
67: {
68: register int i, j;
69: register RTX_CODE code;
70: register char *format_ptr;
71:
72: if (part == 0)
73: return;
74:
75: code = GET_CODE (part);
76: switch (code)
77: {
78: case CLOBBER:
79: clobbers_seen_this_insn++;
80: break;
81:
82: case MATCH_OPERAND:
83: if (XINT (part, 0) > max_recog_operands)
84: max_recog_operands = XINT (part, 0);
85: if (XSTR (part, 2) && *XSTR (part, 2))
86: register_constraint_flag = 1;
87: return;
88:
89: case MATCH_OP_DUP:
90: case MATCH_PAR_DUP:
91: ++dup_operands_seen_this_insn;
92: case MATCH_SCRATCH:
93: case MATCH_PARALLEL:
94: case MATCH_OPERATOR:
95: if (XINT (part, 0) > max_recog_operands)
96: max_recog_operands = XINT (part, 0);
97: /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
98: MATCH_PARALLEL. */
99: break;
100:
101: case LABEL_REF:
102: if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
103: break;
104: return;
105:
106: case MATCH_DUP:
107: ++dup_operands_seen_this_insn;
108: if (XINT (part, 0) > max_recog_operands)
109: max_recog_operands = XINT (part, 0);
110: return;
111:
112: case CC0:
113: if (recog_p)
114: have_cc0_flag = 1;
115: return;
116:
117: case LO_SUM:
118: if (recog_p)
119: have_lo_sum_flag = 1;
120: return;
121:
122: case SET:
123: walk_insn_part (SET_DEST (part), 0, recog_p);
124: walk_insn_part (SET_SRC (part), recog_p,
125: GET_CODE (SET_DEST (part)) != PC);
126: return;
127:
128: case IF_THEN_ELSE:
129: /* Only consider this machine as having a conditional move if the
130: two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise,
131: we have some specific IF_THEN_ELSE construct (like the doz
132: instruction on the RS/6000) that can't be used in the general
133: context we want it for. */
134:
135: if (recog_p && non_pc_set_src
136: && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
137: && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
138: have_cmove_flag = 1;
139: break;
140:
141: case REG: case CONST_INT: case SYMBOL_REF:
142: case PC:
143: return;
144: }
145:
146: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
147:
148: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
149: switch (*format_ptr++)
150: {
151: case 'e':
152: case 'u':
153: walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
154: break;
155: case 'E':
156: if (XVEC (part, i) != NULL)
157: for (j = 0; j < XVECLEN (part, i); j++)
158: walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
159: break;
160: }
161: }
162:
163: static void
164: gen_insn (insn)
165: rtx insn;
166: {
167: int i;
168:
169: /* Walk the insn pattern to gather the #define's status. */
170: clobbers_seen_this_insn = 0;
171: dup_operands_seen_this_insn = 0;
172: if (XVEC (insn, 1) != 0)
173: for (i = 0; i < XVECLEN (insn, 1); i++)
174: walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
175:
176: if (clobbers_seen_this_insn > max_clobbers_per_insn)
177: max_clobbers_per_insn = clobbers_seen_this_insn;
178: if (dup_operands_seen_this_insn > max_dup_operands)
179: max_dup_operands = dup_operands_seen_this_insn;
180: }
181:
182: /* Similar but scan a define_expand. */
183:
184: static void
185: gen_expand (insn)
186: rtx insn;
187: {
188: int i;
189:
190: /* Walk the insn pattern to gather the #define's status. */
191:
192: /* Note that we don't bother recording the number of MATCH_DUPs
193: that occur in a gen_expand, because only reload cares about that. */
194: if (XVEC (insn, 1) != 0)
195: for (i = 0; i < XVECLEN (insn, 1); i++)
196: {
197: /* Compute the maximum SETs and CLOBBERS
198: in any one of the sub-insns;
199: don't sum across all of them. */
200: clobbers_seen_this_insn = 0;
201:
202: walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
203:
204: if (clobbers_seen_this_insn > max_clobbers_per_insn)
205: max_clobbers_per_insn = clobbers_seen_this_insn;
206: }
207: }
208:
209: /* Similar but scan a define_split. */
210:
211: static void
212: gen_split (split)
213: rtx split;
214: {
215: int i;
216:
217: /* Look through the patterns that are matched
218: to compute the maximum operand number. */
219: for (i = 0; i < XVECLEN (split, 0); i++)
220: walk_insn_part (XVECEXP (split, 0, i), 1, 0);
221: /* Look at the number of insns this insn could split into. */
222: if (XVECLEN (split, 2) > max_insns_per_split)
223: max_insns_per_split = XVECLEN (split, 2);
224: }
225:
226: static void
227: gen_peephole (peep)
228: rtx peep;
229: {
230: int i;
231:
232: /* Look through the patterns that are matched
233: to compute the maximum operand number. */
234: for (i = 0; i < XVECLEN (peep, 0); i++)
235: walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
236: }
237:
238: char *
239: xmalloc (size)
240: unsigned size;
241: {
242: register char *val = (char *) malloc (size);
243:
244: if (val == 0)
245: fatal ("virtual memory exhausted");
246:
247: return val;
248: }
249:
250: char *
251: xrealloc (ptr, size)
252: char *ptr;
253: unsigned size;
254: {
255: char *result = (char *) realloc (ptr, size);
256: if (!result)
257: fatal ("virtual memory exhausted");
258: return result;
259: }
260:
261: static void
262: fatal (s, a1, a2)
263: char *s;
264: {
265: fprintf (stderr, "genconfig: ");
266: fprintf (stderr, s, a1, a2);
267: fprintf (stderr, "\n");
268: exit (FATAL_EXIT_CODE);
269: }
270:
271: /* More 'friendly' abort that prints the line and file.
272: config.h can #define abort fancy_abort if you like that sort of thing. */
273:
274: void
275: fancy_abort ()
276: {
277: fatal ("Internal gcc abort.");
278: }
279:
280: int
281: main (argc, argv)
282: int argc;
283: char **argv;
284: {
285: rtx desc;
286: FILE *infile;
287: register int c;
288:
289: obstack_init (rtl_obstack);
290:
291: if (argc <= 1)
292: fatal ("No input file name.");
293:
294: infile = fopen (argv[1], "r");
295: if (infile == 0)
296: {
297: perror (argv[1]);
298: exit (FATAL_EXIT_CODE);
299: }
300:
301: init_rtl ();
302:
303: printf ("/* Generated automatically by the program `genconfig'\n\
304: from the machine description file `md'. */\n\n");
305:
306: /* Allow at least 10 operands for the sake of asm constructs. */
307: max_recog_operands = 9; /* We will add 1 later. */
308: max_dup_operands = 1;
309:
310: /* Read the machine description. */
311:
312: while (1)
313: {
314: c = read_skip_spaces (infile);
315: if (c == EOF)
316: break;
317: ungetc (c, infile);
318:
319: desc = read_rtx (infile);
320: if (GET_CODE (desc) == DEFINE_INSN)
321: gen_insn (desc);
322: if (GET_CODE (desc) == DEFINE_EXPAND)
323: gen_expand (desc);
324: if (GET_CODE (desc) == DEFINE_SPLIT)
325: gen_split (desc);
326: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
327: gen_peephole (desc);
328: }
329:
330: printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
331:
332: printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
333:
334: /* This is conditionally defined, in case the user writes code which emits
335: more splits than we can readily see (and knows s/he does it). */
336: printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n",
337: max_insns_per_split);
338:
339: if (register_constraint_flag)
340: printf ("#define REGISTER_CONSTRAINTS\n");
341:
342: if (have_cc0_flag)
343: printf ("#define HAVE_cc0\n");
344:
345: if (have_cmove_flag)
346: printf ("#define HAVE_conditional_move\n");
347:
348: if (have_lo_sum_flag)
349: printf ("#define HAVE_lo_sum\n");
350:
351: fflush (stdout);
352: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
353: /* NOTREACHED */
354: return 0;
355: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.