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