xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-engine.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002, 2007, 2008, 2009, 2010, 2011 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 }
767