|
|
1.1 root 1: /* Generate code from to output assembler insns as recognized from rtl.
1.1.1.7 root 2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
1.1.1.7 root 6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
1.1 root 11: GNU CC is distributed in the hope that it will be useful,
1.1.1.7 root 12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
1.1 root 19:
20:
21: /* This program reads the machine description for the compiler target machine
22: and produces a file containing three things:
23:
24: 1, An array of strings `insn_template' which is indexed by insn code number
25: and contains the template for output of that insn,
26:
27: 2. An array of ints `insn_n_operands' which is indexed by insn code number
28: and contains the number of distinct operands in the pattern for that insn,
29:
30: 3. An array of ints `insn_n_dups' which is indexed by insn code number
31: and contains the number of match_dup's that appear in the insn's pattern.
32: This says how many elements of `recog_dup_loc' are significant
33: after an insn has been recognized.
34:
1.1.1.2 root 35: 4. An array of arrays of operand constraint strings,
1.1 root 36: `insn_operand_constraint',
37: indexed first by insn code number and second by operand number,
38: containing the constraint for that operand.
1.1.1.2 root 39:
1.1 root 40: This array is generated only if register constraints appear in
41: match_operand rtx's.
42:
1.1.1.2 root 43: 5. An array of arrays of chars which indicate which operands of
1.1 root 44: which insn patterns appear within ADDRESS rtx's. This array is
45: called `insn_operand_address_p' and is generated only if there
46: are *no* register constraints in the match_operand rtx's.
47:
1.1.1.2 root 48: 6. An array of arrays of machine modes, `insn_operand_mode',
49: indexed first by insn code number and second by operand number,
50: containing the machine mode that that operand is supposed to have.
51: Also `insn_operand_strict_low', which is nonzero for operands
52: contained in a STRICT_LOW_PART.
53:
54: 7. An array of arrays of int-valued functions, `insn_operand_predicate',
55: indexed first by insn code number and second by operand number,
56: containing the match_operand predicate for this operand.
57:
58: 8. An array of functions `insn_gen_function' which, indexed
1.1 root 59: by insn code number, gives the function to generate a body
60: for that patter, given operands as arguments.
61:
1.1.1.2 root 62: 9. A function `output_insn_hairy' which is called with two arguments
1.1 root 63: (an insn code number and a vector of operand value rtx's)
64: and returns a template to use for output of that insn.
65: This is used only in the cases where the template is not constant.
66: These cases are specified by a * at the beginning of the template string
67: in the machine description. They are identified for the sake of
68: other parts of the compiler by a zero element in `insn_template'.
1.1.1.4 root 69:
70: 10. An array of structures, `insn_machine_info', that gives machine-specific
71: information about the insn.
1.1 root 72:
1.1.1.5 root 73: 11. An array of ints, `insn_n_alternatives', that gives the number
74: of alternatives in the constraints of each pattern.
75:
1.1 root 76: The code number of an insn is simply its position in the machine description;
77: code numbers are assigned sequentially to entries in the description,
78: starting with code number 0.
79:
80: Thus, the following entry in the machine description
81:
82: (define_insn "clrdf"
83: [(set (match_operand:DF 0 "general_operand" "")
84: (const_int 0))]
85: ""
86: "clrd %0")
87:
88: assuming it is the 25th entry present, would cause
1.1.1.2 root 89: insn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1.
1.1 root 90: It would not make an case in output_insn_hairy because the template
91: given in the entry is a constant (it does not start with `*'). */
92:
93: #include <stdio.h>
1.1.1.2 root 94: #include "config.h"
1.1 root 95: #include "rtl.h"
1.1.1.2 root 96: #include "obstack.h"
1.1 root 97:
98: /* No instruction can have more operands than this.
99: Sorry for this arbitrary limit, but what machine will
100: have an instruction with this many operands? */
101:
102: #define MAX_MAX_OPERANDS 40
103:
104: struct obstack obstack;
1.1.1.2 root 105: struct obstack *rtl_obstack = &obstack;
1.1 root 106:
107: #define obstack_chunk_alloc xmalloc
108: #define obstack_chunk_free free
109: extern int xmalloc ();
110: extern void free ();
111:
112: void fatal ();
1.1.1.9 ! root 113: void fancy_abort ();
1.1.1.6 root 114: void error ();
1.1.1.2 root 115: void mybcopy ();
116: void mybzero ();
1.1 root 117:
118: /* insns in the machine description are assigned sequential code numbers
119: that are used by insn-recog.c (produced by genrecog) to communicate
120: to insn-output.c (produced by this program). */
121:
122: int next_code_number;
123:
124: /* Record in this chain all information that we will output,
125: associated with the code number of the insn. */
126:
127: struct data
128: {
129: int code_number;
130: char *name;
131: char *template; /* string such as "movl %1,%0" */
132: int n_operands; /* Number of operands this insn recognizes */
133: int n_dups; /* Number times match_dup appears in pattern */
1.1.1.5 root 134: int n_alternatives; /* Number of alternatives in each constraint */
1.1 root 135: struct data *next;
136: char *constraints[MAX_MAX_OPERANDS];
1.1.1.5 root 137: /* Number of alternatives in constraints of operand N. */
138: int op_n_alternatives[MAX_MAX_OPERANDS];
1.1.1.2 root 139: char *predicates[MAX_MAX_OPERANDS];
1.1 root 140: char address_p[MAX_MAX_OPERANDS];
141: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 142: char strict_low[MAX_MAX_OPERANDS];
143: char outfun; /* Nonzero means this has an output function */
1.1.1.4 root 144: char *machine_info; /* machine-specific info string. */
1.1 root 145: };
146:
147: /* This variable points to the first link in the chain. */
148:
149: struct data *insn_data;
150:
151: /* Pointer to the last link in the chain, so new elements
152: can be added at the end. */
153:
154: struct data *end_of_insn_data;
155:
156: /* Nonzero if any match_operand has a constraint string;
157: implies that REGISTER_CONSTRAINTS will be defined
158: for this machine description. */
159:
160: int have_constraints;
161:
162: void
163: output_prologue ()
164: {
165:
166: printf ("/* Generated automatically by the program `genoutput'\n\
167: from the machine description file `md'. */\n\n");
168:
169: printf ("#include \"config.h\"\n");
170: printf ("#include \"rtl.h\"\n");
171: printf ("#include \"regs.h\"\n");
1.1.1.8 root 172: printf ("#include \"hard-reg-set.h\"\n");
1.1.1.6 root 173: printf ("#include \"real.h\"\n");
1.1 root 174: printf ("#include \"conditions.h\"\n");
175: printf ("#include \"insn-flags.h\"\n");
176: printf ("#include \"insn-config.h\"\n\n");
177:
1.1.1.4 root 178: printf ("#ifndef __STDC__\n");
179: printf ("#define const\n");
180: printf ("#endif\n\n");
181:
182: printf ("#include \"output.h\"\n");
1.1 root 183: printf ("#include \"aux-output.c\"\n\n");
1.1.1.4 root 184:
185: /* Make sure there is at least a dummy definition of INSN_MACHINE_INFO. */
186: printf ("#ifndef INSN_MACHINE_INFO\n");
187: printf ("#define INSN_MACHINE_INFO struct dummy1 {int i;}\n");
188: printf ("#endif\n\n");
1.1 root 189: }
190:
191: void
192: output_epilogue ()
193: {
194: register struct data *d;
195:
1.1.1.4 root 196: printf ("\nchar * const insn_template[] =\n {\n");
1.1 root 197: for (d = insn_data; d; d = d->next)
198: {
199: if (d->template)
200: printf (" \"%s\",\n", d->template);
201: else
202: printf (" 0,\n");
203: }
204: printf (" };\n");
205:
1.1.1.4 root 206: printf ("\nchar *(*const insn_outfun[])() =\n {\n");
1.1.1.2 root 207: for (d = insn_data; d; d = d->next)
208: {
209: if (d->outfun)
1.1.1.3 root 210: printf (" output_%d,\n", d->code_number);
1.1.1.2 root 211: else
212: printf (" 0,\n");
213: }
214: printf (" };\n");
215:
1.1.1.4 root 216: printf ("\nrtx (*const insn_gen_function[]) () =\n {\n");
1.1 root 217: for (d = insn_data; d; d = d->next)
218: {
219: if (d->name)
220: printf (" gen_%s,\n", d->name);
221: else
222: printf (" 0,\n");
223: }
224: printf (" };\n");
225:
1.1.1.4 root 226: printf ("\nconst int insn_n_operands[] =\n {\n");
1.1 root 227: for (d = insn_data; d; d = d->next)
228: {
229: printf (" %d,\n", d->n_operands);
230: }
231: printf (" };\n");
232:
1.1.1.4 root 233: printf ("\nconst int insn_n_dups[] =\n {\n");
1.1 root 234: for (d = insn_data; d; d = d->next)
235: {
236: printf (" %d,\n", d->n_dups);
237: }
238: printf (" };\n");
239:
240: if (have_constraints)
241: {
1.1.1.4 root 242: printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 243: for (d = insn_data; d; d = d->next)
244: {
1.1.1.5 root 245: register int i, n = 0, start;
1.1 root 246: printf (" {");
1.1.1.5 root 247: /* Make sure all the operands have the same number of
248: alternatives in their constraints.
249: Let N be that number. */
250: for (start = 0; start < d->n_operands; start++)
251: if (d->op_n_alternatives[start] > 0)
252: {
253: if (n == 0)
254: n = d->op_n_alternatives[start];
255: else if (n != d->op_n_alternatives[start])
1.1.1.6 root 256: error ("wrong number of alternatives in operand %d of insn number %d",
1.1.1.5 root 257: start, d->code_number);
258: }
259: /* Record the insn's overall number of alternatives. */
260: d->n_alternatives = n;
261:
1.1 root 262: for (i = 0; i < d->n_operands; i++)
1.1.1.2 root 263: {
264: if (d->constraints[i] == 0)
265: printf (" \"\",");
266: else
267: printf (" \"%s\",", d->constraints[i]);
268: }
1.1 root 269: if (d->n_operands == 0)
270: printf (" 0");
271: printf (" },\n");
272: }
273: printf (" };\n");
274: }
275: else
276: {
1.1.1.4 root 277: printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 278: for (d = insn_data; d; d = d->next)
279: {
280: register int i;
281: printf (" {");
282: for (i = 0; i < d->n_operands; i++)
283: printf (" %d,", d->address_p[i]);
284: if (d->n_operands == 0)
285: printf (" 0");
286: printf (" },\n");
287: }
288: printf (" };\n");
289: }
290:
1.1.1.4 root 291: printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 292: for (d = insn_data; d; d = d->next)
293: {
294: register int i;
295: printf (" {");
296: for (i = 0; i < d->n_operands; i++)
297: printf (" %smode,", GET_MODE_NAME (d->modes[i]));
298: if (d->n_operands == 0)
299: printf (" VOIDmode");
300: printf (" },\n");
301: }
302: printf (" };\n");
1.1.1.2 root 303:
1.1.1.4 root 304: printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n {\n");
1.1.1.2 root 305: for (d = insn_data; d; d = d->next)
306: {
307: register int i;
308: printf (" {");
309: for (i = 0; i < d->n_operands; i++)
310: printf (" %d,", d->strict_low[i]);
311: if (d->n_operands == 0)
312: printf (" 0");
313: printf (" },\n");
314: }
315: printf (" };\n");
316:
1.1.1.4 root 317: printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n {\n");
1.1.1.2 root 318: for (d = insn_data; d; d = d->next)
319: {
320: register int i;
321: printf (" {");
322: for (i = 0; i < d->n_operands; i++)
323: printf (" %s,", ((d->predicates[i] && d->predicates[i][0])
324: ? d->predicates[i] : "0"));
325: if (d->n_operands == 0)
326: printf (" 0");
327: printf (" },\n");
328: }
329: printf (" };\n");
1.1.1.4 root 330:
1.1.1.9 ! root 331: printf ("\n#ifndef DEFAULT_MACHINE_INFO\n#define DEFAULT_MACHINE_INFO 0\n");
! 332: printf ("#endif\n\nconst INSN_MACHINE_INFO insn_machine_info[] =\n {\n");
1.1.1.4 root 333: for (d = insn_data; d; d = d->next)
334: {
335: if (d->machine_info)
336: printf (" {%s},\n", d->machine_info);
337: else
1.1.1.9 ! root 338: printf(" { DEFAULT_MACHINE_INFO },\n");
1.1.1.4 root 339: }
340: printf(" };\n");
1.1.1.5 root 341:
342: printf ("\nconst int insn_n_alternatives[] =\n {\n");
343: for (d = insn_data; d; d = d->next)
344: {
345: if (d->n_alternatives)
346: printf (" %d,\n", d->n_alternatives);
347: else
348: printf(" 0,\n");
349: }
350: printf(" };\n");
1.1 root 351: }
352:
353: /* scan_operands (X) stores in max_opno the largest operand
354: number present in X, if that is larger than the previous
355: value of max_opno. It stores all the constraints in `constraints'
1.1.1.2 root 356: and all the machine modes in `modes'.
357:
358: THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
359: THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */
1.1 root 360:
361: int max_opno;
362: int num_dups;
363: char *constraints[MAX_MAX_OPERANDS];
1.1.1.5 root 364: int op_n_alternatives[MAX_MAX_OPERANDS];
1.1.1.2 root 365: char *predicates[MAX_MAX_OPERANDS];
1.1 root 366: char address_p[MAX_MAX_OPERANDS];
367: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 368: char strict_low[MAX_MAX_OPERANDS];
1.1 root 369:
370: void
1.1.1.2 root 371: scan_operands (part, this_address_p, this_strict_low)
1.1 root 372: rtx part;
373: int this_address_p;
1.1.1.2 root 374: int this_strict_low;
1.1 root 375: {
376: register int i, j;
1.1.1.2 root 377: register RTX_CODE code;
1.1 root 378: register char *format_ptr;
379:
1.1.1.2 root 380: if (part == 0)
381: return;
382:
383: code = GET_CODE (part);
384:
1.1 root 385: if (code == MATCH_OPERAND)
386: {
1.1.1.2 root 387: int opno = XINT (part, 0);
388: if (opno > max_opno)
389: max_opno = opno;
390: if (max_opno >= MAX_MAX_OPERANDS)
1.1.1.6 root 391: error ("Too many operands (%d) in one instruction pattern.\n",
1.1 root 392: max_opno + 1);
1.1.1.2 root 393: modes[opno] = GET_MODE (part);
394: strict_low[opno] = this_strict_low;
395: predicates[opno] = XSTR (part, 1);
396: constraints[opno] = XSTR (part, 2);
1.1 root 397: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
1.1.1.5 root 398: {
399: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1;
400: have_constraints = 1;
401: }
1.1.1.2 root 402: address_p[opno] = this_address_p;
1.1 root 403: return;
404: }
405:
1.1.1.5 root 406: if (code == MATCH_OPERATOR)
407: {
408: int opno = XINT (part, 0);
409: if (opno > max_opno)
410: max_opno = opno;
411: if (max_opno >= MAX_MAX_OPERANDS)
1.1.1.6 root 412: error ("Too many operands (%d) in one instruction pattern.\n",
1.1.1.5 root 413: max_opno + 1);
414: modes[opno] = GET_MODE (part);
415: strict_low[opno] = 0;
416: predicates[opno] = XSTR (part, 1);
417: constraints[opno] = 0;
418: address_p[opno] = 0;
419: for (i = 0; i < XVECLEN (part, 2); i++)
420: scan_operands (XVECEXP (part, 2, i), 0, 0);
421: return;
422: }
423:
1.1 root 424: if (code == MATCH_DUP)
425: {
426: ++num_dups;
427: return;
428: }
429:
430: if (code == ADDRESS)
431: {
1.1.1.2 root 432: scan_operands (XEXP (part, 0), 1, 0);
433: return;
434: }
435:
436: if (code == STRICT_LOW_PART)
437: {
438: scan_operands (XEXP (part, 0), 0, 1);
1.1 root 439: return;
440: }
441:
442: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
443:
444: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
445: switch (*format_ptr++)
446: {
447: case 'e':
1.1.1.2 root 448: scan_operands (XEXP (part, i), 0, 0);
1.1 root 449: break;
450: case 'E':
451: if (XVEC (part, i) != NULL)
452: for (j = 0; j < XVECLEN (part, i); j++)
1.1.1.2 root 453: scan_operands (XVECEXP (part, i, j), 0, 0);
1.1 root 454: break;
455: }
456: }
457:
1.1.1.2 root 458: /* Look at a define_insn just read. Assign its code number.
1.1 root 459: Record on insn_data the template and the number of arguments.
1.1.1.2 root 460: If the insn has a hairy output action, output a function for now. */
1.1 root 461:
462: void
463: gen_insn (insn)
464: rtx insn;
465: {
466: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
467: register int i;
468:
469: d->code_number = next_code_number++;
470: if (XSTR (insn, 0)[0])
471: d->name = XSTR (insn, 0);
472: else
473: d->name = 0;
474:
475: /* Build up the list in the same order as the insns are seen
476: in the machine description. */
477: d->next = 0;
478: if (end_of_insn_data)
479: end_of_insn_data->next = d;
480: else
481: insn_data = d;
482:
483: end_of_insn_data = d;
484:
485: max_opno = -1;
486: num_dups = 0;
487:
1.1.1.2 root 488: mybzero (constraints, sizeof constraints);
1.1.1.5 root 489: mybzero (op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 490: mybzero (predicates, sizeof predicates);
491: mybzero (address_p, sizeof address_p);
492: mybzero (modes, sizeof modes);
493: mybzero (strict_low, sizeof strict_low);
1.1 root 494: for (i = 0; i < XVECLEN (insn, 1); i++)
1.1.1.2 root 495: scan_operands (XVECEXP (insn, 1, i), 0, 0);
1.1 root 496: d->n_operands = max_opno + 1;
497: d->n_dups = num_dups;
1.1.1.2 root 498: mybcopy (constraints, d->constraints, sizeof constraints);
1.1.1.5 root 499: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 500: mybcopy (predicates, d->predicates, sizeof predicates);
501: mybcopy (address_p, d->address_p, sizeof address_p);
502: mybcopy (modes, d->modes, sizeof modes);
503: mybcopy (strict_low, d->strict_low, sizeof strict_low);
1.1.1.4 root 504: d->machine_info = XSTR (insn, 4);
1.1 root 505:
506: /* We need to consider only the instructions whose assembler code template
507: starts with a *. These are the ones where the template is really
508: C code to run to decide on a template to use.
509: So for all others just return now. */
510:
511: if (XSTR (insn, 3)[0] != '*')
512: {
513: d->template = XSTR (insn, 3);
1.1.1.2 root 514: d->outfun = 0;
1.1 root 515: return;
516: }
517:
518: d->template = 0;
1.1.1.2 root 519: d->outfun = 1;
520:
1.1.1.9 ! root 521: printf ("\nstatic char *\n");
1.1.1.2 root 522: printf ("output_%d (operands, insn)\n", d->code_number);
523: printf (" rtx *operands;\n");
524: printf (" rtx insn;\n");
525: printf ("{\n");
526: /* The following is done in a funny way to get around problems in
527: VAX-11 "C" on VMS. It is the equivalent of:
528: printf ("%s\n", &(XSTR (insn, 3)[1])); */
529: {
530: register char *cp = &(XSTR (insn, 3)[1]);
531: while (*cp) putchar (*cp++);
532: putchar ('\n');
533: }
534: printf ("}\n");
1.1 root 535: }
536:
1.1.1.2 root 537: /* Look at a define_peephole just read. Assign its code number.
538: Record on insn_data the template and the number of arguments.
539: If the insn has a hairy output action, output it now. */
540:
541: void
542: gen_peephole (peep)
543: rtx peep;
544: {
545: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
546: register int i;
547:
548: d->code_number = next_code_number++;
549: d->name = 0;
550:
551: /* Build up the list in the same order as the insns are seen
552: in the machine description. */
553: d->next = 0;
554: if (end_of_insn_data)
555: end_of_insn_data->next = d;
556: else
557: insn_data = d;
558:
559: end_of_insn_data = d;
560:
561: max_opno = -1;
562: mybzero (constraints, sizeof constraints);
1.1.1.5 root 563: mybzero (op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 564:
565: /* Get the number of operands by scanning all the
566: patterns of the peephole optimizer.
567: But ignore all the rest of the information thus obtained. */
568: for (i = 0; i < XVECLEN (peep, 0); i++)
569: scan_operands (XVECEXP (peep, 0, i), 0, 0);
570:
571: d->n_operands = max_opno + 1;
572: d->n_dups = 0;
573: mybcopy (constraints, d->constraints, sizeof constraints);
1.1.1.5 root 574: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 575: mybzero (d->predicates, sizeof predicates);
576: mybzero (d->address_p, sizeof address_p);
577: mybzero (d->modes, sizeof modes);
578: mybzero (d->strict_low, sizeof strict_low);
1.1.1.4 root 579: d->machine_info = XSTR (peep, 3);
1.1.1.2 root 580:
581: /* We need to consider only the instructions whose assembler code template
582: starts with a *. These are the ones where the template is really
583: C code to run to decide on a template to use.
584: So for all others just return now. */
585:
586: if (XSTR (peep, 2)[0] != '*')
587: {
588: d->template = XSTR (peep, 2);
589: d->outfun = 0;
590: return;
591: }
592:
593: d->template = 0;
594: d->outfun = 1;
595:
1.1.1.9 ! root 596: printf ("\nstatic char *\n");
1.1.1.2 root 597: printf ("output_%d (operands, insn)\n", d->code_number);
598: printf (" rtx *operands;\n");
599: printf (" rtx insn;\n");
600: printf ("{\n");
601: printf ("%s\n", &(XSTR (peep, 2)[1]));
602: printf ("}\n");
603: }
604:
605: /* Process a define_expand just read. Assign its code number,
606: only for the purposes of `insn_gen_function'. */
607:
608: void
609: gen_expand (insn)
610: rtx insn;
611: {
612: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
613: register int i;
614:
615: d->code_number = next_code_number++;
616: if (XSTR (insn, 0)[0])
617: d->name = XSTR (insn, 0);
618: else
619: d->name = 0;
620:
621: /* Build up the list in the same order as the insns are seen
622: in the machine description. */
623: d->next = 0;
624: if (end_of_insn_data)
625: end_of_insn_data->next = d;
626: else
627: insn_data = d;
628:
629: end_of_insn_data = d;
630:
631: max_opno = -1;
632: num_dups = 0;
633:
634: /* Scan the operands to get the specified predicates and modes,
635: since expand_binop needs to know them. */
636:
637: mybzero (predicates, sizeof predicates);
638: mybzero (modes, sizeof modes);
639: if (XVEC (insn, 1))
640: for (i = 0; i < XVECLEN (insn, 1); i++)
641: scan_operands (XVECEXP (insn, 1, i), 0, 0);
642: d->n_operands = max_opno + 1;
643: mybcopy (predicates, d->predicates, sizeof predicates);
644: mybcopy (modes, d->modes, sizeof modes);
645:
646: mybzero (d->constraints, sizeof constraints);
1.1.1.5 root 647: mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
1.1.1.2 root 648: mybzero (d->address_p, sizeof address_p);
649: mybzero (d->strict_low, sizeof strict_low);
650:
651: d->n_dups = 0;
652: d->template = 0;
653: d->outfun = 0;
1.1.1.4 root 654: d->machine_info = 0;
1.1.1.2 root 655: }
656:
657: int
1.1 root 658: xmalloc (size)
659: {
660: register int val = malloc (size);
661:
662: if (val == 0)
1.1.1.2 root 663: fatal ("virtual memory exhausted");
1.1 root 664: return val;
665: }
666:
667: int
668: xrealloc (ptr, size)
669: char *ptr;
670: int size;
671: {
672: int result = realloc (ptr, size);
673: if (!result)
1.1.1.2 root 674: fatal ("virtual memory exhausted");
1.1 root 675: return result;
676: }
677:
678: void
1.1.1.2 root 679: mybzero (b, length)
680: register char *b;
681: register int length;
682: {
683: while (length-- > 0)
684: *b++ = 0;
685: }
686:
687: void
688: mybcopy (b1, b2, length)
689: register char *b1;
690: register char *b2;
691: register int length;
692: {
693: while (length-- > 0)
694: *b2++ = *b1++;
695: }
696:
697: void
1.1 root 698: fatal (s, a1, a2)
1.1.1.9 ! root 699: char *s;
1.1 root 700: {
1.1.1.2 root 701: fprintf (stderr, "genoutput: ");
1.1 root 702: fprintf (stderr, s, a1, a2);
703: fprintf (stderr, "\n");
1.1.1.2 root 704: exit (FATAL_EXIT_CODE);
1.1 root 705: }
1.1.1.6 root 706:
1.1.1.9 ! root 707: /* More 'friendly' abort that prints the line and file.
! 708: config.h can #define abort fancy_abort if you like that sort of thing. */
! 709:
! 710: void
! 711: fancy_abort ()
! 712: {
! 713: fatal ("Internal gcc abort.");
! 714: }
! 715:
1.1.1.6 root 716: void
717: error (s, a1, a2)
1.1.1.9 ! root 718: char *s;
1.1.1.6 root 719: {
720: fprintf (stderr, "genoutput: ");
721: fprintf (stderr, s, a1, a2);
722: fprintf (stderr, "\n");
723: }
1.1 root 724:
1.1.1.2 root 725: int
1.1 root 726: main (argc, argv)
727: int argc;
728: char **argv;
729: {
730: rtx desc;
731: FILE *infile;
732: extern rtx read_rtx ();
733: register int c;
734:
1.1.1.2 root 735: obstack_init (rtl_obstack);
1.1 root 736:
737: if (argc <= 1)
738: fatal ("No input file name.");
739:
740: infile = fopen (argv[1], "r");
741: if (infile == 0)
742: {
743: perror (argv[1]);
1.1.1.2 root 744: exit (FATAL_EXIT_CODE);
1.1 root 745: }
746:
747: init_rtl ();
748:
749: output_prologue ();
750: next_code_number = 0;
751: have_constraints = 0;
752:
753: /* Read the machine description. */
754:
755: while (1)
756: {
757: c = read_skip_spaces (infile);
758: if (c == EOF)
759: break;
760: ungetc (c, infile);
761:
762: desc = read_rtx (infile);
1.1.1.2 root 763: if (GET_CODE (desc) == DEFINE_INSN)
764: gen_insn (desc);
765: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
766: gen_peephole (desc);
767: if (GET_CODE (desc) == DEFINE_EXPAND)
768: gen_expand (desc);
1.1 root 769: }
770:
771: output_epilogue ();
772:
1.1.1.2 root 773: fflush (stdout);
774: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
1.1 root 775: }
1.1.1.5 root 776:
777: int
778: n_occurrences (c, s)
779: char c;
780: char *s;
781: {
782: int n = 0;
783: while (*s)
784: n += (*s++ == c);
785: return n;
786: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.