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