igen: Fix SMP simulator generator support.
[platform/upstream/binutils.git] / sim / igen / gen-engine.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1997, 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
21 #include "misc.h"
22 #include "lf.h"
23 #include "table.h"
24 #include "filter.h"
25
26 #include "igen.h"
27
28 #include "ld-insn.h"
29 #include "ld-decode.h"
30
31 #include "gen.h"
32
33 #include "gen-idecode.h"
34 #include "gen-engine.h"
35 #include "gen-icache.h"
36 #include "gen-semantics.h"
37
38
39 static void
40 print_run_body (lf *file,
41                 gen_entry *table)
42 {
43   /* Output the function to execute real code:
44      
45      Unfortunatly, there are multiple cases to consider vis:
46      
47      <icache> X <smp>
48      
49      Consequently this function is written in multiple different ways */
50   
51   lf_printf (file, "{\n");
52   lf_indent (file, +2);
53   if (!options.gen.smp)
54     {
55       lf_printf (file, "instruction_address cia;\n");
56     }
57   lf_printf (file, "int current_cpu = next_cpu_nr;\n");
58   
59   if (options.gen.icache)
60     {
61       lf_printf (file, "/* flush the icache of a possible break insn */\n");
62       lf_printf (file, "{\n");
63       lf_printf (file, "  int cpu_nr;\n");
64       lf_printf (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
65       lf_printf (file, "    cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
66       lf_printf (file, "}\n");
67     }
68   
69   if (!options.gen.smp)
70     {
71       
72       lf_putstr (file, "
73 /* CASE 1: NO SMP (with or with out instruction cache).
74
75 In this case, we can take advantage of the fact that the current
76 instruction address (CIA) does not need to be read from / written to
77 the CPU object after the execution of an instruction.
78
79 Instead, CIA is only saved when the main loop exits.  This occures
80 when either sim_engine_halt or sim_engine_restart is called.  Both of
81 these functions save the current instruction address before halting /
82 restarting the simulator.
83
84 As a variation, there may also be support for an instruction cracking
85 cache. */
86
87 ");
88
89       lf_putstr (file, "\n");
90       lf_putstr (file, "/* prime the main loop */\n");
91       lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
92       lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
93       lf_putstr (file, "cia = CIA_GET (CPU);\n");
94
95       lf_putstr (file, "\n");
96       lf_putstr (file, "while (1)\n");
97       lf_putstr (file, "  {\n");
98       lf_indent (file, +4);
99       
100       lf_printf (file, "%sinstruction_address nia;\n",
101                  options.prefix.global.name);
102
103       lf_printf (file, "\n");
104       if (!options.gen.icache)
105         {
106           lf_printf (file, "%sinstruction_word instruction_0 = IMEM (cia);\n",
107                      options.prefix.global.name);
108           lf_printf (file, "\n");
109           lf_indent_suppress (file);
110           lf_printf (file, "#if defined (%sENGINE_ISSUE_PREFIX_HOOK)\n",
111                      options.prefix.global.name);
112           lf_printf (file, "%sENGINE_ISSUE_PREFIX_HOOK();\n",
113                      options.prefix.global.name);
114           lf_indent_suppress (file);
115           lf_printf (file, "#endif\n");
116           lf_printf (file, "\n");
117           print_idecode_body (file, table, "nia = ");
118           lf_printf (file, "\n");
119           lf_indent_suppress (file);
120           lf_printf (file, "#if defined (%sENGINE_ISSUE_POSTFIX_HOOK)\n",
121                      options.prefix.global.name);
122           lf_printf (file, "%sENGINE_ISSUE_POSTFIX_HOOK();\n",
123                      options.prefix.global.name);
124           lf_indent_suppress (file);
125           lf_printf (file, "#endif\n");
126           lf_printf (file, "\n");
127         }
128       else
129         {
130           lf_putstr (file, "idecode_cache *cache_entry =\n");
131           lf_putstr (file, "  cpu_icache_entry (cpu, cia);\n");
132           lf_putstr (file, "if (cache_entry->address == cia)\n");
133           lf_putstr (file, "  {\n");
134           lf_indent (file, -4);
135           lf_putstr (file, "/* cache hit */\n");
136           lf_putstr (file, "idecode_semantic *const semantic = cache_entry->semantic;\n");
137           lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
138           /* tail */
139           lf_indent (file, -4);
140           lf_putstr (file, "  }\n");
141           lf_putstr (file, "else\n");
142           lf_putstr (file, "  {\n");
143           lf_indent (file, +4);
144           lf_putstr (file, "/* cache miss */\n");
145           if (!options.gen.semantic_icache)
146             {
147               lf_putstr (file, "idecode_semantic *semantic;\n");
148             }
149           lf_putstr (file, "instruction_word instruction = IMEM (cia);\n");
150           lf_putstr (file, "if (WITH_MON != 0)\n");
151           lf_putstr (file, "  mon_event (mon_event_icache_miss, cpu, cia);\n");
152           if (options.gen.semantic_icache)
153             {
154               lf_putstr (file, "{\n");
155               lf_indent (file, +2);
156               print_idecode_body (file, table, "nia =");
157               lf_indent (file, -2);
158               lf_putstr (file, "}\n");
159             }
160           else
161             {
162               print_idecode_body (file, table, "semantic =");
163               lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
164             }
165           lf_indent (file, -4);
166           lf_putstr (file, "  }\n");
167         }
168       
169       /* update the cpu if necessary */
170       switch (options.gen.nia)
171         {
172         case nia_is_cia_plus_one:
173           lf_printf (file, "\n");
174           lf_printf (file, "/* Update the instruction address */\n");
175           lf_printf (file, "cia = nia;\n");
176           break;
177         case nia_is_void:
178         case nia_is_invalid:
179           ERROR ("engine gen when NIA complex");
180         }
181
182       /* events */
183       lf_putstr (file, "\n");
184       lf_putstr (file, "/* process any events */\n");
185       lf_putstr (file, "if (sim_events_tick (sd))\n");
186       lf_putstr (file, "  {\n");
187       lf_putstr (file, "    CIA_SET (CPU, cia);\n");
188       lf_putstr (file, "    sim_events_process (sd);\n");
189       lf_putstr (file, "  }\n");
190
191       lf_indent (file, -4);
192       lf_printf (file, "  }\n");
193     }
194   
195   if (options.gen.smp)
196     {
197       
198       lf_putstr (file, "
199 /* CASE 2: SMP (With or without ICACHE)
200
201 The complexity here comes from needing to correctly halt the simulator
202 when it is aborted.  For instance, if cpu0 requests a restart then
203 cpu1 will normally be the next cpu that is run.  Cpu0 being restarted
204 after all the other CPU's and the event queue have been processed */
205
206 ");
207       
208       lf_putstr (file, "\n");
209       lf_printf (file, "/* have ensured that the event queue is current */\n");
210       lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
211       lf_printf (file, "SIM_ASSERT (current_cpu < nr_cpus - 1);\n");
212       lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
213
214       lf_putstr (file, "\n");
215       lf_putstr (file, "while (1)\n");
216       lf_putstr (file, "  {\n");
217       lf_indent (file, +4);
218       
219       lf_putstr (file, "\n");
220       lf_putstr (file, "current_cpu += 1;\n");
221       lf_putstr (file, "if (current_cpu == nr_cpus)\n");
222       lf_putstr (file, "  {\n");
223       lf_putstr (file, "    if (sim_events_tick (sd))\n");
224       lf_putstr (file, "      {\n");
225       lf_putstr (file, "        sim_events_process (sd);\n");
226       lf_putstr (file, "      }\n");
227       lf_putstr (file, "    current_cpu = 0;\n");
228       lf_putstr (file, "  }\n");
229       
230       lf_putstr (file, "\n");
231       lf_putstr (file, "{\n");
232       lf_indent (file, +2);
233       lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
234       lf_putstr (file, "instruction_address cia = CIA_GET (cpu);\n");
235       
236       if (!options.gen.icache)
237         {
238           lf_putstr (file, "instruction_word instruction_0 = IMEM (cia);\n");
239           print_idecode_body (file, table, "cia =");
240           lf_putstr (file, "CIA_SET (cpu, cia);\n");
241         }
242       
243       if (options.gen.icache)
244         {
245           lf_putstr (file, "engine_cache *cache_entry =\n");
246           lf_putstr (file, "  cpu_icache_entry(processor, cia);\n");
247           lf_putstr (file, "\n");
248           lf_putstr (file, "if (cache_entry->address == cia) {\n");
249           {
250             lf_indent (file, +2);
251             lf_putstr (file, "\n");
252             lf_putstr (file, "/* cache hit */\n");
253             lf_putstr (file, "engine_semantic *semantic = cache_entry->semantic;\n");
254             lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n");
255             /* tail */
256             lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
257             lf_putstr (file, "\n");
258             lf_indent (file, -2);
259           }
260           lf_putstr (file, "}\n");
261           lf_putstr (file, "else {\n");
262           {
263             lf_indent (file, +2);
264             lf_putstr (file, "\n");
265             lf_putstr (file, "/* cache miss */\n");
266             if (!options.gen.semantic_icache)
267               {
268                 lf_putstr (file, "engine_semantic *semantic;\n");
269               }
270             lf_putstr (file, "instruction_word instruction = IMEM (cia);\n");
271             lf_putstr (file, "if (WITH_MON != 0)\n");
272             lf_putstr (file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
273             if (options.gen.semantic_icache)
274               {
275                 lf_putstr (file, "{\n");
276                 lf_indent (file, +2);
277                 print_idecode_body(file, table, "cia =");
278                 lf_indent (file, -2);
279                 lf_putstr (file, "}\n");
280               }
281             else
282               {
283                 print_idecode_body(file, table, "semantic = ");
284                 lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n");
285               }
286             /* tail */
287             lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
288             lf_putstr (file, "\n");
289             lf_indent (file, -2);
290           }
291           lf_putstr (file, "}\n");
292         }
293       
294       /* close */
295       lf_indent (file, -2);
296       lf_putstr (file, "}\n");
297       
298       /* tail */
299       lf_indent (file, -4);
300       lf_putstr (file, "  }\n");
301     }
302   
303   
304   lf_indent (file, -2);
305   lf_putstr (file, "}\n");
306 }
307
308
309 /****************************************************************/
310
311 #if 0
312 static void
313 print_jump (lf *file,
314             int is_tail)
315 {
316   if (!options.gen.smp)
317     {
318       lf_putstr (file, "if (event_queue_tick (sd))\n");
319       lf_putstr (file, "  {\n");
320       lf_putstr (file, "    CPU_CIA (processor) = nia;\n");
321       lf_putstr (file, "    sim_events_process (sd);\n");
322       lf_putstr (file, "  }\n");
323       lf_putstr (file, "}\n");
324     }
325   
326   if (options.gen.smp)
327     {
328       if (is_tail)
329         lf_putstr (file, "cpu_set_program_counter(processor, nia);\n");
330       lf_putstr (file, "current_cpu += 1;\n");
331       lf_putstr (file, "if (current_cpu >= nr_cpus)\n");
332       lf_putstr (file, "  {\n");
333       lf_putstr (file, "    if (sim_events_tick (sd))\n");
334       lf_putstr (file, "      {\n");
335       lf_putstr (file, "        sim_events_process (sd);\n");
336       lf_putstr (file, "      }\n");
337       lf_putstr (file, "    current_cpu = 0;\n");
338       lf_putstr (file, "  }\n");
339       lf_putstr (file, "processor = processors[current_cpu];\n");
340       lf_putstr (file, "nia = cpu_get_program_counter(processor);\n");
341     }
342   
343   if (options.gen.icache)
344     {
345       lf_putstr (file, "cache_entry = cpu_icache_entry(processor, nia);\n");
346       lf_putstr (file, "if (cache_entry->address == nia) {\n");
347       lf_putstr (file, "  /* cache hit */\n");
348       lf_putstr (file, "  goto *cache_entry->semantic;\n");
349       lf_putstr (file, "}\n");
350       if (is_tail) {
351         lf_putstr (file, "goto cache_miss;\n");
352       }
353     }
354   
355   if (!options.gen.icache && is_tail)
356     {
357       lf_printf (file, "goto engine;\n");
358     }
359   
360 }
361 #endif
362
363
364 #if 0
365 static void
366 print_jump_insn (lf *file,
367                  insn_entry *instruction,
368                  opcode_bits *expanded_bits,
369                  opcode_field *opcodes,
370                  cache_entry *cache_rules)
371 {
372   insn_opcodes opcode_path;
373
374   memset (&opcode_path, 0, sizeof (opcode_path));
375   opcode_path.opcode = opcodes;
376
377   /* what we are for the moment */
378   lf_printf (file, "\n");
379   print_my_defines (file,
380                     instruction->name,
381                     instruction->format_name,
382                     expanded_bits);
383   
384   /* output the icache entry */
385   if (options.gen.icache)
386     {
387       lf_printf (file, "\n");
388       lf_indent (file, -1);
389       print_function_name (file,
390                            instruction->name,
391                            instruction->format_name,
392                            NULL,
393                            expanded_bits,
394                            function_name_prefix_icache);
395       lf_printf (file, ":\n");
396       lf_indent (file, +1);
397       lf_printf (file, "{\n");
398       lf_indent (file, +2);
399       lf_putstr (file, "const unsigned_word cia = nia;\n");
400       print_itrace (file, instruction, 1/*putting-value-in-cache*/);
401       print_idecode_validate (file, instruction, &opcode_path);
402       lf_printf (file, "\n");
403       lf_printf (file, "{\n");
404       lf_indent (file, +2);
405       print_icache_body (file,
406                          instruction,
407                          expanded_bits,
408                          cache_rules,
409                          0, /*use_defines*/
410                          put_values_in_icache);
411       lf_printf (file, "cache_entry->address = nia;\n");
412       lf_printf (file, "cache_entry->semantic = &&");
413       print_function_name (file,
414                            instruction->name,
415                            instruction->format_name,
416                            NULL,
417                            expanded_bits,
418                            function_name_prefix_semantics);
419       lf_printf (file, ";\n");
420       if (options.gen.semantic_icache)
421         {
422           print_semantic_body (file,
423                                instruction,
424                                expanded_bits,
425                                &opcode_path);
426           print_jump(file, 1/*is-tail*/);
427         }
428       else
429         {
430           lf_printf (file, "/* goto ");
431           print_function_name (file,
432                                instruction->name,
433                                instruction->format_name,
434                                NULL,
435                                expanded_bits,
436                                function_name_prefix_semantics);
437           lf_printf (file, "; */\n");
438         }
439       lf_indent (file, -2);
440       lf_putstr (file, "}\n");
441       lf_indent (file, -2);
442       lf_printf (file, "}\n");
443     }
444   
445   /* print the semantics */
446   lf_printf (file, "\n");
447   lf_indent (file, -1);
448   print_function_name (file,
449                        instruction->name,
450                        instruction->format_name,
451                        NULL,
452                        expanded_bits,
453                        function_name_prefix_semantics);
454   lf_printf (file, ":\n");
455   lf_indent (file, +1);
456   lf_printf (file, "{\n");
457   lf_indent (file, +2);
458   lf_putstr (file, "const unsigned_word cia = nia;\n");
459   print_icache_body (file,
460                      instruction,
461                      expanded_bits,
462                      cache_rules,
463                      (options.gen.direct_access
464                       ? define_variables
465                       : declare_variables),
466                      (options.gen.icache
467                       ? get_values_from_icache
468                       : do_not_use_icache));
469   print_semantic_body (file,
470                        instruction,
471                        expanded_bits,
472                        &opcode_path);
473   if (options.gen.direct_access)
474     print_icache_body (file,
475                        instruction,
476                        expanded_bits,
477                        cache_rules,
478                        undef_variables,
479                        (options.gen.icache
480                         ? get_values_from_icache
481                         : do_not_use_icache));
482   print_jump(file, 1/*is tail*/);
483   lf_indent (file, -2);
484   lf_printf (file, "}\n");
485 }
486 #endif
487
488
489 #if 0
490 static void
491 print_jump_definition (lf *file,
492                        gen_entry *entry,
493                        int depth,
494                        void *data)
495 {
496   cache_entry *cache_rules = (cache_entry*)data;
497   if (entry->opcode_rule->with_duplicates)
498     {
499       ASSERT (entry->nr_insns == 1
500               && entry->opcode == NULL
501               && entry->parent != NULL
502               && entry->parent->opcode != NULL);
503       ASSERT (entry->nr_insns == 1
504               && entry->opcode == NULL
505               && entry->parent != NULL
506               && entry->parent->opcode != NULL
507               && entry->parent->opcode_rule != NULL);
508       print_jump_insn (file,
509                        entry->insns->insn,
510                        entry->expanded_bits,
511                        entry->opcode,
512                        cache_rules);
513     }
514   else 
515     {
516       print_jump_insn (file,
517                        entry->insns->insn,
518                        NULL,
519                        NULL,
520                        cache_rules);
521     }
522 }
523 #endif
524
525
526 #if 0
527 static void
528 print_jump_internal_function (lf *file,
529                               function_entry *function,
530                               void *data)
531 {
532   if (function->is_internal)
533     {
534       lf_printf (file, "\n");
535       lf_print__line_ref (file, function->line);
536       lf_indent (file, -1);
537       print_function_name (file,
538                            function->name,
539                            NULL,
540                            NULL,
541                            NULL,
542                            (options.gen.icache
543                             ? function_name_prefix_icache
544                             : function_name_prefix_semantics));
545       lf_printf (file, ":\n");
546       lf_indent (file, +1);
547       lf_printf (file, "{\n");
548       lf_indent (file, +2);
549       lf_printf (file, "const unsigned_word cia = nia;\n");
550       table_print_code (file, function->code);
551       lf_print__internal_ref (file);
552       lf_printf (file, "error(\"Internal function must longjump\\n\");\n");
553       lf_indent (file, -2);
554       lf_printf (file, "}\n");
555     }
556 }
557 #endif
558
559
560 #if 0
561 static void
562 print_jump_body (lf *file,
563                  gen_entry *entry,
564                  insn_table *isa,
565                  cache_entry *cache_rules)
566 {
567   lf_printf (file, "{\n");
568   lf_indent (file, +2);
569   lf_putstr (file, "jmp_buf halt;\n");
570   lf_putstr (file, "jmp_buf restart;\n");
571   lf_putstr (file, "cpu *processor = NULL;\n");
572   lf_putstr (file, "unsigned_word nia = -1;\n");
573   lf_putstr (file, "instruction_word instruction = 0;\n");
574   if (options.gen.icache)
575     {
576       lf_putstr (file, "engine_cache *cache_entry = NULL;\n");
577     }
578   if (options.gen.smp)
579     {
580       lf_putstr (file, "int current_cpu = -1;\n");
581     }
582   
583   /* all the switches and tables - they know about jumping */
584   print_idecode_lookups (file, entry, cache_rules);
585   
586   /* start the simulation up */
587   if (options.gen.icache)
588     {
589       lf_putstr (file, "\n");
590       lf_putstr (file, "{\n");
591       lf_putstr (file, "  int cpu_nr;\n");
592       lf_putstr (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
593       lf_putstr (file, "    cpu_flush_icache(processors[cpu_nr]);\n");
594       lf_putstr (file, "}\n");
595     }
596   
597   lf_putstr (file, "\n");
598   lf_putstr (file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
599   
600   lf_putstr (file, "\n");
601   lf_putstr (file, "if (setjmp(halt))\n");
602   lf_putstr (file, "  return;\n");
603   
604   lf_putstr (file, "\n");
605   lf_putstr (file, "setjmp(restart);\n");
606   
607   lf_putstr (file, "\n");
608   if (!options.gen.smp)
609     {
610       lf_putstr (file, "processor = processors[0];\n");
611       lf_putstr (file, "nia = cpu_get_program_counter(processor);\n");
612     }
613   else
614     {
615       lf_putstr (file, "current_cpu = psim_last_cpu(system);\n");
616     }
617   
618   if (!options.gen.icache)
619     {
620       lf_printf (file, "\n");
621       lf_indent (file, -1);
622       lf_printf (file, "engine:\n");
623       lf_indent (file, +1);
624     }
625   
626   print_jump(file, 0/*is_tail*/);
627   
628   if (options.gen.icache)
629     {
630       lf_indent (file, -1);
631       lf_printf (file, "cache_miss:\n");
632       lf_indent (file, +1);
633     }
634   
635   lf_putstr (file, "instruction\n");
636   lf_putstr (file, "  = vm_instruction_map_read(cpu_instruction_map(processor),\n");
637   lf_putstr (file, "                            processor, nia);\n");
638   print_idecode_body (file, entry, "/*IGORE*/");
639   
640   /* print out a table of all the internals functions */
641   function_entry_traverse (file, isa->functions,
642                            print_jump_internal_function,
643                            NULL);
644   
645   /* print out a table of all the instructions */
646   ERROR ("Use the list of semantic functions, not travere_tree");
647   gen_entry_traverse_tree (file, entry,
648                            1,
649                            NULL, /* start */
650                            print_jump_definition, /* leaf */
651                            NULL, /* end */
652                            cache_rules);
653   lf_indent (file, -2);
654   lf_printf (file, "}\n");
655 }
656 #endif
657
658
659 /****************************************************************/
660
661
662 void
663 print_engine_run_function_header (lf *file,
664                                   char *processor,
665                                   function_decl_type decl_type)
666 {
667   int indent;
668   lf_printf (file, "\n");
669   switch (decl_type)
670     {
671     case is_function_declaration:
672       lf_print__function_type (file, "void", "INLINE_ENGINE", "\n");
673       break;
674     case is_function_definition:
675       lf_print__function_type (file, "void", "INLINE_ENGINE", " ");
676       break;
677     case is_function_variable:
678       lf_printf (file, "void (*");
679       break;
680     }
681   indent = print_function_name (file,
682                                 "run",
683                                 NULL, /* format name */
684                                 processor,
685                                 NULL, /* expanded bits */
686                                 function_name_prefix_engine);
687   switch (decl_type)
688     {
689     case is_function_definition:
690       lf_putstr (file, "\n(");
691       indent = 1;
692       break;
693     case is_function_declaration:
694       indent += lf_printf (file, " (");
695       break;
696     case is_function_variable:
697       lf_putstr (file, ")\n(");
698       indent = 1;
699       break;
700     }
701   lf_indent (file, +indent);
702   lf_printf (file, "SIM_DESC sd,\n");
703   lf_printf (file, "int next_cpu_nr,\n");
704   lf_printf (file, "int nr_cpus,\n");
705   lf_printf (file, "int siggnal)");
706   lf_indent (file, -indent);
707   switch (decl_type)
708     {
709     case is_function_definition:
710       lf_putstr (file, "\n");
711       break;
712     case is_function_variable:
713     case is_function_declaration:
714       lf_putstr (file, ";\n");
715       break;
716     }
717 }
718
719
720 void
721 gen_engine_h (lf *file,
722               gen_table *gen,
723               insn_table *isa,
724               cache_entry *cache_rules)
725 {
726   gen_list *entry;
727   for (entry = gen->tables; entry != NULL; entry = entry->next)
728     {
729       print_engine_run_function_header (file,
730                                         entry->model->name,
731                                         is_function_declaration);
732     }
733 }
734
735
736 void
737 gen_engine_c(lf *file,
738              gen_table *gen,
739              insn_table *isa,
740              cache_entry *cache_rules)
741 {
742   gen_list *entry;
743   /* the intro */
744   lf_printf (file, "#include \"sim-inline.c\"\n");
745   lf_printf (file, "\n");
746   lf_printf (file, "#include \"sim-main.h\"\n");
747   lf_printf (file, "#include \"itable.h\"\n");
748   lf_printf (file, "#include \"idecode.h\"\n");
749   lf_printf (file, "#include \"semantics.h\"\n");
750   lf_printf (file, "#include \"icache.h\"\n");
751   lf_printf (file, "#include \"engine.h\"\n");
752   lf_printf (file, "#include \"support.h\"\n");
753   lf_printf (file, "\n");
754   lf_printf (file, "#include \"sim-assert.h\"\n");
755   lf_printf (file, "\n");
756   print_idecode_globals (file);
757   lf_printf (file, "\n");
758
759   for (entry = gen->tables; entry != NULL; entry = entry->next)
760     {
761       switch (options.gen.code)
762         {
763         case generate_calls:
764           print_idecode_lookups (file, entry->table, cache_rules);
765           
766           /* output the main engine routine */
767           print_engine_run_function_header (file,
768                                             entry->model->name,
769                                             is_function_definition);
770           print_run_body (file, entry->table);
771           break;
772           
773         case generate_jumps:
774           ERROR ("Jumps currently unimplemented");
775 #if 0
776           print_engine_run_function_header (file,
777                                             entry->processor,
778                                             is_function_definition);
779           print_jump_body (file, entry->table,
780                            isa, cache_rules);
781 #endif
782           break;
783         }
784     }
785 }