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