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