]>
Commit | Line | Data |
---|---|---|
c143ef62 MM |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
30c87b55 MM |
21 | |
22 | ||
c143ef62 MM |
23 | #include <getopt.h> |
24 | ||
25 | #include "misc.h" | |
26 | #include "lf.h" | |
30c87b55 MM |
27 | #include "table.h" |
28 | #include "config.h" | |
c143ef62 | 29 | |
30c87b55 | 30 | #include "filter.h" |
c143ef62 | 31 | |
30c87b55 MM |
32 | #include "ld-decode.h" |
33 | #include "ld-cache.h" | |
34 | #include "ld-insn.h" | |
c143ef62 | 35 | |
30c87b55 | 36 | #include "igen.h" |
c143ef62 | 37 | |
30c87b55 MM |
38 | #include "gen-model.h" |
39 | #include "gen-icache.h" | |
40 | #include "gen-itable.h" | |
41 | #include "gen-idecode.h" | |
42 | #include "gen-semantics.h" | |
43 | #include "gen-support.h" | |
c143ef62 | 44 | |
30c87b55 MM |
45 | int hi_bit_nr; |
46 | int insn_bit_size = max_insn_bit_size; | |
c143ef62 | 47 | |
30c87b55 | 48 | igen_code code = generate_calls; |
c143ef62 | 49 | |
30c87b55 | 50 | int generate_expanded_instructions; |
5c04f4f7 | 51 | int icache_size = 1024; |
30c87b55 | 52 | int generate_smp; |
c143ef62 MM |
53 | |
54 | /****************************************************************/ | |
55 | ||
30c87b55 MM |
56 | static int |
57 | print_insn_bits(lf *file, insn_bits *bits) | |
c143ef62 | 58 | { |
30c87b55 MM |
59 | int nr = 0; |
60 | if (bits == NULL) | |
61 | return nr; | |
62 | nr += print_insn_bits(file, bits->last); | |
63 | nr += lf_putchr(file, '_'); | |
64 | nr += lf_putstr(file, bits->field->val_string); | |
65 | if (bits->opcode->is_boolean && bits->value == 0) | |
66 | nr += lf_putint(file, bits->opcode->boolean_constant); | |
67 | else if (!bits->opcode->is_boolean) { | |
68 | if (bits->opcode->last < bits->field->last) | |
69 | nr += lf_putint(file, bits->value << (bits->field->last - bits->opcode->last)); | |
c143ef62 | 70 | else |
30c87b55 | 71 | nr += lf_putint(file, bits->value); |
c143ef62 | 72 | } |
30c87b55 MM |
73 | return nr; |
74 | } | |
c143ef62 | 75 | |
30c87b55 MM |
76 | extern int |
77 | print_function_name(lf *file, | |
78 | const char *basename, | |
79 | insn_bits *expanded_bits, | |
80 | lf_function_name_prefixes prefix) | |
81 | { | |
82 | int nr = 0; | |
83 | /* the prefix */ | |
84 | switch (prefix) { | |
85 | case function_name_prefix_semantics: | |
86 | nr += lf_putstr(file, "semantic_"); | |
87 | break; | |
88 | case function_name_prefix_idecode: | |
89 | nr += lf_printf(file, "idecode_"); | |
90 | break; | |
91 | case function_name_prefix_itable: | |
92 | nr += lf_putstr(file, "itable_"); | |
93 | break; | |
94 | case function_name_prefix_icache: | |
95 | nr += lf_putstr(file, "icache_"); | |
96 | break; | |
97 | default: | |
98 | break; | |
c143ef62 MM |
99 | } |
100 | ||
30c87b55 MM |
101 | /* the function name */ |
102 | { | |
103 | const char *pos; | |
104 | for (pos = basename; | |
105 | *pos != '\0'; | |
106 | pos++) { | |
107 | switch (*pos) { | |
108 | case '/': | |
109 | case '-': | |
110 | break; | |
111 | case ' ': | |
112 | nr += lf_putchr(file, '_'); | |
113 | break; | |
114 | default: | |
115 | nr += lf_putchr(file, *pos); | |
116 | break; | |
117 | } | |
118 | } | |
8a1d8a0b | 119 | } |
c143ef62 | 120 | |
30c87b55 MM |
121 | /* the suffix */ |
122 | if (generate_expanded_instructions) | |
123 | nr += print_insn_bits(file, expanded_bits); | |
c143ef62 | 124 | |
30c87b55 | 125 | return nr; |
c143ef62 MM |
126 | } |
127 | ||
128 | ||
30c87b55 | 129 | void |
5c04f4f7 MM |
130 | print_my_defines(lf *file, |
131 | insn_bits *expanded_bits, | |
132 | table_entry *file_entry) | |
c143ef62 | 133 | { |
5c04f4f7 | 134 | /* #define MY_INDEX xxxxx */ |
30c87b55 MM |
135 | lf_indent_suppress(file); |
136 | lf_printf(file, "#undef MY_INDEX\n"); | |
137 | lf_indent_suppress(file); | |
138 | lf_printf(file, "#define MY_INDEX "); | |
139 | print_function_name(file, | |
140 | file_entry->fields[insn_name], | |
141 | NULL, | |
142 | function_name_prefix_itable); | |
c143ef62 | 143 | lf_printf(file, "\n"); |
5c04f4f7 MM |
144 | /* #define MY_PREFIX xxxxxx */ |
145 | lf_indent_suppress(file); | |
146 | lf_printf(file, "#undef MY_PREFIX\n"); | |
147 | lf_indent_suppress(file); | |
148 | lf_printf(file, "#define MY_PREFIX "); | |
149 | print_function_name(file, | |
150 | file_entry->fields[insn_name], | |
151 | expanded_bits, | |
152 | function_name_prefix_none); | |
153 | lf_printf(file, "\n"); | |
c143ef62 MM |
154 | } |
155 | ||
c143ef62 | 156 | |
30c87b55 MM |
157 | void |
158 | print_itrace(lf *file, | |
159 | table_entry *file_entry, | |
160 | int idecode) | |
c143ef62 | 161 | { |
30c87b55 MM |
162 | lf_print__external_reference(file, file_entry->line_nr, file_entry->file_name); |
163 | lf_printf(file, "ITRACE(trace_%s, (\"%s %s\\n\"));\n", | |
164 | (idecode ? "idecode" : "semantics"), | |
165 | (idecode ? "idecode" : "semantics"), | |
166 | file_entry->fields[insn_name]); | |
167 | lf_print__internal_reference(file); | |
c143ef62 MM |
168 | } |
169 | ||
170 | ||
a3114052 MM |
171 | /****************************************************************/ |
172 | ||
1dc7c0ed MM |
173 | |
174 | static void | |
30c87b55 MM |
175 | gen_semantics_h(insn_table *table, |
176 | lf *file, | |
177 | igen_code generate) | |
a3114052 | 178 | { |
30c87b55 MM |
179 | lf_printf(file, "typedef %s idecode_semantic\n(%s);\n", |
180 | SEMANTIC_FUNCTION_TYPE, | |
181 | SEMANTIC_FUNCTION_FORMAL); | |
80948f39 | 182 | lf_printf(file, "\n"); |
30c87b55 MM |
183 | if ((code & generate_calls)) { |
184 | if (generate_expanded_instructions) | |
185 | insn_table_traverse_tree(table, | |
186 | file, NULL, | |
187 | 1, | |
188 | NULL, /* start */ | |
189 | print_semantic_declaration, /* leaf */ | |
190 | NULL, /* end */ | |
191 | NULL); /* padding */ | |
192 | else | |
193 | insn_table_traverse_insn(table, | |
194 | file, NULL, | |
195 | print_semantic_declaration); | |
196 | ||
80948f39 | 197 | } |
30c87b55 MM |
198 | else { |
199 | lf_print__this_file_is_empty(file); | |
80948f39 | 200 | } |
30c87b55 | 201 | } |
80948f39 | 202 | |
eb4ef197 | 203 | |
30c87b55 MM |
204 | static void |
205 | gen_semantics_c(insn_table *table, | |
206 | cache_table *cache_rules, | |
207 | lf *file, | |
208 | igen_code generate) | |
209 | { | |
210 | if ((code & generate_calls)) { | |
80948f39 | 211 | lf_printf(file, "\n"); |
30c87b55 MM |
212 | lf_printf(file, "#include \"cpu.h\"\n"); |
213 | lf_printf(file, "#include \"idecode.h\"\n"); | |
214 | lf_printf(file, "#include \"semantics.h\"\n"); | |
215 | lf_printf(file, "#include \"support.h\"\n"); | |
80948f39 | 216 | lf_printf(file, "\n"); |
30c87b55 MM |
217 | if (generate_expanded_instructions) |
218 | insn_table_traverse_tree(table, | |
219 | file, cache_rules, | |
220 | 1, | |
221 | NULL, /* start */ | |
222 | print_semantic_definition, /* leaf */ | |
223 | NULL, /* end */ | |
224 | NULL); /* padding */ | |
225 | else | |
226 | insn_table_traverse_insn(table, | |
227 | file, cache_rules, | |
228 | print_semantic_definition); | |
229 | ||
80948f39 | 230 | } |
30c87b55 MM |
231 | else { |
232 | lf_print__this_file_is_empty(file); | |
80948f39 | 233 | } |
a3114052 MM |
234 | } |
235 | ||
a3114052 | 236 | |
30c87b55 | 237 | /****************************************************************/ |
a3114052 | 238 | |
a3114052 | 239 | |
eb4ef197 | 240 | static void |
30c87b55 MM |
241 | gen_icache_h(insn_table *table, |
242 | lf *file, | |
243 | igen_code generate) | |
eb4ef197 | 244 | { |
30c87b55 MM |
245 | lf_printf(file, "typedef %s idecode_icache\n(%s);\n", |
246 | ICACHE_FUNCTION_TYPE, | |
247 | ICACHE_FUNCTION_FORMAL); | |
248 | lf_printf(file, "\n"); | |
249 | if ((code & generate_calls) | |
250 | && (code & generate_with_icache)) { | |
251 | insn_table_traverse_function(table, | |
252 | file, NULL, | |
253 | print_icache_internal_function_declaration); | |
254 | if (generate_expanded_instructions) | |
255 | insn_table_traverse_tree(table, | |
256 | file, NULL, | |
257 | 1, | |
258 | NULL, /* start */ | |
259 | print_icache_declaration, /* leaf */ | |
260 | NULL, /* end */ | |
261 | NULL); /* padding */ | |
262 | else | |
263 | insn_table_traverse_insn(table, | |
264 | file, NULL, | |
265 | print_icache_declaration); | |
266 | ||
eb4ef197 MM |
267 | } |
268 | else { | |
30c87b55 | 269 | lf_print__this_file_is_empty(file); |
eb4ef197 | 270 | } |
eb4ef197 MM |
271 | } |
272 | ||
30c87b55 MM |
273 | static void |
274 | gen_icache_c(insn_table *table, | |
275 | cache_table *cache_rules, | |
276 | lf *file, | |
277 | igen_code generate) | |
a3114052 | 278 | { |
30c87b55 MM |
279 | /* output `internal' invalid/floating-point unavailable functions |
280 | where needed */ | |
281 | if ((code & generate_calls) | |
282 | && (code & generate_with_icache)) { | |
80948f39 | 283 | lf_printf(file, "\n"); |
30c87b55 MM |
284 | lf_printf(file, "#include \"cpu.h\"\n"); |
285 | lf_printf(file, "#include \"idecode.h\"\n"); | |
286 | lf_printf(file, "#include \"semantics.h\"\n"); | |
287 | lf_printf(file, "#include \"icache.h\"\n"); | |
288 | lf_printf(file, "#include \"support.h\"\n"); | |
80948f39 | 289 | lf_printf(file, "\n"); |
30c87b55 MM |
290 | insn_table_traverse_function(table, |
291 | file, NULL, | |
292 | print_icache_internal_function_definition); | |
845ff5a4 | 293 | lf_printf(file, "\n"); |
30c87b55 MM |
294 | if (generate_expanded_instructions) |
295 | insn_table_traverse_tree(table, | |
296 | file, cache_rules, | |
297 | 1, | |
298 | NULL, /* start */ | |
299 | print_icache_definition, /* leaf */ | |
300 | NULL, /* end */ | |
301 | NULL); /* padding */ | |
302 | else | |
303 | insn_table_traverse_insn(table, | |
304 | file, cache_rules, | |
305 | print_icache_definition); | |
306 | ||
80948f39 | 307 | } |
30c87b55 MM |
308 | else { |
309 | lf_print__this_file_is_empty(file); | |
28816f45 | 310 | } |
c143ef62 MM |
311 | } |
312 | ||
30c87b55 | 313 | |
c143ef62 MM |
314 | /****************************************************************/ |
315 | ||
316 | ||
317 | int | |
318 | main(int argc, | |
319 | char **argv, | |
320 | char **envp) | |
321 | { | |
30c87b55 MM |
322 | cache_table *cache_rules = NULL; |
323 | lf_file_references file_references = lf_include_references; | |
324 | decode_table *decode_rules = NULL; | |
325 | filter *filters = NULL; | |
c143ef62 | 326 | insn_table *instructions = NULL; |
c143ef62 | 327 | char *real_file_name = NULL; |
30c87b55 | 328 | int is_header = 0; |
c143ef62 MM |
329 | int ch; |
330 | ||
331 | if (argc == 1) { | |
332 | printf("Usage:\n"); | |
a983c8f0 MM |
333 | printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n"); |
334 | printf("Config options:\n"); | |
30c87b55 | 335 | printf(" -F <filter-out-flag> eg -F 64 to skip 64bit instructions\n"); |
30c87b55 MM |
336 | printf(" -E Expand (duplicate) semantic functions\n"); |
337 | printf(" -I <icache-size> Generate cracking cache version\n"); | |
5c04f4f7 MM |
338 | printf(" -C Include semantics in cache functions\n"); |
339 | printf(" -S Include insn (instruction) in icache\n"); | |
f2181eff | 340 | printf(" -R Use defines to reference cache vars\n"); |
30c87b55 MM |
341 | printf(" -L Supress line numbering in output files\n"); |
342 | printf(" -B <bit-size> Set the number of bits in an instruction\n"); | |
343 | printf(" -H <high-bit> Set the nr of the high (msb bit)\n"); | |
344 | printf(" -N <nr-cpus> Specify the max number of cpus the simulation will support\n"); | |
345 | printf(" -J Use jumps instead of function calls\n"); | |
f2181eff | 346 | printf("\n"); |
a983c8f0 | 347 | printf("Input options (ucase version also dumps loaded table):\n"); |
30c87b55 MM |
348 | printf(" -o <opcode-rules>\n"); |
349 | printf(" -k <cache-rules>\n"); | |
350 | printf(" -i <instruction-table>\n"); | |
f2181eff | 351 | printf("\n"); |
a983c8f0 | 352 | printf("Output options:\n"); |
30c87b55 MM |
353 | printf(" -n <real-name> Specify the real name of for the next output file\n"); |
354 | printf(" -h Generate header file\n"); | |
355 | printf(" -c <output-file> output icache\n"); | |
356 | printf(" -d <output-file> output idecode\n"); | |
357 | printf(" -m <output-file> output model\n"); | |
358 | printf(" -s <output-file> output schematic\n"); | |
359 | printf(" -t <output-file> output itable\n"); | |
360 | printf(" -f <output-file> output support functions\n"); | |
c143ef62 MM |
361 | } |
362 | ||
363 | while ((ch = getopt(argc, argv, | |
5c04f4f7 | 364 | "F:EI:RSLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:")) |
30c87b55 | 365 | != -1) { |
c143ef62 MM |
366 | fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : "")); |
367 | switch(ch) { | |
30c87b55 MM |
368 | case 'C': |
369 | code |= generate_with_icache; | |
370 | code |= generate_with_semantic_icache; | |
5c04f4f7 MM |
371 | break; |
372 | case 'S': | |
373 | code |= generate_with_icache; | |
374 | code |= generate_with_insn_in_icache; | |
30c87b55 MM |
375 | break; |
376 | case 'L': | |
377 | file_references = lf_omit_references; | |
378 | break; | |
379 | case 'E': | |
380 | generate_expanded_instructions = 1; | |
c143ef62 | 381 | break; |
30c87b55 MM |
382 | case 'I': |
383 | icache_size = a2i(optarg); | |
384 | code |= generate_with_icache; | |
c143ef62 | 385 | break; |
30c87b55 MM |
386 | case 'N': |
387 | generate_smp = a2i(optarg); | |
c143ef62 | 388 | break; |
f2181eff | 389 | case 'R': |
5c04f4f7 | 390 | code |= generate_with_direct_access; |
f2181eff | 391 | break; |
30c87b55 MM |
392 | case 'B': |
393 | insn_bit_size = a2i(optarg); | |
394 | ASSERT(insn_bit_size > 0 && insn_bit_size <= max_insn_bit_size | |
395 | && (hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0)); | |
a983c8f0 | 396 | break; |
30c87b55 | 397 | case 'H': |
a983c8f0 | 398 | hi_bit_nr = a2i(optarg); |
30c87b55 MM |
399 | ASSERT(hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0); |
400 | break; | |
401 | case 'F': | |
402 | filters = new_filter(optarg, filters); | |
403 | break; | |
404 | case 'J': | |
405 | code &= ~generate_calls; | |
406 | code |= generate_jumps; | |
a983c8f0 | 407 | break; |
c143ef62 | 408 | case 'i': |
30c87b55 MM |
409 | if (decode_rules == NULL || cache_rules == NULL) { |
410 | fprintf(stderr, "Must specify decode and cache tables\n"); | |
411 | exit (1); | |
412 | } | |
413 | instructions = load_insn_table(optarg, decode_rules, filters); | |
c143ef62 MM |
414 | fprintf(stderr, "\texpanding ...\n"); |
415 | insn_table_expand_insns(instructions); | |
c143ef62 | 416 | break; |
c143ef62 | 417 | case 'o': |
30c87b55 | 418 | decode_rules = load_decode_table(optarg, hi_bit_nr); |
c143ef62 | 419 | break; |
c143ef62 | 420 | case 'k': |
30c87b55 | 421 | cache_rules = load_cache_table(optarg, hi_bit_nr); |
c143ef62 MM |
422 | break; |
423 | case 'n': | |
424 | real_file_name = strdup(optarg); | |
425 | break; | |
30c87b55 MM |
426 | case 'h': |
427 | is_header = 1; | |
428 | break; | |
c143ef62 | 429 | case 's': |
c143ef62 | 430 | case 'd': |
a3114052 | 431 | case 'm': |
c143ef62 | 432 | case 't': |
30c87b55 MM |
433 | case 'f': |
434 | case 'c': | |
c143ef62 | 435 | { |
30c87b55 MM |
436 | lf *file = lf_open(optarg, real_file_name, file_references, |
437 | (is_header ? lf_is_h : lf_is_c), | |
438 | argv[0]); | |
439 | lf_print__file_start(file); | |
c143ef62 MM |
440 | ASSERT(instructions != NULL); |
441 | switch (ch) { | |
c143ef62 | 442 | case 's': |
30c87b55 MM |
443 | if(is_header) |
444 | gen_semantics_h(instructions, file, code); | |
445 | else | |
446 | gen_semantics_c(instructions, cache_rules, file, code); | |
c143ef62 MM |
447 | break; |
448 | case 'd': | |
30c87b55 MM |
449 | if (is_header) |
450 | gen_idecode_h(file, instructions, cache_rules); | |
451 | else | |
452 | gen_idecode_c(file, instructions, cache_rules); | |
a3114052 MM |
453 | break; |
454 | case 'm': | |
30c87b55 MM |
455 | if (is_header) |
456 | gen_model_h(instructions, file); | |
457 | else | |
458 | gen_model_c(instructions, file); | |
c143ef62 MM |
459 | break; |
460 | case 't': | |
30c87b55 MM |
461 | if (is_header) |
462 | gen_itable_h(instructions, file); | |
463 | else | |
464 | gen_itable_c(instructions, file); | |
465 | break; | |
466 | case 'f': | |
467 | if (is_header) | |
468 | gen_support_h(instructions, file); | |
469 | else | |
470 | gen_support_c(instructions, file); | |
c143ef62 | 471 | break; |
30c87b55 MM |
472 | case 'c': |
473 | if (is_header) | |
474 | gen_icache_h(instructions, file, code); | |
475 | else | |
476 | gen_icache_c(instructions, cache_rules, file, code); | |
c143ef62 MM |
477 | break; |
478 | } | |
30c87b55 | 479 | lf_print__file_finish(file); |
c143ef62 | 480 | lf_close(file); |
30c87b55 | 481 | is_header = 0; |
c143ef62 MM |
482 | } |
483 | real_file_name = NULL; | |
484 | break; | |
485 | default: | |
486 | error("unknown option\n"); | |
487 | } | |
488 | } | |
489 | return 0; | |
490 | } |