|
|
1.1 root 1: /* Generate code to initialize optabs from machine description.
1.1.1.2 root 2: Copyright (C) 1993, 1994 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
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 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
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
1.1.1.3 ! root 18: the Free Software Foundation, 59 Temple Place - Suite 330,
! 19: Boston, MA 02111-1307, USA. */
1.1 root 20:
21:
22: #include <stdio.h>
23: #include "hconfig.h"
24: #include "rtl.h"
25: #include "obstack.h"
26: #include <ctype.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: char *xmalloc ();
38: static void fatal ();
39: void fancy_abort ();
40:
41: /* Many parts of GCC use arrays that are indexed by machine mode and
42: contain the insn codes for pattern in the MD file that perform a given
43: operation on operands of that mode.
44:
45: These patterns are present in the MD file with names that contain
46: the mode(s) used and the name of the operation. This program
47: writes a function `init_all_optabs' that initializes the optabs with
48: all the insn codes of the relevant patterns present in the MD file.
49:
50: This array contains a list of optabs that need to be initialized. Within
51: each string, the name of the pattern to be matched against is delimited
52: with %( and %). In the string, %a and %b are used to match a short mode
53: name (the part of the mode name not including `mode' and converted to
54: lower-case). When writing out the initializer, the entire string is
55: used. %A and %B are replaced with the full name of the mode; %a and %b
56: are replaced with the short form of the name, as above.
57:
58: If %N is present in the pattern, it means the two modes must be consecutive
59: widths in the same mode class (e.g, QImode and HImode). %I means that
60: only integer modes should be considered for the next mode, and %F means
61: that only float modes should be considered.
62:
63: For some optabs, we store the operation by RTL codes. These are only
64: used for comparisons. In that case, %c and %C are the lower-case and
65: upper-case forms of the comparison, respectively. */
66:
67: /* The reason we use \% is to avoid sequences of the form %-capletter-%
68: which SCCS treats as magic. This gets warnings which you should ignore. */
69:
70: char *optabs[] =
71: { "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)",
72: "extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)",
73: "fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)",
74: "fixtab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns%F\%a%b2%)",
75: "fixtrunctab[(int) %A][(int) %B][0] = CODE_FOR_%(fix_trunc%F\%a%I\%b2%)",
76: "fixtrunctab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns_trunc%F\%a%I\%b2%)",
77: "floattab[(int) %B][(int) %A][0] = CODE_FOR_%(float%I\%a%F\%b2%)",
78: "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)",
79: "add_optab->handlers[(int) %A].insn_code = CODE_FOR_%(add%a3%)",
80: "sub_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sub%a3%)",
81: "smul_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mul%a3%)",
1.1.1.2 root 82: "umul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umul%a3_highpart%)",
83: "smul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smul%a3_highpart%)",
1.1 root 84: "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N",
85: "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N",
86: "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)",
87: "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)",
88: "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)",
89: "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)",
90: "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)",
91: "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)",
92: "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)",
93: "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)",
94: "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)",
95: "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)",
96: "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)",
97: "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)",
98: "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)",
99: "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)",
100: "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)",
101: "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)",
102: "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)",
103: "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)",
104: "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)",
105: "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)",
106: "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)",
107: "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)",
108: "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)",
109: "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)",
110: "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)",
111: "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)",
112: "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)",
113: "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
114: "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)",
115: "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)",
116: "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)",
117: "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)",
118: "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)",
119: "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)",
120: "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
121: "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
1.1.1.3 ! root 122: "movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)",
1.1 root 123: "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
124: "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
125: "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)" };
126:
127: /* Allow linking with print-rtl.c. */
128: char **insn_name_ptr;
129:
130: static void
131: gen_insn (insn)
132: rtx insn;
133: {
134: char *name = XSTR (insn, 0);
135: int m1, m2, op;
136: int pindex;
137: int i;
138: char *np, *pp, *p, *q;
139: struct obstack *obstack_ptr;
140:
141: /* Don't mention instructions whose names are the null string.
142: They are in the machine description just to be recognized. */
143: if (*name == 0)
144: return;
145:
146: /* See if NAME matches one of the patterns we have for the optabs we know
147: about. */
148:
149: for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
150: {
151: int force_float = 0, force_int = 0;
152: int force_consec = 0;
153: int matches = 1;
154:
155: for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
156: ;
157:
158: for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
159: pp++)
160: {
161: if (*pp != '%')
162: {
163: if (*pp != *np++)
164: break;
165: }
166: else
167: switch (*++pp)
168: {
169: case 'N':
170: force_consec = 1;
171: break;
172: case 'I':
173: force_int = 1;
174: break;
175: case 'F':
176: force_float = 1;
177: break;
178: case 'c':
179: for (op = 0; op < NUM_RTX_CODE; op++)
180: {
181: for (p = rtx_name[op], q = np; *p; p++, q++)
182: if (*p != *q)
183: break;
184:
185: /* We have to be concerned about matching "gt" and
186: missing "gtu", e.g., so verify we have reached the
187: end of thing we are to match. We do not have this
188: problem with modes since no mode is a prefix of
189: another. */
190: if (*p == 0 && *q == 0 && rtx_class[op] == '<')
191: break;
192: }
193:
194: if (op == NUM_RTX_CODE)
195: matches = 0;
196: else
197: np += strlen (rtx_name[op]);
198: break;
199: case 'a':
200: case 'b':
201: for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
202: {
203: for (p = mode_name[i], q = np; *p; p++, q++)
204: if (tolower (*p) != *q)
205: break;
206:
207: if (*p == 0
208: && (! force_int || mode_class[i] == MODE_INT)
209: && (! force_float || mode_class[i] == MODE_FLOAT))
210: break;
211: }
212:
213: if (i == (int) MAX_MACHINE_MODE)
214: matches = 0;
215: else if (*pp == 'a')
216: m1 = i, np += strlen (mode_name[i]);
217: else
218: m2 = i, np += strlen (mode_name[i]);
219:
220: force_int = force_float = 0;
221: break;
222:
223: default:
224: abort ();
225: }
226: }
227:
228: if (matches && pp[0] == '%' && pp[1] == ')'
229: && *np == 0
1.1.1.3 ! root 230: && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
1.1 root 231: break;
232: }
233:
234: if (pindex == sizeof optabs / sizeof optabs[0])
235: return;
236:
237: /* We found a match. If this pattern is only conditionally present,
238: write out the "if" and two extra blanks. */
239:
240: if (*XSTR (insn, 2) != 0)
241: printf (" if (HAVE_%s)\n ", name);
242:
243: printf (" ");
244:
245: /* Now write out the initialization, making all required substitutions. */
246: for (pp = optabs[pindex]; *pp; pp++)
247: {
248: if (*pp != '%')
249: printf ("%c", *pp);
250: else
251: switch (*++pp)
252: {
253: case '(': case ')':
254: case 'I': case 'F': case 'N':
255: break;
256: case 'a':
257: for (np = mode_name[m1]; *np; np++)
258: printf ("%c", tolower (*np));
259: break;
260: case 'b':
261: for (np = mode_name[m2]; *np; np++)
262: printf ("%c", tolower (*np));
263: break;
264: case 'A':
265: printf ("%smode", mode_name[m1]);
266: break;
267: case 'B':
268: printf ("%smode", mode_name[m2]);
269: break;
270: case 'c':
271: printf ("%s", rtx_name[op]);
272: break;
273: case 'C':
274: for (np = rtx_name[op]; *np; np++)
275: printf ("%c", toupper (*np));
276: break;
277: }
278: }
279:
280: printf (";\n");
281: }
282:
283: char *
284: xmalloc (size)
285: unsigned size;
286: {
287: register char *val = (char *) malloc (size);
288:
289: if (val == 0)
290: fatal ("virtual memory exhausted");
291:
292: return val;
293: }
294:
295: char *
296: xrealloc (ptr, size)
297: char *ptr;
298: unsigned size;
299: {
300: char *result = (char *) realloc (ptr, size);
301: if (!result)
302: fatal ("virtual memory exhausted");
303: return result;
304: }
305:
306: static void
307: fatal (s, a1, a2)
308: char *s;
309: {
310: fprintf (stderr, "genopinit: ");
311: fprintf (stderr, s, a1, a2);
312: fprintf (stderr, "\n");
313: exit (FATAL_EXIT_CODE);
314: }
315:
316: /* More 'friendly' abort that prints the line and file.
317: config.h can #define abort fancy_abort if you like that sort of thing. */
318:
319: void
320: fancy_abort ()
321: {
322: fatal ("Internal gcc abort.");
323: }
324:
325: int
326: main (argc, argv)
327: int argc;
328: char **argv;
329: {
330: rtx desc;
331: rtx dummy;
332: rtx *insn_ptr;
333: FILE *infile;
334: register int c;
335:
336: obstack_init (rtl_obstack);
337:
338: if (argc <= 1)
339: fatal ("No input file name.");
340:
341: infile = fopen (argv[1], "r");
342: if (infile == 0)
343: {
344: perror (argv[1]);
345: exit (FATAL_EXIT_CODE);
346: }
347:
348: init_rtl ();
349:
350: printf ("/* Generated automatically by the program `genopinit'\n\
351: from the machine description file `md'. */\n\n");
352:
353: printf ("#include \"config.h\"\n");
354: printf ("#include \"rtl.h\"\n");
355: printf ("#include \"flags.h\"\n");
356: printf ("#include \"insn-flags.h\"\n");
357: printf ("#include \"insn-codes.h\"\n");
358: printf ("#include \"insn-config.h\"\n");
359: printf ("#include \"recog.h\"\n");
360: printf ("#include \"expr.h\"\n");
361: printf ("#include \"reload.h\"\n\n");
362:
363: printf ("void\ninit_all_optabs ()\n{\n");
364:
365: /* Read the machine description. */
366:
367: while (1)
368: {
369: c = read_skip_spaces (infile);
370: if (c == EOF)
371: break;
372: ungetc (c, infile);
373:
374: desc = read_rtx (infile);
375: if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
376: gen_insn (desc);
377: }
378:
379: printf ("}\n");
380:
381: fflush (stdout);
382: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
383: /* NOTREACHED */
384: return 0;
385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.