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 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
40static void
41print_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
52static void
53print_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
65static void
66print_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\
101In this case, we can take advantage of the fact that the current\n\
102instruction address (CIA) does not need to be read from / written to\n\
103the CPU object after the execution of an instruction.\n\
104\n\
105Instead, CIA is only saved when the main loop exits.  This occures\n\
106when either sim_engine_halt or sim_engine_restart is called.  Both of\n\
107these functions save the current instruction address before halting /\n\
108restarting the simulator.\n\
109\n\
110As a variation, there may also be support for an instruction cracking\n\
111cache. */\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\
220The complexity here comes from needing to correctly halt the simulator\n\
221when it is aborted.  For instance, if cpu0 requests a restart then\n\
222cpu1 will normally be the next cpu that is run.  Cpu0 being restarted\n\
223after 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
337static void
338print_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
390static void
391print_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
496static void
497print_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
523static void
524print_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
555static void
556print_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
655void
656print_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
710void
711gen_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
725void
726gen_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}
767