OSDN Git Service

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