]>
Commit | Line | Data |
---|---|---|
41299f41 | 1 | /* Generate from machine description: |
41299f41 TW |
2 | - some flags HAVE_... saying which simple standard instructions are |
3 | available for this machine. | |
d050d723 JL |
4 | Copyright (C) 1987, 1991, 1995, 1998, |
5 | 1999, 2000 Free Software Foundation, Inc. | |
41299f41 TW |
6 | |
7 | This file is part of GNU CC. | |
8 | ||
9 | GNU CC is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2, or (at your option) | |
12 | any later version. | |
13 | ||
14 | GNU CC is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GNU CC; see the file COPYING. If not, write to | |
a35311b0 RK |
21 | the Free Software Foundation, 59 Temple Place - Suite 330, |
22 | Boston, MA 02111-1307, USA. */ | |
41299f41 TW |
23 | |
24 | ||
20f92396 | 25 | #include "hconfig.h" |
0b93b64e | 26 | #include "system.h" |
41299f41 TW |
27 | #include "rtl.h" |
28 | #include "obstack.h" | |
f8b6598e | 29 | #include "errors.h" |
c88c0d42 | 30 | #include "gensupport.h" |
41299f41 | 31 | |
41299f41 TW |
32 | |
33 | #define obstack_chunk_alloc xmalloc | |
34 | #define obstack_chunk_free free | |
35 | ||
f837a861 MM |
36 | /* Obstacks to remember normal, and call insns. */ |
37 | static struct obstack call_obstack, normal_obstack; | |
38 | ||
39 | /* Max size of names encountered. */ | |
40 | static int max_id_len; | |
41 | ||
706b0f60 ZW |
42 | /* Max operand encountered in a scan over some insn. */ |
43 | static int max_opno; | |
56c0e996 | 44 | |
706b0f60 ZW |
45 | static void max_operand_1 PARAMS ((rtx)); |
46 | static int num_operands PARAMS ((rtx)); | |
47 | static void gen_proto PARAMS ((rtx)); | |
48 | static void gen_nonproto PARAMS ((rtx)); | |
49 | static void gen_insn PARAMS ((rtx)); | |
56c0e996 | 50 | |
f837a861 | 51 | /* Count the number of match_operand's found. */ |
0f41302f | 52 | |
706b0f60 ZW |
53 | static void |
54 | max_operand_1 (x) | |
f837a861 MM |
55 | rtx x; |
56 | { | |
706b0f60 ZW |
57 | register RTX_CODE code; |
58 | register int i; | |
59 | register int len; | |
60 | register const char *fmt; | |
f837a861 | 61 | |
706b0f60 ZW |
62 | if (x == 0) |
63 | return; | |
f837a861 | 64 | |
706b0f60 | 65 | code = GET_CODE (x); |
f837a861 | 66 | |
706b0f60 ZW |
67 | if (code == MATCH_OPERAND || code == MATCH_OPERATOR |
68 | || code == MATCH_PARALLEL) | |
69 | max_opno = MAX (max_opno, XINT (x, 0)); | |
70 | ||
71 | fmt = GET_RTX_FORMAT (code); | |
72 | len = GET_RTX_LENGTH (code); | |
73 | for (i = 0; i < len; i++) | |
f837a861 | 74 | { |
706b0f60 ZW |
75 | if (fmt[i] == 'e' || fmt[i] == 'u') |
76 | max_operand_1 (XEXP (x, i)); | |
77 | else if (fmt[i] == 'E') | |
f837a861 | 78 | { |
706b0f60 ZW |
79 | int j; |
80 | for (j = 0; j < XVECLEN (x, i); j++) | |
81 | max_operand_1 (XVECEXP (x, i, j)); | |
f837a861 MM |
82 | } |
83 | } | |
706b0f60 | 84 | } |
f837a861 | 85 | |
706b0f60 ZW |
86 | static int |
87 | num_operands (insn) | |
88 | rtx insn; | |
89 | { | |
90 | register int len = XVECLEN (insn, 1); | |
91 | register int i; | |
92 | ||
93 | max_opno = -1; | |
94 | ||
95 | for (i = 0; i < len; i++) | |
96 | max_operand_1 (XVECEXP (insn, 1, i)); | |
97 | ||
98 | return max_opno + 1; | |
f837a861 MM |
99 | } |
100 | ||
101 | /* Print out prototype information for a function. */ | |
0f41302f | 102 | |
f837a861 MM |
103 | static void |
104 | gen_proto (insn) | |
105 | rtx insn; | |
106 | { | |
107 | int num = num_operands (insn); | |
a94ae8f5 | 108 | printf ("extern rtx gen_%-*s PARAMS ((", max_id_len, XSTR (insn, 0)); |
f837a861 MM |
109 | |
110 | if (num == 0) | |
111 | printf ("void"); | |
112 | else | |
113 | { | |
114 | while (num-- > 1) | |
115 | printf ("rtx, "); | |
116 | ||
117 | printf ("rtx"); | |
118 | } | |
119 | ||
120 | printf ("));\n"); | |
121 | } | |
122 | ||
123 | /* Print out a function declaration without a prototype. */ | |
0f41302f | 124 | |
f837a861 MM |
125 | static void |
126 | gen_nonproto (insn) | |
127 | rtx insn; | |
128 | { | |
129 | printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); | |
130 | } | |
131 | ||
41299f41 TW |
132 | static void |
133 | gen_insn (insn) | |
134 | rtx insn; | |
135 | { | |
3cce094d KG |
136 | const char *name = XSTR (insn, 0); |
137 | const char *p; | |
f837a861 MM |
138 | struct obstack *obstack_ptr; |
139 | int len; | |
41299f41 | 140 | |
6b6ca844 RK |
141 | /* Don't mention instructions whose names are the null string |
142 | or begin with '*'. They are in the machine description just | |
143 | to be recognized. */ | |
144 | if (name[0] == 0 || name[0] == '*') | |
41299f41 TW |
145 | return; |
146 | ||
6b6ca844 RK |
147 | len = strlen (name); |
148 | ||
f837a861 MM |
149 | if (len > max_id_len) |
150 | max_id_len = len; | |
151 | ||
152 | printf ("#define HAVE_%s ", name); | |
41299f41 TW |
153 | if (strlen (XSTR (insn, 2)) == 0) |
154 | printf ("1\n"); | |
155 | else | |
156 | { | |
157 | /* Write the macro definition, putting \'s at the end of each line, | |
158 | if more than one. */ | |
159 | printf ("("); | |
160 | for (p = XSTR (insn, 2); *p; p++) | |
161 | { | |
162 | if (*p == '\n') | |
163 | printf (" \\\n"); | |
164 | else | |
165 | printf ("%c", *p); | |
166 | } | |
167 | printf (")\n"); | |
168 | } | |
6610a1b0 | 169 | |
f837a861 MM |
170 | /* Save the current insn, so that we can later put out appropriate |
171 | prototypes. At present, most md files have the wrong number of | |
6610a1b0 MM |
172 | arguments for the call insns (call, call_value, call_pop, |
173 | call_value_pop) ignoring the extra arguments that are passed for | |
174 | some machines, so by default, turn off the prototype. */ | |
175 | ||
0a1c58a2 | 176 | obstack_ptr = ((name[0] == 'c' || name[0] == 's') |
6610a1b0 MM |
177 | && (!strcmp (name, "call") |
178 | || !strcmp (name, "call_value") | |
179 | || !strcmp (name, "call_pop") | |
0a1c58a2 JL |
180 | || !strcmp (name, "call_value_pop") |
181 | || !strcmp (name, "sibcall") | |
182 | || !strcmp (name, "sibcall_value") | |
183 | || !strcmp (name, "sibcall_pop") | |
184 | || !strcmp (name, "sibcall_value_pop"))) | |
f837a861 MM |
185 | ? &call_obstack : &normal_obstack; |
186 | ||
187 | obstack_grow (obstack_ptr, &insn, sizeof (rtx)); | |
41299f41 TW |
188 | } |
189 | \f | |
2778b98d | 190 | PTR |
41299f41 | 191 | xmalloc (size) |
2778b98d | 192 | size_t size; |
41299f41 | 193 | { |
2778b98d | 194 | register PTR val = (PTR) malloc (size); |
41299f41 TW |
195 | |
196 | if (val == 0) | |
197 | fatal ("virtual memory exhausted"); | |
198 | ||
199 | return val; | |
200 | } | |
201 | ||
2778b98d | 202 | PTR |
470b68c0 RH |
203 | xrealloc (old, size) |
204 | PTR old; | |
2778b98d | 205 | size_t size; |
41299f41 | 206 | { |
470b68c0 | 207 | register PTR ptr; |
09d83d25 | 208 | if (old) |
470b68c0 RH |
209 | ptr = (PTR) realloc (old, size); |
210 | else | |
211 | ptr = (PTR) malloc (size); | |
212 | if (!ptr) | |
41299f41 | 213 | fatal ("virtual memory exhausted"); |
470b68c0 | 214 | return ptr; |
41299f41 TW |
215 | } |
216 | ||
a94ae8f5 | 217 | extern int main PARAMS ((int, char **)); |
c1b59dce | 218 | |
41299f41 TW |
219 | int |
220 | main (argc, argv) | |
221 | int argc; | |
222 | char **argv; | |
223 | { | |
224 | rtx desc; | |
f837a861 MM |
225 | rtx dummy; |
226 | rtx *call_insns; | |
227 | rtx *normal_insns; | |
228 | rtx *insn_ptr; | |
41299f41 | 229 | |
f8b6598e | 230 | progname = "genflags"; |
f837a861 MM |
231 | obstack_init (&call_obstack); |
232 | obstack_init (&normal_obstack); | |
41299f41 TW |
233 | |
234 | if (argc <= 1) | |
235 | fatal ("No input file name."); | |
236 | ||
c88c0d42 CP |
237 | if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE) |
238 | return (FATAL_EXIT_CODE); | |
239 | ||
41299f41 TW |
240 | printf ("/* Generated automatically by the program `genflags'\n\ |
241 | from the machine description file `md'. */\n\n"); | |
242 | ||
243 | /* Read the machine description. */ | |
244 | ||
245 | while (1) | |
246 | { | |
c88c0d42 | 247 | int line_no, insn_code_number = 0; |
41299f41 | 248 | |
c88c0d42 CP |
249 | desc = read_md_rtx (&line_no, &insn_code_number); |
250 | if (desc == NULL) | |
251 | break; | |
41299f41 TW |
252 | if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) |
253 | gen_insn (desc); | |
254 | } | |
255 | ||
f837a861 | 256 | /* Print out the prototypes now. */ |
0f41302f | 257 | dummy = (rtx) 0; |
f837a861 MM |
258 | obstack_grow (&call_obstack, &dummy, sizeof (rtx)); |
259 | call_insns = (rtx *) obstack_finish (&call_obstack); | |
260 | ||
261 | obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); | |
262 | normal_insns = (rtx *) obstack_finish (&normal_obstack); | |
263 | ||
f837a861 MM |
264 | for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) |
265 | gen_proto (*insn_ptr); | |
266 | ||
267 | printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); | |
268 | for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) | |
269 | gen_proto (*insn_ptr); | |
270 | ||
271 | printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); | |
272 | for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) | |
273 | gen_nonproto (*insn_ptr); | |
274 | ||
275 | printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); | |
f837a861 | 276 | |
41299f41 | 277 | fflush (stdout); |
c1b59dce | 278 | return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); |
41299f41 | 279 | } |
a995e389 RH |
280 | |
281 | /* Define this so we can link with print-rtl.o to get debug_rtx function. */ | |
282 | const char * | |
283 | get_insn_name (code) | |
c1b59dce | 284 | int code ATTRIBUTE_UNUSED; |
a995e389 RH |
285 | { |
286 | return NULL; | |
287 | } |