1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2024 Free Software Foundation, Inc.
4 
5    Contributed by Andrew Cagney.
6 
7    This file is part of GDB.
8 
9    This program 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 3 of the License, or
12    (at your option) any later version.
13 
14    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include <getopt.h>
23 #include <stdlib.h>
24 
25 #include "misc.h"
26 #include "lf.h"
27 #include "table.h"
28 #include "filter.h"
29 
30 #include "igen.h"
31 
32 #include "ld-insn.h"
33 #include "ld-decode.h"
34 #include "ld-cache.h"
35 
36 #include "gen.h"
37 
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-engine.h"
44 #include "gen-support.h"
45 #include "gen-engine.h"
46 
47 
48 /****************************************************************/
49 
50 
51 /* Semantic functions */
52 
53 int
print_semantic_function_formal(lf * file,int nr_prefetched_words)54 print_semantic_function_formal (lf *file, int nr_prefetched_words)
55 {
56   int nr = 0;
57   int word_nr;
58   if (options.gen.icache || nr_prefetched_words < 0)
59     {
60       nr += lf_printf (file, "SIM_DESC sd,\n");
61       nr += lf_printf (file, "%sidecode_cache *cache_entry,\n",
62                            options.module.global.prefix.l);
63       nr += lf_printf (file, "%sinstruction_address cia",
64                            options.module.global.prefix.l);
65     }
66   else if (options.gen.smp)
67     {
68       nr += lf_printf (file, "sim_cpu *cpu,\n");
69       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
70           {
71             nr += lf_printf (file, "%sinstruction_word instruction_%d,\n",
72                                  options.module.global.prefix.l, word_nr);
73           }
74       nr += lf_printf (file, "%sinstruction_address cia",
75                            options.module.global.prefix.l);
76     }
77   else
78     {
79       nr += lf_printf (file, "SIM_DESC sd,\n");
80       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
81           {
82             nr += lf_printf (file, "%sinstruction_word instruction_%d,\n",
83                                  options.module.global.prefix.l, word_nr);
84           }
85       nr += lf_printf (file, "%sinstruction_address cia",
86                            options.module.global.prefix.l);
87     }
88   return nr;
89 }
90 
91 int
print_semantic_function_actual(lf * file,int nr_prefetched_words)92 print_semantic_function_actual (lf *file, int nr_prefetched_words)
93 {
94   int nr = 0;
95   int word_nr;
96   if (options.gen.icache || nr_prefetched_words < 0)
97     {
98       nr += lf_printf (file, "sd, cache_entry, cia");
99     }
100   else
101     {
102       if (options.gen.smp)
103           nr += lf_printf (file, "cpu");
104       else
105           nr += lf_printf (file, "sd");
106       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
107           nr += lf_printf (file, ", instruction_%d", word_nr);
108       nr += lf_printf (file, ", cia");
109     }
110   return nr;
111 }
112 
113 int
print_semantic_function_type(lf * file)114 print_semantic_function_type (lf *file)
115 {
116   int nr = 0;
117   nr += lf_printf (file, "%sinstruction_address",
118                        options.module.global.prefix.l);
119   return nr;
120 }
121 
122 
123 /* Idecode functions */
124 
125 int
print_icache_function_formal(lf * file,int nr_prefetched_words)126 print_icache_function_formal (lf *file, int nr_prefetched_words)
127 {
128   int nr = 0;
129   int word_nr;
130   if (options.gen.smp)
131     nr += lf_printf (file, "sim_cpu *cpu,\n");
132   else
133     nr += lf_printf (file, "SIM_DESC sd,\n");
134   for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
135     nr += lf_printf (file, " %sinstruction_word instruction_%d,\n",
136                          options.module.global.prefix.l, word_nr);
137   nr += lf_printf (file, " %sinstruction_address cia,\n",
138                        options.module.global.prefix.l);
139   nr += lf_printf (file, " %sidecode_cache *cache_entry",
140                        options.module.global.prefix.l);
141   return nr;
142 }
143 
144 int
print_icache_function_actual(lf * file,int nr_prefetched_words)145 print_icache_function_actual (lf *file, int nr_prefetched_words)
146 {
147   int nr = 0;
148   int word_nr;
149   if (options.gen.smp)
150     nr += lf_printf (file, "cpu");
151   else
152     nr += lf_printf (file, "sd");
153   for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
154     nr += lf_printf (file, ", instruction_%d", word_nr);
155   nr += lf_printf (file, ", cia, cache_entry");
156   return nr;
157 }
158 
159 int
print_icache_function_type(lf * file)160 print_icache_function_type (lf *file)
161 {
162   int nr;
163   if (options.gen.semantic_icache)
164     {
165       nr = print_semantic_function_type (file);
166     }
167   else
168     {
169       nr = lf_printf (file, "%sidecode_semantic *",
170                           options.module.global.prefix.l);
171     }
172   return nr;
173 }
174 
175 
176 /* Function names */
177 
178 static int
print_opcode_bits(lf * file,const opcode_bits * bits)179 print_opcode_bits (lf *file, const opcode_bits *bits)
180 {
181   int nr = 0;
182   if (bits == NULL)
183     return nr;
184   nr += lf_putchr (file, '_');
185   nr += lf_putstr (file, bits->field->val_string);
186   if (bits->opcode->is_boolean && bits->value == 0)
187     nr += lf_putint (file, bits->opcode->boolean_constant);
188   else if (!bits->opcode->is_boolean)
189     {
190       if (bits->opcode->last < bits->field->last)
191           nr +=
192             lf_putint (file,
193                          bits->value << (bits->field->last - bits->opcode->last));
194       else
195           nr += lf_putint (file, bits->value);
196     }
197   nr += print_opcode_bits (file, bits->next);
198   return nr;
199 }
200 
201 static int
print_c_name(lf * file,const char * name)202 print_c_name (lf *file, const char *name)
203 {
204   int nr = 0;
205   const char *pos;
206   for (pos = name; *pos != '\0'; pos++)
207     {
208       switch (*pos)
209           {
210           case '/':
211           case '-':
212             break;
213           case ' ':
214           case '.':
215             nr += lf_putchr (file, '_');
216             break;
217           default:
218             nr += lf_putchr (file, *pos);
219             break;
220           }
221     }
222   return nr;
223 }
224 
225 extern int
print_function_name(lf * file,const char * basename,const char * format_name,const char * model_name,const opcode_bits * expanded_bits,lf_function_name_prefixes prefix)226 print_function_name (lf *file,
227                          const char *basename,
228                          const char *format_name,
229                          const char *model_name,
230                          const opcode_bits *expanded_bits,
231                          lf_function_name_prefixes prefix)
232 {
233   int nr = 0;
234   /* the prefix */
235   switch (prefix)
236     {
237     case function_name_prefix_semantics:
238       nr += lf_printf (file, "%s", options.module.semantics.prefix.l);
239       nr += lf_printf (file, "semantic_");
240       break;
241     case function_name_prefix_idecode:
242       nr += lf_printf (file, "%s", options.module.idecode.prefix.l);
243       nr += lf_printf (file, "idecode_");
244       break;
245     case function_name_prefix_itable:
246       nr += lf_printf (file, "%sitable_", options.module.itable.prefix.l);
247       break;
248     case function_name_prefix_icache:
249       nr += lf_printf (file, "%s", options.module.icache.prefix.l);
250       nr += lf_printf (file, "icache_");
251       break;
252     case function_name_prefix_engine:
253       nr += lf_printf (file, "%s", options.module.engine.prefix.l);
254       nr += lf_printf (file, "engine_");
255     default:
256       break;
257     }
258 
259   if (model_name != NULL)
260     {
261       nr += print_c_name (file, model_name);
262       nr += lf_printf (file, "_");
263     }
264 
265   /* the function name */
266   nr += print_c_name (file, basename);
267 
268   /* the format name if available */
269   if (format_name != NULL)
270     {
271       nr += lf_printf (file, "_");
272       nr += print_c_name (file, format_name);
273     }
274 
275   /* the suffix */
276   nr += print_opcode_bits (file, expanded_bits);
277 
278   return nr;
279 }
280 
281 
282 void
print_my_defines(lf * file,const char * basename,const char * format_name,const opcode_bits * expanded_bits)283 print_my_defines (lf *file,
284                       const char *basename,
285                       const char *format_name,
286                       const opcode_bits *expanded_bits)
287 {
288   /* #define MY_INDEX xxxxx */
289   lf_indent_suppress (file);
290   lf_printf (file, "#undef MY_INDEX\n");
291   lf_indent_suppress (file);
292   lf_printf (file, "#define MY_INDEX ");
293   print_function_name (file,
294                            basename, format_name, NULL,
295                            NULL, function_name_prefix_itable);
296   lf_printf (file, "\n");
297   /* #define MY_PREFIX xxxxxx */
298   lf_indent_suppress (file);
299   lf_printf (file, "#undef ");
300   print_function_name (file,
301                            basename, format_name, NULL,
302                            expanded_bits, function_name_prefix_none);
303   lf_printf (file, "\n");
304   lf_indent_suppress (file);
305   lf_printf (file, "#undef MY_PREFIX\n");
306   lf_indent_suppress (file);
307   lf_printf (file, "#define MY_PREFIX ");
308   print_function_name (file,
309                            basename, format_name, NULL,
310                            expanded_bits, function_name_prefix_none);
311   lf_printf (file, "\n");
312   /* #define MY_NAME xxxxxx */
313   lf_indent_suppress (file);
314   lf_indent_suppress (file);
315   lf_printf (file, "#undef MY_NAME\n");
316   lf_indent_suppress (file);
317   lf_printf (file, "#define MY_NAME \"");
318   print_function_name (file,
319                            basename, format_name, NULL,
320                            expanded_bits, function_name_prefix_none);
321   lf_printf (file, "\"\n");
322 }
323 
324 
325 static int
print_itrace_prefix(lf * file)326 print_itrace_prefix (lf *file)
327 {
328   const char *prefix = "trace_prefix (";
329   int indent = strlen (prefix);
330   lf_printf (file, "%sSD, CPU, cia, CIA, TRACE_LINENUM_P (CPU), \\\n",
331                prefix);
332   lf_indent (file, +indent);
333   lf_printf (file, "%sitable[MY_INDEX].file, \\\n",
334                options.module.itable.prefix.l);
335   lf_printf (file, "%sitable[MY_INDEX].line_nr, \\\n",
336                options.module.itable.prefix.l);
337   lf_printf (file, "\"");
338   return indent;
339 }
340 
341 
342 static void
print_itrace_format(lf * file,const insn_mnemonic_entry * assembler)343 print_itrace_format (lf *file, const insn_mnemonic_entry *assembler)
344 {
345   /* pass=1 is fmt string; pass=2 is arguments */
346   int pass;
347   /* print the format string */
348   for (pass = 1; pass <= 2; pass++)
349     {
350       const char *chp = assembler->format;
351       chp++;                            /* skip the leading quote */
352       /* write out the format/args */
353       while (*chp != '\0')
354           {
355             if (chp[0] == '\\' && (chp[1] == '<' || chp[1] == '>'))
356               {
357                 if (pass == 1)
358                     lf_putchr (file, chp[1]);
359                 chp += 2;
360               }
361             else if (chp[0] == '<' || chp[0] == '%')
362               {
363                 /* parse [ "%" ... ] "<" [ func "#" ] param ">" */
364                 const char *fmt;
365                 const char *func;
366                 int strlen_func;
367                 const char *param;
368                 int strlen_param;
369                 /* the "%" ... "<" format */
370                 fmt = chp;
371                 while (chp[0] != '<' && chp[0] != '\0')
372                     chp++;
373                 if (chp[0] != '<')
374                     error (assembler->line, "Missing `<' after `%%'\n");
375                 chp++;
376                 /* [ "func" # ] OR "param" */
377                 func = chp;
378                 param = chp;
379                 while (chp[0] != '>' && chp[0] != '#' && chp[0] != '\0')
380                     chp++;
381                 strlen_func = chp - func;
382                 if (chp[0] == '#')
383                     {
384                       chp++;
385                       param = chp;
386                       while (chp[0] != '>' && chp[0] != '\0')
387                         chp++;
388                     }
389                 strlen_param = chp - param;
390                 if (chp[0] != '>')
391                     error (assembler->line,
392                            "Missing closing `>' in assembler string\n");
393                 chp++;
394                 /* now process it */
395                 if (pass == 2)
396                     lf_printf (file, ", \\\n");
397                 if (strncmp (fmt, "<", 1) == 0)
398                     /* implicit long int format */
399                     {
400                       if (pass == 1)
401                         lf_printf (file, "%%ld");
402                       else
403                         {
404                           lf_printf (file, "(long) ");
405                           lf_write (file, param, strlen_param);
406                         }
407                     }
408                 else if (strncmp (fmt, "%<", 2) == 0)
409                     /* explicit format */
410                     {
411                       if (pass == 1)
412                         lf_printf (file, "%%");
413                       else
414                         lf_write (file, param, strlen_param);
415                     }
416                 else if (strncmp (fmt, "%s<", 3) == 0)
417                     /* string format */
418                     {
419                       if (pass == 1)
420                         lf_printf (file, "%%s");
421                       else
422                         {
423                           lf_printf (file, "%sstr_",
424                                          options.module.global.prefix.l);
425                           lf_write (file, func, strlen_func);
426                           lf_printf (file, " (SD_, ");
427                           lf_write (file, param, strlen_param);
428                           lf_printf (file, ")");
429                         }
430                     }
431                 else if (strncmp (fmt, "%lx<", 4) == 0)
432                     /* simple hex */
433                     {
434                       if (pass == 1)
435                         lf_printf (file, "%%lx");
436                       else
437                         {
438                           lf_printf (file, "(unsigned long) ");
439                           lf_write (file, param, strlen_param);
440                         }
441                     }
442                 else if (strncmp (fmt, "%#lx<", 5) == 0)
443                     /* simple hex with 0x prefix */
444                     {
445                       if (pass == 1)
446                         lf_printf (file, "%%#lx");
447                       else
448                         {
449                           lf_printf (file, "(unsigned long) ");
450                           lf_write (file, param, strlen_param);
451                         }
452                     }
453                 else if (strncmp (fmt, "%08lx<", 6) == 0)
454                     /* simple hex */
455                     {
456                       if (pass == 1)
457                         lf_printf (file, "%%08lx");
458                       else
459                         {
460                           lf_printf (file, "(unsigned long) ");
461                           lf_write (file, param, strlen_param);
462                         }
463                     }
464                 else
465                     error (assembler->line, "Unknown assembler string format\n");
466               }
467             else
468               {
469                 if (pass == 1)
470                     lf_putchr (file, chp[0]);
471                 chp += 1;
472               }
473           }
474     }
475   lf_printf (file, ");\n");
476 }
477 
478 
479 void
print_itrace(lf * file,const insn_entry * insn,int idecode)480 print_itrace (lf *file, const insn_entry *insn, int idecode)
481 {
482   /* NB: Here we escape each EOLN. This is so that the the compiler
483      treats a trace function call as a single line.  Consequently any
484      errors in the line are refered back to the same igen assembler
485      source line */
486   const char *phase = (idecode) ? "DECODE" : "INSN";
487   lf_printf (file, "\n");
488   lf_indent_suppress (file);
489   lf_printf (file, "#if defined (WITH_TRACE)\n");
490   lf_printf (file, "/* generate a trace prefix if any tracing enabled */\n");
491   lf_printf (file, "if (TRACE_ANY_P (CPU))\n");
492   lf_printf (file, "  {\n");
493   lf_indent (file, +4);
494   {
495     if (insn->mnemonics != NULL)
496       {
497           insn_mnemonic_entry *assembler = insn->mnemonics;
498           int is_first = 1;
499           do
500             {
501               if (assembler->condition != NULL)
502                 {
503                     int indent;
504                     lf_printf (file, "%sif (%s)\n",
505                                  is_first ? "" : "else ", assembler->condition);
506                     lf_indent (file, +2);
507                     lf_print__line_ref (file, assembler->line);
508                     indent = print_itrace_prefix (file);
509                     print_itrace_format (file, assembler);
510                     lf_print__internal_ref (file);
511                     lf_indent (file, -indent);
512                     lf_indent (file, -2);
513                     if (assembler->next == NULL)
514                       error (assembler->line,
515                                "Missing final unconditional assembler\n");
516                 }
517               else
518                 {
519                     int indent;
520                     if (!is_first)
521                       {
522                         lf_printf (file, "else\n");
523                         lf_indent (file, +2);
524                       }
525                     lf_print__line_ref (file, assembler->line);
526                     indent = print_itrace_prefix (file);
527                     print_itrace_format (file, assembler);
528                     lf_print__internal_ref (file);
529                     lf_indent (file, -indent);
530                     if (!is_first)
531                       lf_indent (file, -2);
532                     if (assembler->next != NULL)
533                       error (assembler->line,
534                                "Unconditional assembler is not last\n");
535                 }
536               is_first = 0;
537               assembler = assembler->next;
538             }
539           while (assembler != NULL);
540       }
541     else
542       {
543           int indent;
544           lf_indent (file, +2);
545           lf_print__line_ref (file, insn->line);
546           indent = print_itrace_prefix (file);
547           lf_printf (file, "%%s\", \\\n");
548           lf_printf (file, "itable[MY_INDEX].name);\n");
549           lf_print__internal_ref (file);
550           lf_indent (file, -indent);
551           lf_indent (file, -2);
552       }
553     lf_printf (file, "/* trace the instruction execution if enabled */\n");
554     lf_printf (file, "if (TRACE_%s_P (CPU))\n", phase);
555     lf_printf (file,
556                  "  trace_generic (SD, CPU, TRACE_%s_IDX, \" %%s\", itable[MY_INDEX].name);\n",
557                  phase);
558   }
559   lf_indent (file, -4);
560   lf_printf (file, "  }\n");
561   lf_indent_suppress (file);
562   lf_printf (file, "#endif\n");
563 }
564 
565 
566 void
print_sim_engine_abort(lf * file,const char * message)567 print_sim_engine_abort (lf *file, const char *message)
568 {
569   lf_printf (file, "sim_engine_abort (SD, CPU, cia, ");
570   lf_printf (file, "\"%s\"", message);
571   lf_printf (file, ");\n");
572 }
573 
574 
575 void
print_include(lf * file,igen_module module)576 print_include (lf *file, igen_module module)
577 {
578   lf_printf (file, "#include \"%s%s.h\"\n", module.prefix.l, module.suffix.l);
579 }
580 
581 void
print_include_inline(lf * file,igen_module module)582 print_include_inline (lf *file, igen_module module)
583 {
584   lf_printf (file, "#if C_REVEALS_MODULE_P (%s_INLINE)\n", module.suffix.u);
585   lf_printf (file, "#include \"%s%s.c\"\n", module.prefix.l, module.suffix.l);
586   lf_printf (file, "#else\n");
587   print_include (file, module);
588   lf_printf (file, "#endif\n");
589   lf_printf (file, "\n");
590 }
591 
592 void
print_includes(lf * file)593 print_includes (lf *file)
594 {
595   lf_printf (file, "\n");
596   lf_printf (file, "#include \"sim-inline.c\"\n");
597   lf_printf (file, "\n");
598   print_include_inline (file, options.module.itable);
599   print_include_inline (file, options.module.idecode);
600   print_include_inline (file, options.module.support);
601 }
602 
603 
604 /****************************************************************/
605 
606 
607 static void
gen_semantics_h(lf * file,const insn_list * semantics,int max_nr_words)608 gen_semantics_h (lf *file, const insn_list *semantics, int max_nr_words)
609 {
610   int word_nr;
611   const insn_list *semantic;
612   for (word_nr = -1; word_nr <= max_nr_words; word_nr++)
613     {
614       lf_printf (file, "typedef ");
615       print_semantic_function_type (file);
616       lf_printf (file, " %sidecode_semantic", options.module.global.prefix.l);
617       if (word_nr >= 0)
618           lf_printf (file, "_%d", word_nr);
619       lf_printf (file, "\n(");
620       lf_indent (file, +1);
621       print_semantic_function_formal (file, word_nr);
622       lf_indent (file, -1);
623       lf_printf (file, ");\n");
624       lf_printf (file, "\n");
625     }
626   switch (options.gen.code)
627     {
628     case generate_calls:
629       for (semantic = semantics; semantic != NULL; semantic = semantic->next)
630           {
631             /* Ignore any special/internal instructions */
632             if (semantic->insn->nr_words == 0)
633               continue;
634             print_semantic_declaration (file,
635                                               semantic->insn,
636                                               semantic->expanded_bits,
637                                               semantic->opcodes,
638                                               semantic->nr_prefetched_words);
639           }
640       break;
641     case generate_jumps:
642       lf_print__this_file_is_empty (file, "generating jumps");
643       break;
644     }
645 }
646 
647 
648 static void
gen_semantics_c(lf * file,const insn_list * semantics,cache_entry * cache_rules)649 gen_semantics_c (lf *file, const insn_list *semantics, cache_entry *cache_rules)
650 {
651   if (options.gen.code == generate_calls)
652     {
653       const insn_list *semantic;
654       print_includes (file);
655       print_include (file, options.module.semantics);
656       lf_printf (file, "\n");
657 
658       for (semantic = semantics; semantic != NULL; semantic = semantic->next)
659           {
660             /* Ignore any special/internal instructions */
661             if (semantic->insn->nr_words == 0)
662               continue;
663             print_semantic_definition (file,
664                                              semantic->insn,
665                                              semantic->expanded_bits,
666                                              semantic->opcodes,
667                                              cache_rules,
668                                              semantic->nr_prefetched_words);
669           }
670     }
671   else
672     {
673       lf_print__this_file_is_empty (file, "generating jump engine");
674     }
675 }
676 
677 
678 /****************************************************************/
679 
680 
681 static void
gen_icache_h(lf * file,const insn_list * semantic,const function_entry * functions,int max_nr_words)682 gen_icache_h (lf *file,
683                 const insn_list *semantic,
684                 const function_entry *functions, int max_nr_words)
685 {
686   int word_nr;
687   for (word_nr = 0; word_nr <= max_nr_words; word_nr++)
688     {
689       lf_printf (file, "typedef ");
690       print_icache_function_type (file);
691       lf_printf (file, " %sidecode_icache_%d\n(",
692                      options.module.global.prefix.l, word_nr);
693       print_icache_function_formal (file, word_nr);
694       lf_printf (file, ");\n");
695       lf_printf (file, "\n");
696     }
697   if (options.gen.code == generate_calls && options.gen.icache)
698     {
699       function_entry_traverse (file, functions,
700                                      print_icache_internal_function_declaration,
701                                      NULL);
702       while (semantic != NULL)
703           {
704             print_icache_declaration (file,
705                                             semantic->insn,
706                                             semantic->expanded_bits,
707                                             semantic->opcodes,
708                                             semantic->nr_prefetched_words);
709             semantic = semantic->next;
710           }
711     }
712   else
713     {
714       lf_print__this_file_is_empty (file, "generating jump engine");
715     }
716 }
717 
718 static void
gen_icache_c(lf * file,const insn_list * semantic,const function_entry * functions,cache_entry * cache_rules)719 gen_icache_c (lf *file,
720                 const insn_list *semantic,
721                 const function_entry *functions, cache_entry *cache_rules)
722 {
723   /* output `internal' invalid/floating-point unavailable functions
724      where needed */
725   if (options.gen.code == generate_calls && options.gen.icache)
726     {
727       lf_printf (file, "\n");
728       lf_printf (file, "#include \"cpu.h\"\n");
729       lf_printf (file, "#include \"idecode.h\"\n");
730       lf_printf (file, "#include \"semantics.h\"\n");
731       lf_printf (file, "#include \"icache.h\"\n");
732       lf_printf (file, "#include \"support.h\"\n");
733       lf_printf (file, "\n");
734       function_entry_traverse (file, functions,
735                                      print_icache_internal_function_definition,
736                                      NULL);
737       lf_printf (file, "\n");
738       while (semantic != NULL)
739           {
740             print_icache_definition (file,
741                                            semantic->insn,
742                                            semantic->expanded_bits,
743                                            semantic->opcodes,
744                                            cache_rules,
745                                            semantic->nr_prefetched_words);
746             semantic = semantic->next;
747           }
748     }
749   else
750     {
751       lf_print__this_file_is_empty (file, "generating jump engine");
752     }
753 }
754 
755 
756 /****************************************************************/
757 
758 
759 static void
gen_idecode_h(lf * file,const gen_table * gen,const insn_table * insns,cache_entry * cache_rules)760 gen_idecode_h (lf *file,
761                  const gen_table *gen,
762                  const insn_table *insns,
763                  cache_entry *cache_rules)
764 {
765   lf_printf (file, "typedef uint%d_t %sinstruction_word;\n",
766                options.insn_bit_size, options.module.global.prefix.l);
767   if (options.gen.delayed_branch)
768     {
769       lf_printf (file, "typedef struct _%sinstruction_address {\n",
770                      options.module.global.prefix.l);
771       lf_printf (file, "  address_word ip; /* instruction pointer */\n");
772       lf_printf (file, "  address_word dp; /* delayed-slot pointer */\n");
773       lf_printf (file, "} %sinstruction_address;\n",
774                      options.module.global.prefix.l);
775     }
776   else
777     {
778       lf_printf (file, "typedef address_word %sinstruction_address;\n",
779                      options.module.global.prefix.l);
780 
781     }
782   if (options.gen.nia == nia_is_invalid
783       && strlen (options.module.global.prefix.u) > 0)
784     {
785       lf_indent_suppress (file);
786       lf_printf (file, "#define %sINVALID_INSTRUCTION_ADDRESS ",
787                      options.module.global.prefix.u);
788       lf_printf (file, "INVALID_INSTRUCTION_ADDRESS\n");
789     }
790   lf_printf (file, "\n");
791   print_icache_struct (file, insns, cache_rules);
792   lf_printf (file, "\n");
793   if (options.gen.icache)
794     {
795       ERROR ("FIXME - idecode with icache suffering from bit-rot");
796     }
797   else
798     {
799       gen_list *entry;
800       for (entry = gen->tables; entry != NULL; entry = entry->next)
801           {
802             print_idecode_issue_function_header (file,
803                                                          (options.gen.multi_sim
804                                                             ? entry->model->name
805                                                             : NULL),
806                                                          is_function_declaration,
807                                                          1 /*ALWAYS ONE WORD */ );
808           }
809       if (options.gen.multi_sim)
810           {
811             print_idecode_issue_function_header (file,
812                                                          NULL,
813                                                          is_function_variable,
814                                                          1 /*ALWAYS ONE WORD */ );
815           }
816     }
817 }
818 
819 
820 static void
gen_idecode_c(lf * file,const gen_table * gen,const insn_table * isa,cache_entry * cache_rules)821 gen_idecode_c (lf *file,
822                  const gen_table *gen,
823                  const insn_table *isa,
824                  cache_entry *cache_rules)
825 {
826   /* the intro */
827   print_includes (file);
828   print_include_inline (file, options.module.semantics);
829   lf_printf (file, "\n");
830 
831   print_idecode_globals (file);
832   lf_printf (file, "\n");
833 
834   switch (options.gen.code)
835     {
836     case generate_calls:
837       {
838           gen_list *entry;
839           for (entry = gen->tables; entry != NULL; entry = entry->next)
840             {
841               print_idecode_lookups (file, entry->table, cache_rules);
842 
843               /* output the main idecode routine */
844               if (!options.gen.icache)
845                 {
846                     print_idecode_issue_function_header (file,
847                                                                  (options.gen.multi_sim
848                                                                   ? entry->model->name
849                                                                   : NULL),
850                                                                  1 /*is definition */ ,
851                                                                  1 /*ALWAYS ONE WORD */ );
852                     lf_printf (file, "{\n");
853                     lf_indent (file, +2);
854                     lf_printf (file, "%sinstruction_address nia;\n",
855                                  options.module.global.prefix.l);
856                     print_idecode_body (file, entry->table, "nia =");
857                     lf_printf (file, "return nia;");
858                     lf_indent (file, -2);
859                     lf_printf (file, "}\n");
860                 }
861             }
862           break;
863       }
864     case generate_jumps:
865       {
866           lf_print__this_file_is_empty (file, "generating a jump engine");
867           break;
868       }
869     }
870 }
871 
872 
873 /****************************************************************/
874 
875 
876 static void
gen_run_c(lf * file,const gen_table * gen)877 gen_run_c (lf *file, const gen_table *gen)
878 {
879   gen_list *entry;
880   lf_printf (file, "#include \"sim-main.h\"\n");
881   lf_printf (file, "#include \"engine.h\"\n");
882   lf_printf (file, "#include \"idecode.h\"\n");
883   lf_printf (file, "#include \"bfd.h\"\n");
884   lf_printf (file, "\n");
885 
886   if (options.gen.multi_sim)
887     {
888       print_idecode_issue_function_header (file, NULL, is_function_variable,
889                                                      1);
890       lf_printf (file, "\n");
891       print_engine_run_function_header (file, NULL, is_function_variable);
892       lf_printf (file, "\n");
893     }
894 
895   lf_printf (file, "void\n");
896   lf_printf (file, "sim_engine_run (SIM_DESC sd,\n");
897   lf_printf (file, "                int next_cpu_nr,\n");
898   lf_printf (file, "                int nr_cpus,\n");
899   lf_printf (file, "                int siggnal)\n");
900   lf_printf (file, "{\n");
901   lf_indent (file, +2);
902   if (options.gen.multi_sim)
903     {
904       lf_printf (file, "int mach;\n");
905       lf_printf (file, "if (STATE_ARCHITECTURE (sd) == NULL)\n");
906       lf_printf (file, "  mach = 0;\n");
907       lf_printf (file, "else\n");
908       lf_printf (file, "  mach = STATE_ARCHITECTURE (sd)->mach;\n");
909       lf_printf (file, "switch (mach)\n");
910       lf_printf (file, "  {\n");
911       lf_indent (file, +2);
912       for (entry = gen->tables; entry != NULL; entry = entry->next)
913           {
914             if (options.gen.default_model != NULL
915                 && (strcmp (entry->model->name, options.gen.default_model) == 0
916                       || strcmp (entry->model->full_name,
917                                    options.gen.default_model) == 0))
918               lf_printf (file, "default:\n");
919             lf_printf (file, "case bfd_mach_%s:\n", entry->model->full_name);
920             lf_indent (file, +2);
921             print_function_name (file, "issue", NULL,       /* format name */
922                                      NULL,        /* NO processor */
923                                      NULL,        /* expanded bits */
924                                      function_name_prefix_idecode);
925             lf_printf (file, " = ");
926             print_function_name (file, "issue", NULL,       /* format name */
927                                      entry->model->name, NULL,        /* expanded bits */
928                                      function_name_prefix_idecode);
929             lf_printf (file, ";\n");
930             print_function_name (file, "run", NULL,         /* format name */
931                                      NULL,        /* NO processor */
932                                      NULL,        /* expanded bits */
933                                      function_name_prefix_engine);
934             lf_printf (file, " = ");
935             print_function_name (file, "run", NULL,         /* format name */
936                                      entry->model->name, NULL,        /* expanded bits */
937                                      function_name_prefix_engine);
938             lf_printf (file, ";\n");
939             lf_printf (file, "break;\n");
940             lf_indent (file, -2);
941           }
942       if (options.gen.default_model == NULL)
943           {
944             lf_printf (file, "default:\n");
945             lf_indent (file, +2);
946             lf_printf (file, "sim_engine_abort (sd, NULL, NULL_CIA,\n");
947             lf_printf (file,
948                          "                  \"sim_engine_run - unknown machine\");\n");
949             lf_printf (file, "break;\n");
950             lf_indent (file, -2);
951           }
952       lf_indent (file, -2);
953       lf_printf (file, "  }\n");
954     }
955   print_function_name (file, "run", NULL,         /* format name */
956                            NULL,        /* NO processor */
957                            NULL,        /* expanded bits */
958                            function_name_prefix_engine);
959   lf_printf (file, " (sd, next_cpu_nr, nr_cpus, siggnal);\n");
960   lf_indent (file, -2);
961   lf_printf (file, "}\n");
962 }
963 
964 /****************************************************************/
965 
966 static gen_table *
do_gen(const insn_table * isa,const decode_table * decode_rules)967 do_gen (const insn_table *isa, const decode_table *decode_rules)
968 {
969   gen_table *gen;
970   if (decode_rules == NULL)
971     error (NULL, "Must specify a decode table\n");
972   if (isa == NULL)
973     error (NULL, "Must specify an instruction table\n");
974   if (decode_table_max_word_nr (decode_rules) > 0)
975     options.gen.multi_word = decode_table_max_word_nr (decode_rules);
976   gen = make_gen_tables (isa, decode_rules);
977   gen_tables_expand_insns (gen);
978   gen_tables_expand_semantics (gen);
979   return gen;
980 }
981 
982 /****************************************************************/
983 
984 igen_options options;
985 
986 int
main(int argc,char ** argv,char ** envp)987 main (int argc, char **argv, char **envp)
988 {
989   cache_entry *cache_rules = NULL;
990   lf_file_references file_references = lf_include_references;
991   decode_table *decode_rules = NULL;
992   insn_table *isa = NULL;
993   gen_table *gen = NULL;
994   char *real_file_name = NULL;
995   int is_header = 0;
996   int ch;
997   static const struct option longopts[] = { { 0 } };
998   lf *standard_out =
999     lf_open ("-", "stdout", lf_omit_references, lf_is_text, "igen");
1000 
1001   INIT_OPTIONS ();
1002 
1003   if (argc == 1)
1004     {
1005       printf ("Usage:\n");
1006       printf ("\n");
1007       printf ("  igen <config-opts> ... <input-opts>... <output-opts>...\n");
1008       printf ("\n");
1009       printf ("Config options:\n");
1010       printf ("\n");
1011       printf ("  -B <bit-size>\n");
1012       printf ("\t Set the number of bits in an instruction (deprecated).\n");
1013       printf
1014           ("\t This option can now be set directly in the instruction table.\n");
1015       printf ("\n");
1016       printf ("  -D <data-structure>\n");
1017       printf
1018           ("\t Dump the specified data structure to stdout. Valid structures include:\n");
1019       printf
1020           ("\t processor-names - list the names of all the processors (models)\n");
1021       printf ("\n");
1022       printf ("  -F <filter-list>\n");
1023       printf
1024           ("\t Filter out any instructions with a non-empty flags field that contains\n");
1025       printf ("\t a flag not listed in the <filter-list>.\n");
1026       printf ("\n");
1027       printf ("  -H <high-bit>\n");
1028       printf
1029           ("\t Set the number of the high (most significant) instruction bit (deprecated).\n");
1030       printf
1031           ("\t This option can now be set directly in the instruction table.\n");
1032       printf ("\n");
1033       printf ("  -I <directory>\n");
1034       printf
1035           ("\t Add <directory> to the list of directories searched when opening a file\n");
1036       printf ("\n");
1037       printf ("  -M <model-list>\n");
1038       printf
1039           ("\t Filter out any instructions that do not support at least one of the listed\n");
1040       printf
1041           ("\t models (An instructions with no model information is considered to support\n");
1042       printf ("\t all models.).\n");
1043       printf ("\n");
1044       printf ("  -N <nr-cpus>\n");
1045       printf ("\t Generate a simulator supporting <nr-cpus>\n");
1046       printf
1047           ("\t Specify `-N 0' to disable generation of the SMP. Specifying `-N 1' will\n");
1048       printf
1049           ("\t still generate an SMP enabled simulator but will only support one CPU.\n");
1050       printf ("\n");
1051       printf ("  -T <mechanism>\n");
1052       printf
1053           ("\t Override the decode mechanism specified by the decode rules\n");
1054       printf ("\n");
1055       printf ("  -P <prefix>\n");
1056       printf
1057           ("\t Prepend global names (except itable) with the string <prefix>.\n");
1058       printf
1059           ("\t Specify -P <module>=<prefix> to set a specific <module>'s prefix.\n");
1060       printf ("\n");
1061       printf ("  -S <suffix>\n");
1062       printf
1063           ("\t Replace a global name (suffix) (except itable) with the string <suffix>.\n");
1064       printf
1065           ("\t Specify -S <module>=<suffix> to change a specific <module>'s name (suffix).\n");
1066       printf ("\n");
1067       printf ("  -Werror\n");
1068       printf ("\t Make warnings errors\n");
1069       printf ("  -Wnodiscard\n");
1070       printf
1071           ("\t Suppress warnings about discarded functions and instructions\n");
1072       printf ("  -Wnowidth\n");
1073       printf
1074           ("\t Suppress warnings about instructions with invalid widths\n");
1075       printf ("  -Wnounimplemented\n");
1076       printf ("\t Suppress warnings about unimplemented instructions\n");
1077       printf ("\n");
1078       printf ("  -G [!]<gen-option>\n");
1079       printf ("\t Any of the following options:\n");
1080       printf ("\n");
1081       printf
1082           ("\t decode-duplicate       - Override the decode rules, forcing the duplication of\n");
1083       printf ("\t                          semantic functions\n");
1084       printf
1085           ("\t decode-combine         - Combine any duplicated entries within a table\n");
1086       printf
1087           ("\t decode-zero-reserved   - Override the decode rules, forcing reserved bits to be\n");
1088       printf ("\t                          treated as zero.\n");
1089       printf
1090           ("\t decode-switch-is-goto  - Overfide the padded-switch code type as a goto-switch\n");
1091       printf ("\n");
1092       printf
1093           ("\t gen-conditional-issue  - conditionally issue each instruction\n");
1094       printf
1095           ("\t gen-delayed-branch     - need both cia and nia passed around\n");
1096       printf
1097           ("\t gen-direct-access      - use #defines to directly access values\n");
1098       printf
1099           ("\t gen-zero-r<N>          - arch assumes GPR(<N>) == 0, keep it that way\n");
1100       printf
1101           ("\t gen-icache[=<N>        - generate an instruction cracking cache of size <N>\n");
1102       printf ("\t                          Default size is %d\n",
1103                 options.gen.icache_size);
1104       printf
1105           ("\t gen-insn-in-icache     - save original instruction when cracking\n");
1106       printf
1107           ("\t gen-multi-sim[=MODEL]  - generate multiple simulators - one per model\n");
1108       printf
1109           ("\t                          If specified MODEL is made the default architecture.\n");
1110       printf
1111           ("\t                          By default, a single simulator that will\n");
1112       printf
1113           ("\t                          execute any instruction is generated\n");
1114       printf
1115           ("\t gen-multi-word         - generate code allowing for multi-word insns\n");
1116       printf
1117           ("\t gen-semantic-icache    - include semantic code in cracking functions\n");
1118       printf
1119           ("\t gen-slot-verification  - perform slot verification as part of decode\n");
1120       printf ("\t gen-nia-invalid        - NIA defaults to nia_invalid\n");
1121       printf ("\t gen-nia-void           - do not compute/return NIA\n");
1122       printf ("\n");
1123       printf
1124           ("\t trace-combine          - report combined entries a rule application\n");
1125       printf
1126           ("\t trace-entries          - report entries after a rules application\n");
1127       printf ("\t trace-rule-rejection   - report each rule as rejected\n");
1128       printf ("\t trace-rule-selection   - report each rule as selected\n");
1129       printf
1130           ("\t trace-insn-insertion   - report each instruction as it is inserted into a decode table\n");
1131       printf
1132           ("\t trace-rule-expansion   - report each instruction as it is expanded (before insertion into a decode table)\n");
1133       printf ("\t trace-all              - enable all trace options\n");
1134       printf ("\n");
1135       printf
1136           ("\t field-widths           - instruction formats specify widths (deprecated)\n");
1137       printf
1138           ("\t                          By default, an instruction format specifies bit\n");
1139       printf ("\t                          positions\n");
1140       printf
1141           ("\t                          This option can now be set directly in the\n");
1142       printf ("\t                          instruction table\n");
1143       printf
1144           ("\t jumps                  - use jumps instead of function calls\n");
1145       printf
1146           ("\t omit-line-numbers      - do not include line number information in the output\n");
1147       printf ("\n");
1148       printf ("Input options:\n");
1149       printf ("\n");
1150       printf ("  -k <cache-rules> (deprecated)\n");
1151       printf ("  -o <decode-rules>\n");
1152       printf ("  -i <instruction-table>\n");
1153       printf ("\n");
1154       printf ("Output options:\n");
1155       printf ("\n");
1156       printf ("  -x                    Perform expansion (required)\n");
1157       printf
1158           ("  -n <real-name>        Specify the real name of the next output file\n");
1159       printf
1160           ("  -h                     Generate the header (.h) file rather than the body (.c)\n");
1161       printf ("  -c <output-file>      output icache\n");
1162       printf ("  -d <output-file>      output idecode\n");
1163       printf ("  -e <output-file>      output engine\n");
1164       printf ("  -f <output-file>      output support functions\n");
1165       printf ("  -m <output-file>      output model\n");
1166       printf ("  -r <output-file>      output multi-sim run\n");
1167       printf ("  -s <output-file>      output schematic\n");
1168       printf ("  -t <output-file>      output itable\n");
1169     }
1170 
1171   while ((ch = getopt_long (argc, argv,
1172                                   "B:D:F:G:H:I:M:N:P:T:W:o:k:i:n:hc:d:e:m:r:s:t:f:x",
1173                                   longopts, NULL))
1174            != -1)
1175     {
1176 #if 0  /* For debugging.  */
1177       fprintf (stderr, "  -%c ", ch);
1178       if (optarg)
1179           fprintf (stderr, "%s ", optarg);
1180       fprintf (stderr, "\\\n");
1181 #endif
1182 
1183       switch (ch)
1184           {
1185 
1186           case 'M':
1187             filter_parse (&options.model_filter, optarg);
1188             break;
1189 
1190           case 'D':
1191             if (strcmp (optarg, "processor-names"))
1192               {
1193                 const char *processor;
1194                 for (processor = filter_next (options.model_filter, "");
1195                        processor != NULL;
1196                        processor = filter_next (options.model_filter, processor))
1197                     lf_printf (standard_out, "%s\n", processor);
1198               }
1199             else
1200               error (NULL, "Unknown data structure %s, not dumped\n", optarg);
1201             break;
1202 
1203           case 'F':
1204             filter_parse (&options.flags_filter, optarg);
1205             break;
1206 
1207           case 'I':
1208             {
1209               table_include **dir = &options.include;
1210               while ((*dir) != NULL)
1211                 dir = &(*dir)->next;
1212               (*dir) = ZALLOC (table_include);
1213               (*dir)->dir = strdup (optarg);
1214             }
1215             break;
1216 
1217           case 'B':
1218             options.insn_bit_size = a2i (optarg);
1219             if (options.insn_bit_size <= 0
1220                 || options.insn_bit_size > max_insn_bit_size)
1221               {
1222                 error (NULL, "Instruction bitsize must be in range 1..%d\n",
1223                          max_insn_bit_size);
1224               }
1225             if (options.hi_bit_nr != options.insn_bit_size - 1
1226                 && options.hi_bit_nr != 0)
1227               {
1228                 error (NULL, "Conflict betweem hi-bit-nr and insn-bit-size\n");
1229               }
1230             break;
1231 
1232           case 'H':
1233             options.hi_bit_nr = a2i (optarg);
1234             if (options.hi_bit_nr != options.insn_bit_size - 1
1235                 && options.hi_bit_nr != 0)
1236               {
1237                 error (NULL, "Conflict between hi-bit-nr and insn-bit-size\n");
1238               }
1239             break;
1240 
1241           case 'N':
1242             options.gen.smp = a2i (optarg);
1243             break;
1244 
1245           case 'P':
1246           case 'S':
1247             {
1248               igen_module *names;
1249               igen_name *name;
1250               char *chp;
1251               chp = strchr (optarg, '=');
1252               if (chp == NULL)
1253                 {
1254                     names = &options.module.global;
1255                     chp = optarg;
1256                 }
1257               else
1258                 {
1259                     chp = chp + 1;      /* skip `=' */
1260                     names = NULL;
1261                     if (strncmp (optarg, "global=", chp - optarg) == 0)
1262                       {
1263                         names = &options.module.global;
1264                       }
1265                     if (strncmp (optarg, "engine=", chp - optarg) == 0)
1266                       {
1267                         names = &options.module.engine;
1268                       }
1269                     if (strncmp (optarg, "icache=", chp - optarg) == 0)
1270                       {
1271                         names = &options.module.icache;
1272                       }
1273                     if (strncmp (optarg, "idecode=", chp - optarg) == 0)
1274                       {
1275                         names = &options.module.idecode;
1276                       }
1277                     if (strncmp (optarg, "itable=", chp - optarg) == 0)
1278                       {
1279                         names = &options.module.itable;
1280                       }
1281                     if (strncmp (optarg, "semantics=", chp - optarg) == 0)
1282                       {
1283                         names = &options.module.semantics;
1284                       }
1285                     if (strncmp (optarg, "support=", chp - optarg) == 0)
1286                       {
1287                         names = &options.module.support;
1288                       }
1289                     if (names == NULL)
1290                       {
1291                         error (NULL, "Prefix `%s' unreconized\n", optarg);
1292                       }
1293                 }
1294               switch (ch)
1295                 {
1296                 case 'P':
1297                     name = &names->prefix;
1298                     break;
1299                 case 'S':
1300                     name = &names->suffix;
1301                     break;
1302                 default:
1303                     abort (); /* Bad switch.  */
1304                 }
1305               name->u = strdup (chp);
1306               name->l = strdup (chp);
1307               chp = name->u;
1308               while (*chp)
1309                 {
1310                     if (islower (*chp))
1311                       *chp = toupper (*chp);
1312                     chp++;
1313                 }
1314               if (name == &options.module.global.prefix)
1315                 {
1316                     options.module.engine.prefix = options.module.global.prefix;
1317                     options.module.icache.prefix = options.module.global.prefix;
1318                     options.module.idecode.prefix = options.module.global.prefix;
1319                     /* options.module.itable.prefix = options.module.global.prefix; */
1320                     options.module.semantics.prefix =
1321                       options.module.global.prefix;
1322                     options.module.support.prefix = options.module.global.prefix;
1323                 }
1324               if (name == &options.module.global.suffix)
1325                 {
1326                     options.module.engine.suffix = options.module.global.suffix;
1327                     options.module.icache.suffix = options.module.global.suffix;
1328                     options.module.idecode.suffix = options.module.global.suffix;
1329                     /* options.module.itable.suffix = options.module.global.suffix; */
1330                     options.module.semantics.suffix =
1331                       options.module.global.suffix;
1332                     options.module.support.suffix = options.module.global.suffix;
1333                 }
1334               break;
1335             }
1336 
1337           case 'W':
1338             {
1339               if (strcmp (optarg, "error") == 0)
1340                 options.warning = error;
1341               else if (strcmp (optarg, "nodiscard") == 0)
1342                 options.warn.discard = 0;
1343               else if (strcmp (optarg, "discard") == 0)
1344                 options.warn.discard = 1;
1345               else if (strcmp (optarg, "nowidth") == 0)
1346                 options.warn.width = 0;
1347               else if (strcmp (optarg, "width") == 0)
1348                 options.warn.width = 1;
1349               else if (strcmp (optarg, "nounimplemented") == 0)
1350                 options.warn.unimplemented = 0;
1351               else if (strcmp (optarg, "unimplemented") == 0)
1352                 options.warn.unimplemented = 1;
1353               else
1354                 error (NULL, "Unknown -W argument `%s'\n", optarg);
1355               break;
1356             }
1357 
1358 
1359           case 'G':
1360             {
1361               int enable_p;
1362               char *argp;
1363               if (strncmp (optarg, "no-", strlen ("no-")) == 0)
1364                 {
1365                     argp = optarg + strlen ("no-");
1366                     enable_p = 0;
1367                 }
1368               else if (strncmp (optarg, "!", strlen ("!")) == 0)
1369                 {
1370                     argp = optarg + strlen ("no-");
1371                     enable_p = 0;
1372                 }
1373               else
1374                 {
1375                     argp = optarg;
1376                     enable_p = 1;
1377                 }
1378               if (strcmp (argp, "decode-duplicate") == 0)
1379                 {
1380                     options.decode.duplicate = enable_p;
1381                 }
1382               else if (strcmp (argp, "decode-combine") == 0)
1383                 {
1384                     options.decode.combine = enable_p;
1385                 }
1386               else if (strcmp (argp, "decode-zero-reserved") == 0)
1387                 {
1388                     options.decode.zero_reserved = enable_p;
1389                 }
1390 
1391               else if (strcmp (argp, "gen-conditional-issue") == 0)
1392                 {
1393                     options.gen.conditional_issue = enable_p;
1394                 }
1395               else if (strcmp (argp, "conditional-issue") == 0)
1396                 {
1397                     options.gen.conditional_issue = enable_p;
1398                     options.warning (NULL,
1399                                          "Option conditional-issue replaced by gen-conditional-issue\n");
1400                 }
1401               else if (strcmp (argp, "gen-delayed-branch") == 0)
1402                 {
1403                     options.gen.delayed_branch = enable_p;
1404                 }
1405               else if (strcmp (argp, "delayed-branch") == 0)
1406                 {
1407                     options.gen.delayed_branch = enable_p;
1408                     options.warning (NULL,
1409                                          "Option delayed-branch replaced by gen-delayed-branch\n");
1410                 }
1411               else if (strcmp (argp, "gen-direct-access") == 0)
1412                 {
1413                     options.gen.direct_access = enable_p;
1414                 }
1415               else if (strcmp (argp, "direct-access") == 0)
1416                 {
1417                     options.gen.direct_access = enable_p;
1418                     options.warning (NULL,
1419                                          "Option direct-access replaced by gen-direct-access\n");
1420                 }
1421               else if (strncmp (argp, "gen-zero-r", strlen ("gen-zero-r")) == 0)
1422                 {
1423                     options.gen.zero_reg = enable_p;
1424                     options.gen.zero_reg_nr = atoi (argp + strlen ("gen-zero-r"));
1425                 }
1426               else if (strncmp (argp, "zero-r", strlen ("zero-r")) == 0)
1427                 {
1428                     options.gen.zero_reg = enable_p;
1429                     options.gen.zero_reg_nr = atoi (argp + strlen ("zero-r"));
1430                     options.warning (NULL,
1431                                          "Option zero-r<N> replaced by gen-zero-r<N>\n");
1432                 }
1433               else if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0)
1434                 {
1435                     switch (argp[strlen ("gen-icache")])
1436                       {
1437                       case '=':
1438                         options.gen.icache_size =
1439                           atoi (argp + strlen ("gen-icache") + 1);
1440                         options.gen.icache = enable_p;
1441                         break;
1442                       case '\0':
1443                         options.gen.icache = enable_p;
1444                         break;
1445                       default:
1446                         error (NULL,
1447                                  "Expecting -Ggen-icache or -Ggen-icache=<N>\n");
1448                       }
1449                 }
1450               else if (strcmp (argp, "gen-insn-in-icache") == 0)
1451                 {
1452                     options.gen.insn_in_icache = enable_p;
1453                 }
1454               else if (strncmp (argp, "gen-multi-sim", strlen ("gen-multi-sim"))
1455                          == 0)
1456                 {
1457                     char *arg = &argp[strlen ("gen-multi-sim")];
1458                     switch (arg[0])
1459                       {
1460                       case '=':
1461                         options.gen.multi_sim = enable_p;
1462                         options.gen.default_model = arg + 1;
1463                         if (!filter_is_member
1464                               (options.model_filter, options.gen.default_model))
1465                           error (NULL, "multi-sim model %s unknown\n",
1466                                    options.gen.default_model);
1467                         break;
1468                       case '\0':
1469                         options.gen.multi_sim = enable_p;
1470                         options.gen.default_model = NULL;
1471                         break;
1472                       default:
1473                         error (NULL,
1474                                  "Expecting -Ggen-multi-sim or -Ggen-multi-sim=<MODEL>\n");
1475                         break;
1476                       }
1477                 }
1478               else if (strcmp (argp, "gen-multi-word") == 0)
1479                 {
1480                     options.gen.multi_word = enable_p;
1481                 }
1482               else if (strcmp (argp, "gen-semantic-icache") == 0)
1483                 {
1484                     options.gen.semantic_icache = enable_p;
1485                 }
1486               else if (strcmp (argp, "gen-slot-verification") == 0)
1487                 {
1488                     options.gen.slot_verification = enable_p;
1489                 }
1490               else if (strcmp (argp, "verify-slot") == 0)
1491                 {
1492                     options.gen.slot_verification = enable_p;
1493                     options.warning (NULL,
1494                                          "Option verify-slot replaced by gen-slot-verification\n");
1495                 }
1496               else if (strcmp (argp, "gen-nia-invalid") == 0)
1497                 {
1498                     options.gen.nia = nia_is_invalid;
1499                 }
1500               else if (strcmp (argp, "default-nia-minus-one") == 0)
1501                 {
1502                     options.gen.nia = nia_is_invalid;
1503                     options.warning (NULL,
1504                                          "Option default-nia-minus-one replaced by gen-nia-invalid\n");
1505                 }
1506               else if (strcmp (argp, "gen-nia-void") == 0)
1507                 {
1508                     options.gen.nia = nia_is_void;
1509                 }
1510               else if (strcmp (argp, "trace-all") == 0)
1511                 {
1512                     memset (&options.trace, enable_p, sizeof (options.trace));
1513                 }
1514               else if (strcmp (argp, "trace-combine") == 0)
1515                 {
1516                     options.trace.combine = enable_p;
1517                 }
1518               else if (strcmp (argp, "trace-entries") == 0)
1519                 {
1520                     options.trace.entries = enable_p;
1521                 }
1522               else if (strcmp (argp, "trace-rule-rejection") == 0)
1523                 {
1524                     options.trace.rule_rejection = enable_p;
1525                 }
1526               else if (strcmp (argp, "trace-rule-selection") == 0)
1527                 {
1528                     options.trace.rule_selection = enable_p;
1529                 }
1530               else if (strcmp (argp, "trace-insn-insertion") == 0)
1531                 {
1532                     options.trace.insn_insertion = enable_p;
1533                 }
1534               else if (strcmp (argp, "trace-insn-expansion") == 0)
1535                 {
1536                     options.trace.insn_expansion = enable_p;
1537                 }
1538               else if (strcmp (argp, "jumps") == 0)
1539                 {
1540                     options.gen.code = generate_jumps;
1541                 }
1542               else if (strcmp (argp, "field-widths") == 0)
1543                 {
1544                     options.insn_specifying_widths = enable_p;
1545                 }
1546               else if (strcmp (argp, "omit-line-numbers") == 0)
1547                 {
1548                     file_references = lf_omit_references;
1549                 }
1550               else
1551                 {
1552                     error (NULL, "Unknown option %s\n", optarg);
1553                 }
1554               break;
1555             }
1556 
1557           case 'i':
1558             isa = load_insn_table (optarg, cache_rules);
1559             if (isa->illegal_insn == NULL)
1560               error (NULL, "illegal-instruction missing from insn table\n");
1561             break;
1562 
1563           case 'x':
1564             gen = do_gen (isa, decode_rules);
1565             break;
1566 
1567           case 'o':
1568             decode_rules = load_decode_table (optarg);
1569             break;
1570 
1571           case 'k':
1572             if (isa != NULL)
1573               error (NULL, "Cache file must appear before the insn file\n");
1574             cache_rules = load_cache_table (optarg);
1575             break;
1576 
1577           case 'n':
1578             real_file_name = strdup (optarg);
1579             break;
1580 
1581           case 'h':
1582             is_header = 1;
1583             break;
1584 
1585           case 'c':
1586           case 'd':
1587           case 'e':
1588           case 'f':
1589           case 'm':
1590           case 'r':
1591           case 's':
1592           case 't':
1593             {
1594               lf *file = lf_open (optarg, real_file_name, file_references,
1595                                         (is_header ? lf_is_h : lf_is_c),
1596                                         argv[0]);
1597               if (gen == NULL && ch != 't' && ch != 'm' && ch != 'f')
1598                 {
1599                     options.warning (NULL,
1600                                          "Explicitly generate tables with -x option\n");
1601                     gen = do_gen (isa, decode_rules);
1602                 }
1603               lf_print__file_start (file);
1604               switch (ch)
1605                 {
1606                 case 'm':
1607                     if (is_header)
1608                       gen_model_h (file, isa);
1609                     else
1610                       gen_model_c (file, isa);
1611                     break;
1612                 case 't':
1613                     if (is_header)
1614                       gen_itable_h (file, isa);
1615                     else
1616                       gen_itable_c (file, isa);
1617                     break;
1618                 case 'f':
1619                     if (is_header)
1620                       gen_support_h (file, isa);
1621                     else
1622                       gen_support_c (file, isa);
1623                     break;
1624                 case 'r':
1625                     if (is_header)
1626                       options.warning (NULL, "-hr option ignored\n");
1627                     else
1628                       gen_run_c (file, gen);
1629                     break;
1630                 case 's':
1631                     if (is_header)
1632                       gen_semantics_h (file, gen->semantics, isa->max_nr_words);
1633                     else
1634                       gen_semantics_c (file, gen->semantics, isa->caches);
1635                     break;
1636                 case 'd':
1637                     if (is_header)
1638                       gen_idecode_h (file, gen, isa, cache_rules);
1639                     else
1640                       gen_idecode_c (file, gen, isa, cache_rules);
1641                     break;
1642                 case 'e':
1643                     if (is_header)
1644                       gen_engine_h (file, gen, isa, cache_rules);
1645                     else
1646                       gen_engine_c (file, gen, isa, cache_rules);
1647                     break;
1648                 case 'c':
1649                     if (is_header)
1650                       gen_icache_h (file,
1651                                         gen->semantics,
1652                                         isa->functions, isa->max_nr_words);
1653                     else
1654                       gen_icache_c (file,
1655                                         gen->semantics, isa->functions, cache_rules);
1656                     break;
1657                 }
1658               lf_print__file_finish (file);
1659               lf_close (file);
1660               is_header = 0;
1661             }
1662             real_file_name = NULL;
1663             break;
1664           default:
1665             ERROR ("Bad switch");
1666           }
1667     }
1668   return (0);
1669 }
1670