|
|
1.1 root 1: /* Generate code from to output assembler insns as recognized from rtl.
2: Copyright (C) 1987 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 reads the machine description for the compiler target machine
23: and produces a file containing three things:
24:
25: 1, An array of strings `insn_template' which is indexed by insn code number
26: and contains the template for output of that insn,
27:
28: 2. An array of ints `insn_n_operands' which is indexed by insn code number
29: and contains the number of distinct operands in the pattern for that insn,
30:
31: 3. An array of ints `insn_n_dups' which is indexed by insn code number
32: and contains the number of match_dup's that appear in the insn's pattern.
33: This says how many elements of `recog_dup_loc' are significant
34: after an insn has been recognized.
35:
36: 4. An array of arrays of machine modes, `insn_operand_machine_mode',
37: indexed first by insn code number and second by operand number,
38: containing the machine mode that that operand is supposed to have.
39:
40: 5. An array of arrays of operand constraint strings,
41: `insn_operand_constraint',
42: indexed first by insn code number and second by operand number,
43: containing the constraint for that operand.
44: This array is generated only if register constraints appear in
45: match_operand rtx's.
46:
47: 6. An array of arrays of chars which indicate which operands of
48: which insn patterns appear within ADDRESS rtx's. This array is
49: called `insn_operand_address_p' and is generated only if there
50: are *no* register constraints in the match_operand rtx's.
51:
52: 7. An array of functions `insn_gen_function' which, indexed
53: by insn code number, gives the function to generate a body
54: for that patter, given operands as arguments.
55:
56: 8. A function `output_insn_hairy' which is called with two arguments
57: (an insn code number and a vector of operand value rtx's)
58: and returns a template to use for output of that insn.
59: This is used only in the cases where the template is not constant.
60: These cases are specified by a * at the beginning of the template string
61: in the machine description. They are identified for the sake of
62: other parts of the compiler by a zero element in `insn_template'.
63:
64: The code number of an insn is simply its position in the machine description;
65: code numbers are assigned sequentially to entries in the description,
66: starting with code number 0.
67:
68: Thus, the following entry in the machine description
69:
70: (define_insn "clrdf"
71: [(set (match_operand:DF 0 "general_operand" "")
72: (const_int 0))]
73: ""
74: "clrd %0")
75:
76: assuming it is the 25th entry present, would cause
77: insn_template[24] to be "c;rd %0", and insn_n_operands[24] to be 1.
78: It would not make an case in output_insn_hairy because the template
79: given in the entry is a constant (it does not start with `*'). */
80:
81: #include <stdio.h>
82: #include "rtl.h"
83: #include <obstack.h>
84:
85: /* No instruction can have more operands than this.
86: Sorry for this arbitrary limit, but what machine will
87: have an instruction with this many operands? */
88:
89: #define MAX_MAX_OPERANDS 40
90:
91: struct obstack obstack;
92: struct obstack *current_obstack = &obstack;
93:
94: #define obstack_chunk_alloc xmalloc
95: #define obstack_chunk_free free
96: extern int xmalloc ();
97: extern void free ();
98:
99: void fatal ();
100:
101: /* insns in the machine description are assigned sequential code numbers
102: that are used by insn-recog.c (produced by genrecog) to communicate
103: to insn-output.c (produced by this program). */
104:
105: int next_code_number;
106:
107: /* Record in this chain all information that we will output,
108: associated with the code number of the insn. */
109:
110: struct data
111: {
112: int code_number;
113: char *name;
114: char *template; /* string such as "movl %1,%0" */
115: int n_operands; /* Number of operands this insn recognizes */
116: int n_dups; /* Number times match_dup appears in pattern */
117: struct data *next;
118: char *constraints[MAX_MAX_OPERANDS];
119: char address_p[MAX_MAX_OPERANDS];
120: enum machine_mode modes[MAX_MAX_OPERANDS];
121: };
122:
123: /* This variable points to the first link in the chain. */
124:
125: struct data *insn_data;
126:
127: /* Pointer to the last link in the chain, so new elements
128: can be added at the end. */
129:
130: struct data *end_of_insn_data;
131:
132: /* Nonzero if any match_operand has a constraint string;
133: implies that REGISTER_CONSTRAINTS will be defined
134: for this machine description. */
135:
136: int have_constraints;
137:
138: void
139: output_prologue ()
140: {
141:
142: printf ("/* Generated automatically by the program `genoutput'\n\
143: from the machine description file `md'. */\n\n");
144:
145: printf ("#include \"config.h\"\n");
146: printf ("#include \"rtl.h\"\n");
147: printf ("#include \"regs.h\"\n");
148: printf ("#include \"conditions.h\"\n");
149: printf ("#include \"insn-flags.h\"\n");
150: printf ("#include \"insn-config.h\"\n\n");
151:
152: printf ("extern rtx adj_offsetable_operand();\n\
153: extern void output_asm_insn();\n\n");
154:
155: printf ("#include \"aux-output.c\"\n\n");
156:
157: printf ("char *\noutput_insn_hairy (code_number, operands, insn)\n");
158: printf (" int code_number;\n");
159: printf (" rtx *operands;\n");
160: printf (" rtx insn;\n{\n switch (code_number)\n {\n");
161: }
162:
163: void
164: output_epilogue ()
165: {
166: register struct data *d;
167:
168: printf (" default: abort ();\n");
169: printf (" }\n}\n");
170:
171: printf ("\nchar *insn_template[] =\n {\n");
172: for (d = insn_data; d; d = d->next)
173: {
174: if (d->template)
175: printf (" \"%s\",\n", d->template);
176: else
177: printf (" 0,\n");
178: }
179: printf (" };\n");
180:
181: printf ("\nrtx (*insn_gen_function[]) () =\n {\n");
182: for (d = insn_data; d; d = d->next)
183: {
184: if (d->name)
185: printf (" gen_%s,\n", d->name);
186: else
187: printf (" 0,\n");
188: }
189: printf (" };\n");
190:
191: printf ("\nint insn_n_operands[] =\n {\n");
192: for (d = insn_data; d; d = d->next)
193: {
194: printf (" %d,\n", d->n_operands);
195: }
196: printf (" };\n");
197:
198: printf ("\nint insn_n_dups[] =\n {\n");
199: for (d = insn_data; d; d = d->next)
200: {
201: printf (" %d,\n", d->n_dups);
202: }
203: printf (" };\n");
204:
205: if (have_constraints)
206: {
207: printf ("\nchar *insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
208: for (d = insn_data; d; d = d->next)
209: {
210: register int i;
211: printf (" {");
212: for (i = 0; i < d->n_operands; i++)
213: printf (" \"%s\",", d->constraints[i]);
214: if (d->n_operands == 0)
215: printf (" 0");
216: printf (" },\n");
217: }
218: printf (" };\n");
219: }
220: else
221: {
222: printf ("\nchar insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n");
223: for (d = insn_data; d; d = d->next)
224: {
225: register int i;
226: printf (" {");
227: for (i = 0; i < d->n_operands; i++)
228: printf (" %d,", d->address_p[i]);
229: if (d->n_operands == 0)
230: printf (" 0");
231: printf (" },\n");
232: }
233: printf (" };\n");
234: }
235:
236: printf ("\nenum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n");
237: for (d = insn_data; d; d = d->next)
238: {
239: register int i;
240: printf (" {");
241: for (i = 0; i < d->n_operands; i++)
242: printf (" %smode,", GET_MODE_NAME (d->modes[i]));
243: if (d->n_operands == 0)
244: printf (" VOIDmode");
245: printf (" },\n");
246: }
247: printf (" };\n");
248: }
249:
250: /* scan_operands (X) stores in max_opno the largest operand
251: number present in X, if that is larger than the previous
252: value of max_opno. It stores all the constraints in `constraints'
253: and all the machine modes in `modes'. */
254:
255: int max_opno;
256: int num_dups;
257: char *constraints[MAX_MAX_OPERANDS];
258: char address_p[MAX_MAX_OPERANDS];
259: enum machine_mode modes[MAX_MAX_OPERANDS];
260:
261: void
262: scan_operands (part, this_address_p)
263: rtx part;
264: int this_address_p;
265: {
266: register int i, j;
267: register RTX_CODE code = GET_CODE (part);
268: register char *format_ptr;
269:
270: if (code == MATCH_OPERAND)
271: {
272: if (XINT (part, 0) > max_opno)
273: max_opno = XINT (part, 0);
274: if (max_opno > MAX_MAX_OPERANDS)
275: fatal ("Too many operands (%d) in one instruction pattern.\n",
276: max_opno + 1);
277: modes[max_opno] = GET_MODE (part);
278: constraints[max_opno] = XSTR (part, 2);
279: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
280: have_constraints = 1;
281: address_p[max_opno] = this_address_p;
282: return;
283: }
284:
285: if (code == MATCH_DUP)
286: {
287: ++num_dups;
288: return;
289: }
290:
291: if (code == ADDRESS)
292: {
293: scan_operands (XEXP (part, 0), 1);
294: return;
295: }
296:
297: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
298:
299: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
300: switch (*format_ptr++)
301: {
302: case 'e':
303: scan_operands (XEXP (part, i), 0);
304: break;
305: case 'E':
306: if (XVEC (part, i) != NULL)
307: for (j = 0; j < XVECLEN (part, i); j++)
308: scan_operands (XVECEXP (part, i, j), 0);
309: break;
310: }
311: }
312:
313: /* Read the next insn. Assign its code number.
314: Record on insn_data the template and the number of arguments.
315: If the insn has a hairy output action, output it now. */
316:
317: void
318: gen_insn (insn)
319: rtx insn;
320: {
321: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
322: register int i;
323:
324: d->code_number = next_code_number++;
325: if (XSTR (insn, 0)[0])
326: d->name = XSTR (insn, 0);
327: else
328: d->name = 0;
329:
330: /* Build up the list in the same order as the insns are seen
331: in the machine description. */
332: d->next = 0;
333: if (end_of_insn_data)
334: end_of_insn_data->next = d;
335: else
336: insn_data = d;
337:
338: end_of_insn_data = d;
339:
340: max_opno = -1;
341: num_dups = 0;
342:
343: bzero (constraints, sizeof constraints);
344: bzero (address_p, sizeof address_p);
345: bzero (modes, sizeof modes);
346: for (i = 0; i < XVECLEN (insn, 1); i++)
347: scan_operands (XVECEXP (insn, 1, i), 0);
348: d->n_operands = max_opno + 1;
349: d->n_dups = num_dups;
350: bcopy (constraints, d->constraints, sizeof constraints);
351: bcopy (address_p, d->address_p, sizeof address_p);
352: bcopy (modes, d->modes, sizeof modes);
353:
354: /* We need to consider only the instructions whose assembler code template
355: starts with a *. These are the ones where the template is really
356: C code to run to decide on a template to use.
357: So for all others just return now. */
358:
359: if (XSTR (insn, 3)[0] != '*')
360: {
361: d->template = XSTR (insn, 3);
362: return;
363: }
364:
365: d->template = 0;
366: printf (" case %d:\n", d->code_number);
367: printf ("%s\n", &(XSTR (insn, 3)[1]));
368: }
369:
370: xmalloc (size)
371: {
372: register int val = malloc (size);
373:
374: if (val == 0)
375: abort ();
376:
377: return val;
378: }
379:
380: int
381: xrealloc (ptr, size)
382: char *ptr;
383: int size;
384: {
385: int result = realloc (ptr, size);
386: if (!result)
387: abort ();
388: return result;
389: }
390:
391: void
392: fatal (s, a1, a2)
393: {
394: fprintf (stderr, "genemit: ");
395: fprintf (stderr, s, a1, a2);
396: fprintf (stderr, "\n");
397: exit (1);
398: }
399:
400: main (argc, argv)
401: int argc;
402: char **argv;
403: {
404: rtx desc;
405: FILE *infile;
406: extern rtx read_rtx ();
407: register int c;
408:
409: obstack_init (current_obstack);
410:
411: if (argc <= 1)
412: fatal ("No input file name.");
413:
414: infile = fopen (argv[1], "r");
415: if (infile == 0)
416: {
417: perror (argv[1]);
418: exit (1);
419: }
420:
421: init_rtl ();
422:
423: output_prologue ();
424: next_code_number = 0;
425: have_constraints = 0;
426:
427: /* Read the machine description. */
428:
429: while (1)
430: {
431: c = read_skip_spaces (infile);
432: if (c == EOF)
433: break;
434: ungetc (c, infile);
435:
436: desc = read_rtx (infile);
437: gen_insn (desc);
438: }
439:
440: output_epilogue ();
441:
442: return 0;
443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.