xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-engine.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
14e98e3e1Schristos /* The IGEN simulator generator for GDB, the GNU Debugger.
24e98e3e1Schristos 
3*71f62182Schristos    Copyright 2002-2024 Free Software Foundation, Inc.
44e98e3e1Schristos 
54e98e3e1Schristos    Contributed by Andrew Cagney.
64e98e3e1Schristos 
74e98e3e1Schristos    This file is part of GDB.
84e98e3e1Schristos 
94e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
104e98e3e1Schristos    it under the terms of the GNU General Public License as published by
114e98e3e1Schristos    the Free Software Foundation; either version 3 of the License, or
124e98e3e1Schristos    (at your option) any later version.
134e98e3e1Schristos 
144e98e3e1Schristos    This program is distributed in the hope that it will be useful,
154e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
164e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
174e98e3e1Schristos    GNU General Public License for more details.
184e98e3e1Schristos 
194e98e3e1Schristos    You should have received a copy of the GNU General Public License
204e98e3e1Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
214e98e3e1Schristos 
224e98e3e1Schristos #include "misc.h"
234e98e3e1Schristos #include "lf.h"
244e98e3e1Schristos #include "table.h"
254e98e3e1Schristos #include "filter.h"
264e98e3e1Schristos 
274e98e3e1Schristos #include "igen.h"
284e98e3e1Schristos 
294e98e3e1Schristos #include "ld-insn.h"
304e98e3e1Schristos #include "ld-decode.h"
314e98e3e1Schristos 
324e98e3e1Schristos #include "gen.h"
334e98e3e1Schristos 
344e98e3e1Schristos #include "gen-idecode.h"
354e98e3e1Schristos #include "gen-engine.h"
364e98e3e1Schristos #include "gen-icache.h"
374e98e3e1Schristos #include "gen-semantics.h"
384e98e3e1Schristos 
394e98e3e1Schristos 
404e98e3e1Schristos static void
414e98e3e1Schristos print_engine_issue_prefix_hook (lf *file)
424e98e3e1Schristos {
434e98e3e1Schristos   lf_printf (file, "\n");
444e98e3e1Schristos   lf_indent_suppress (file);
454e98e3e1Schristos   lf_printf (file, "#if defined (ENGINE_ISSUE_PREFIX_HOOK)\n");
464e98e3e1Schristos   lf_printf (file, "ENGINE_ISSUE_PREFIX_HOOK();\n");
474e98e3e1Schristos   lf_indent_suppress (file);
484e98e3e1Schristos   lf_printf (file, "#endif\n");
494e98e3e1Schristos   lf_printf (file, "\n");
504e98e3e1Schristos }
514e98e3e1Schristos 
524e98e3e1Schristos static void
534e98e3e1Schristos print_engine_issue_postfix_hook (lf *file)
544e98e3e1Schristos {
554e98e3e1Schristos   lf_printf (file, "\n");
564e98e3e1Schristos   lf_indent_suppress (file);
574e98e3e1Schristos   lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n");
584e98e3e1Schristos   lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n");
594e98e3e1Schristos   lf_indent_suppress (file);
604e98e3e1Schristos   lf_printf (file, "#endif\n");
614e98e3e1Schristos   lf_printf (file, "\n");
624e98e3e1Schristos }
634e98e3e1Schristos 
644e98e3e1Schristos 
654e98e3e1Schristos static void
664b169a6bSchristos print_run_body (lf *file, const gen_entry *table)
674e98e3e1Schristos {
684e98e3e1Schristos   /* Output the function to execute real code:
694e98e3e1Schristos 
704e98e3e1Schristos      Unfortunatly, there are multiple cases to consider vis:
714e98e3e1Schristos 
724e98e3e1Schristos      <icache> X <smp>
734e98e3e1Schristos 
744e98e3e1Schristos      Consequently this function is written in multiple different ways */
754e98e3e1Schristos 
764e98e3e1Schristos   lf_printf (file, "{\n");
774e98e3e1Schristos   lf_indent (file, +2);
784e98e3e1Schristos   if (!options.gen.smp)
794e98e3e1Schristos     {
804e98e3e1Schristos       lf_printf (file, "%sinstruction_address cia;\n",
814e98e3e1Schristos 		 options.module.global.prefix.l);
824e98e3e1Schristos     }
834e98e3e1Schristos   lf_printf (file, "int current_cpu = next_cpu_nr;\n");
844e98e3e1Schristos 
854e98e3e1Schristos   if (options.gen.icache)
864e98e3e1Schristos     {
874e98e3e1Schristos       lf_printf (file, "/* flush the icache of a possible break insn */\n");
884e98e3e1Schristos       lf_printf (file, "{\n");
894e98e3e1Schristos       lf_printf (file, "  int cpu_nr;\n");
904e98e3e1Schristos       lf_printf (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
914e98e3e1Schristos       lf_printf (file, "    cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
924e98e3e1Schristos       lf_printf (file, "}\n");
934e98e3e1Schristos     }
944e98e3e1Schristos 
954e98e3e1Schristos   if (!options.gen.smp)
964e98e3e1Schristos     {
974e98e3e1Schristos 
984e98e3e1Schristos       lf_putstr (file, "\
994e98e3e1Schristos /* CASE 1: NO SMP (with or with out instruction cache).\n\
1004e98e3e1Schristos \n\
1014e98e3e1Schristos In this case, we can take advantage of the fact that the current\n\
1024e98e3e1Schristos instruction address (CIA) does not need to be read from / written to\n\
1034e98e3e1Schristos the CPU object after the execution of an instruction.\n\
1044e98e3e1Schristos \n\
1054e98e3e1Schristos Instead, CIA is only saved when the main loop exits.  This occures\n\
1064e98e3e1Schristos when either sim_engine_halt or sim_engine_restart is called.  Both of\n\
1074e98e3e1Schristos these functions save the current instruction address before halting /\n\
1084e98e3e1Schristos restarting the simulator.\n\
1094e98e3e1Schristos \n\
1104e98e3e1Schristos As a variation, there may also be support for an instruction cracking\n\
1114e98e3e1Schristos cache. */\n\
1124e98e3e1Schristos \n\
1134e98e3e1Schristos ");
1144e98e3e1Schristos 
1154e98e3e1Schristos       lf_putstr (file, "\n");
1164e98e3e1Schristos       lf_putstr (file, "/* prime the main loop */\n");
1174e98e3e1Schristos       lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
1184e98e3e1Schristos       lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
119212397c6Schristos       lf_putstr (file, "cia = CPU_PC_GET (CPU);\n");
1204e98e3e1Schristos 
1214e98e3e1Schristos       lf_putstr (file, "\n");
1224e98e3e1Schristos       lf_putstr (file, "while (1)\n");
1234e98e3e1Schristos       lf_putstr (file, "  {\n");
1244e98e3e1Schristos       lf_indent (file, +4);
1254e98e3e1Schristos 
1264e98e3e1Schristos       lf_printf (file, "%sinstruction_address nia;\n",
1274e98e3e1Schristos 		 options.module.global.prefix.l);
1284e98e3e1Schristos 
1294e98e3e1Schristos       lf_printf (file, "\n");
1304e98e3e1Schristos       if (!options.gen.icache)
1314e98e3e1Schristos 	{
1324e98e3e1Schristos 	  lf_printf (file,
1334e98e3e1Schristos 		     "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
1344e98e3e1Schristos 		     options.module.global.prefix.l, options.insn_bit_size);
1354e98e3e1Schristos 	  print_engine_issue_prefix_hook (file);
1364e98e3e1Schristos 	  print_idecode_body (file, table, "nia = ");
1374e98e3e1Schristos 	  print_engine_issue_postfix_hook (file);
1384e98e3e1Schristos 	}
1394e98e3e1Schristos       else
1404e98e3e1Schristos 	{
1414e98e3e1Schristos 	  lf_putstr (file, "idecode_cache *cache_entry =\n");
1424e98e3e1Schristos 	  lf_putstr (file, "  cpu_icache_entry (cpu, cia);\n");
1434e98e3e1Schristos 	  lf_putstr (file, "if (cache_entry->address == cia)\n");
1444e98e3e1Schristos 	  lf_putstr (file, "  {\n");
1454e98e3e1Schristos 	  lf_indent (file, -4);
1464e98e3e1Schristos 	  lf_putstr (file, "/* cache hit */\n");
1474e98e3e1Schristos 	  lf_putstr (file,
1484e98e3e1Schristos 		     "idecode_semantic *const semantic = cache_entry->semantic;\n");
1494e98e3e1Schristos 	  lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
1504e98e3e1Schristos 	  /* tail */
1514e98e3e1Schristos 	  lf_indent (file, -4);
1524e98e3e1Schristos 	  lf_putstr (file, "  }\n");
1534e98e3e1Schristos 	  lf_putstr (file, "else\n");
1544e98e3e1Schristos 	  lf_putstr (file, "  {\n");
1554e98e3e1Schristos 	  lf_indent (file, +4);
1564e98e3e1Schristos 	  lf_putstr (file, "/* cache miss */\n");
1574e98e3e1Schristos 	  if (!options.gen.semantic_icache)
1584e98e3e1Schristos 	    {
1594e98e3e1Schristos 	      lf_putstr (file, "idecode_semantic *semantic;\n");
1604e98e3e1Schristos 	    }
1614e98e3e1Schristos 	  lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
1624e98e3e1Schristos 		     options.insn_bit_size);
1634e98e3e1Schristos 	  lf_putstr (file, "if (WITH_MON != 0)\n");
1644e98e3e1Schristos 	  lf_putstr (file,
1654e98e3e1Schristos 		     "  mon_event (mon_event_icache_miss, cpu, cia);\n");
1664e98e3e1Schristos 	  if (options.gen.semantic_icache)
1674e98e3e1Schristos 	    {
1684e98e3e1Schristos 	      lf_putstr (file, "{\n");
1694e98e3e1Schristos 	      lf_indent (file, +2);
1704e98e3e1Schristos 	      print_engine_issue_prefix_hook (file);
1714e98e3e1Schristos 	      print_idecode_body (file, table, "nia =");
1724e98e3e1Schristos 	      print_engine_issue_postfix_hook (file);
1734e98e3e1Schristos 	      lf_indent (file, -2);
1744e98e3e1Schristos 	      lf_putstr (file, "}\n");
1754e98e3e1Schristos 	    }
1764e98e3e1Schristos 	  else
1774e98e3e1Schristos 	    {
1784e98e3e1Schristos 	      print_engine_issue_prefix_hook (file);
1794e98e3e1Schristos 	      print_idecode_body (file, table, "semantic =");
1804e98e3e1Schristos 	      lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
1814e98e3e1Schristos 	      print_engine_issue_postfix_hook (file);
1824e98e3e1Schristos 	    }
1834e98e3e1Schristos 	  lf_indent (file, -4);
1844e98e3e1Schristos 	  lf_putstr (file, "  }\n");
1854e98e3e1Schristos 	}
1864e98e3e1Schristos 
1874e98e3e1Schristos       /* update the cpu if necessary */
1884e98e3e1Schristos       switch (options.gen.nia)
1894e98e3e1Schristos 	{
1904e98e3e1Schristos 	case nia_is_cia_plus_one:
1914e98e3e1Schristos 	  lf_printf (file, "\n");
1924e98e3e1Schristos 	  lf_printf (file, "/* Update the instruction address */\n");
1934e98e3e1Schristos 	  lf_printf (file, "cia = nia;\n");
1944e98e3e1Schristos 	  break;
1954e98e3e1Schristos 	case nia_is_void:
1964e98e3e1Schristos 	case nia_is_invalid:
1974e98e3e1Schristos 	  ERROR ("engine gen when NIA complex");
1984e98e3e1Schristos 	}
1994e98e3e1Schristos 
2004e98e3e1Schristos       /* events */
2014e98e3e1Schristos       lf_putstr (file, "\n");
2024e98e3e1Schristos       lf_putstr (file, "/* process any events */\n");
2034e98e3e1Schristos       lf_putstr (file, "if (sim_events_tick (sd))\n");
2044e98e3e1Schristos       lf_putstr (file, "  {\n");
205212397c6Schristos       lf_putstr (file, "    CPU_PC_SET (CPU, cia);\n");
2064e98e3e1Schristos       lf_putstr (file, "    sim_events_process (sd);\n");
207212397c6Schristos       lf_putstr (file, "    cia = CPU_PC_GET (CPU);\n");
2084e98e3e1Schristos       lf_putstr (file, "  }\n");
2094e98e3e1Schristos 
2104e98e3e1Schristos       lf_indent (file, -4);
2114e98e3e1Schristos       lf_printf (file, "  }\n");
2124e98e3e1Schristos     }
2134e98e3e1Schristos 
2144e98e3e1Schristos   if (options.gen.smp)
2154e98e3e1Schristos     {
2164e98e3e1Schristos 
2174e98e3e1Schristos       lf_putstr (file, "\
2184e98e3e1Schristos /* CASE 2: SMP (With or without ICACHE)\n\
2194e98e3e1Schristos \n\
2204e98e3e1Schristos The complexity here comes from needing to correctly halt the simulator\n\
2214e98e3e1Schristos when it is aborted.  For instance, if cpu0 requests a restart then\n\
2224e98e3e1Schristos cpu1 will normally be the next cpu that is run.  Cpu0 being restarted\n\
2234e98e3e1Schristos after all the other CPU's and the event queue have been processed */\n\
2244e98e3e1Schristos \n\
2254e98e3e1Schristos ");
2264e98e3e1Schristos 
2274e98e3e1Schristos       lf_putstr (file, "\n");
2284e98e3e1Schristos       lf_printf (file,
2294e98e3e1Schristos 		 "/* have ensured that the event queue is NOT next */\n");
2304e98e3e1Schristos       lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
2314e98e3e1Schristos       lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
2324e98e3e1Schristos       lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
2334e98e3e1Schristos 
2344e98e3e1Schristos       lf_putstr (file, "\n");
2354e98e3e1Schristos       lf_putstr (file, "while (1)\n");
2364e98e3e1Schristos       lf_putstr (file, "  {\n");
2374e98e3e1Schristos       lf_indent (file, +4);
2384e98e3e1Schristos       lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
239212397c6Schristos       lf_putstr (file, "instruction_address cia = CPU_PC_GET (cpu);\n");
2404e98e3e1Schristos       lf_putstr (file, "\n");
2414e98e3e1Schristos 
2424e98e3e1Schristos       if (!options.gen.icache)
2434e98e3e1Schristos 	{
2444e98e3e1Schristos 	  lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n",
2454e98e3e1Schristos 		     options.insn_bit_size);
2464e98e3e1Schristos 	  print_engine_issue_prefix_hook (file);
2474e98e3e1Schristos 	  print_idecode_body (file, table, "cia =");
248212397c6Schristos 	  lf_putstr (file, "CPU_PC_SET (cpu, cia);\n");
2494e98e3e1Schristos 	  print_engine_issue_postfix_hook (file);
2504e98e3e1Schristos 	}
2514e98e3e1Schristos 
2524e98e3e1Schristos       if (options.gen.icache)
2534e98e3e1Schristos 	{
2544e98e3e1Schristos 	  lf_putstr (file, "engine_cache *cache_entry =\n");
2554e98e3e1Schristos 	  lf_putstr (file, "  cpu_icache_entry(processor, cia);\n");
2564e98e3e1Schristos 	  lf_putstr (file, "\n");
2574e98e3e1Schristos 	  lf_putstr (file, "if (cache_entry->address == cia) {\n");
2584e98e3e1Schristos 	  {
2594e98e3e1Schristos 	    lf_indent (file, +2);
2604e98e3e1Schristos 	    lf_putstr (file, "\n");
2614e98e3e1Schristos 	    lf_putstr (file, "/* cache hit */\n");
2624e98e3e1Schristos 	    lf_putstr (file,
2634e98e3e1Schristos 		       "engine_semantic *semantic = cache_entry->semantic;\n");
2644e98e3e1Schristos 	    lf_putstr (file,
2654e98e3e1Schristos 		       "cia = semantic(processor, cache_entry, cia);\n");
2664e98e3e1Schristos 	    /* tail */
2674e98e3e1Schristos 	    lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
2684e98e3e1Schristos 	    lf_putstr (file, "\n");
2694e98e3e1Schristos 	    lf_indent (file, -2);
2704e98e3e1Schristos 	  }
2714e98e3e1Schristos 	  lf_putstr (file, "}\n");
2724e98e3e1Schristos 	  lf_putstr (file, "else {\n");
2734e98e3e1Schristos 	  {
2744e98e3e1Schristos 	    lf_indent (file, +2);
2754e98e3e1Schristos 	    lf_putstr (file, "\n");
2764e98e3e1Schristos 	    lf_putstr (file, "/* cache miss */\n");
2774e98e3e1Schristos 	    if (!options.gen.semantic_icache)
2784e98e3e1Schristos 	      {
2794e98e3e1Schristos 		lf_putstr (file, "engine_semantic *semantic;\n");
2804e98e3e1Schristos 	      }
2814e98e3e1Schristos 	    lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
2824e98e3e1Schristos 		       options.insn_bit_size);
2834e98e3e1Schristos 	    lf_putstr (file, "if (WITH_MON != 0)\n");
2844e98e3e1Schristos 	    lf_putstr (file,
2854e98e3e1Schristos 		       "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
2864e98e3e1Schristos 	    if (options.gen.semantic_icache)
2874e98e3e1Schristos 	      {
2884e98e3e1Schristos 		lf_putstr (file, "{\n");
2894e98e3e1Schristos 		lf_indent (file, +2);
2904e98e3e1Schristos 		print_engine_issue_prefix_hook (file);
2914e98e3e1Schristos 		print_idecode_body (file, table, "cia =");
2924e98e3e1Schristos 		print_engine_issue_postfix_hook (file);
2934e98e3e1Schristos 		lf_indent (file, -2);
2944e98e3e1Schristos 		lf_putstr (file, "}\n");
2954e98e3e1Schristos 	      }
2964e98e3e1Schristos 	    else
2974e98e3e1Schristos 	      {
2984e98e3e1Schristos 		print_engine_issue_prefix_hook (file);
2994e98e3e1Schristos 		print_idecode_body (file, table, "semantic = ");
3004e98e3e1Schristos 		lf_putstr (file,
3014e98e3e1Schristos 			   "cia = semantic(processor, cache_entry, cia);\n");
3024e98e3e1Schristos 		print_engine_issue_postfix_hook (file);
3034e98e3e1Schristos 	      }
3044e98e3e1Schristos 	    /* tail */
3054e98e3e1Schristos 	    lf_putstr (file, "cpu_set_program_counter(processor, cia);\n");
3064e98e3e1Schristos 	    lf_putstr (file, "\n");
3074e98e3e1Schristos 	    lf_indent (file, -2);
3084e98e3e1Schristos 	  }
3094e98e3e1Schristos 	  lf_putstr (file, "}\n");
3104e98e3e1Schristos 	}
3114e98e3e1Schristos 
3124e98e3e1Schristos       lf_putstr (file, "\n");
3134e98e3e1Schristos       lf_putstr (file, "current_cpu += 1;\n");
3144e98e3e1Schristos       lf_putstr (file, "if (current_cpu == nr_cpus)\n");
3154e98e3e1Schristos       lf_putstr (file, "  {\n");
3164e98e3e1Schristos       lf_putstr (file, "    if (sim_events_tick (sd))\n");
3174e98e3e1Schristos       lf_putstr (file, "      {\n");
3184e98e3e1Schristos       lf_putstr (file, "        sim_events_process (sd);\n");
3194e98e3e1Schristos       lf_putstr (file, "      }\n");
3204e98e3e1Schristos       lf_putstr (file, "    current_cpu = 0;\n");
3214e98e3e1Schristos       lf_putstr (file, "  }\n");
3224e98e3e1Schristos 
3234e98e3e1Schristos       /* tail */
3244e98e3e1Schristos       lf_indent (file, -4);
3254e98e3e1Schristos       lf_putstr (file, "  }\n");
3264e98e3e1Schristos     }
3274e98e3e1Schristos 
3284e98e3e1Schristos 
3294e98e3e1Schristos   lf_indent (file, -2);
3304e98e3e1Schristos   lf_putstr (file, "}\n");
3314e98e3e1Schristos }
3324e98e3e1Schristos 
3334e98e3e1Schristos 
3344e98e3e1Schristos /****************************************************************/
3354e98e3e1Schristos 
3364e98e3e1Schristos void
3374e98e3e1Schristos print_engine_run_function_header (lf *file,
3384b169a6bSchristos 				  const char *processor,
3394e98e3e1Schristos 				  function_decl_type decl_type)
3404e98e3e1Schristos {
3414e98e3e1Schristos   int indent;
3424e98e3e1Schristos   lf_printf (file, "\n");
3434e98e3e1Schristos   switch (decl_type)
3444e98e3e1Schristos     {
3454e98e3e1Schristos     case is_function_declaration:
3464e98e3e1Schristos       lf_print__function_type (file, "void", "INLINE_ENGINE", "\n");
3474e98e3e1Schristos       break;
3484e98e3e1Schristos     case is_function_definition:
3494e98e3e1Schristos       lf_print__function_type (file, "void", "INLINE_ENGINE", " ");
3504e98e3e1Schristos       break;
3514e98e3e1Schristos     case is_function_variable:
3524e98e3e1Schristos       lf_printf (file, "void (*");
3534e98e3e1Schristos       break;
3544e98e3e1Schristos     }
3554e98e3e1Schristos   indent = print_function_name (file, "run", NULL,	/* format name */
3564e98e3e1Schristos 				processor, NULL,	/* expanded bits */
3574e98e3e1Schristos 				function_name_prefix_engine);
3584e98e3e1Schristos   switch (decl_type)
3594e98e3e1Schristos     {
3604e98e3e1Schristos     case is_function_definition:
3614e98e3e1Schristos       lf_putstr (file, "\n(");
3624e98e3e1Schristos       indent = 1;
3634e98e3e1Schristos       break;
3644e98e3e1Schristos     case is_function_declaration:
3654e98e3e1Schristos       indent += lf_printf (file, " (");
3664e98e3e1Schristos       break;
3674e98e3e1Schristos     case is_function_variable:
3684e98e3e1Schristos       lf_putstr (file, ")\n(");
3694e98e3e1Schristos       indent = 1;
3704e98e3e1Schristos       break;
3714e98e3e1Schristos     }
3724e98e3e1Schristos   lf_indent (file, +indent);
3734e98e3e1Schristos   lf_printf (file, "SIM_DESC sd,\n");
3744e98e3e1Schristos   lf_printf (file, "int next_cpu_nr,\n");
3754e98e3e1Schristos   lf_printf (file, "int nr_cpus,\n");
3764e98e3e1Schristos   lf_printf (file, "int siggnal)");
3774e98e3e1Schristos   lf_indent (file, -indent);
3784e98e3e1Schristos   switch (decl_type)
3794e98e3e1Schristos     {
3804e98e3e1Schristos     case is_function_definition:
3814e98e3e1Schristos       lf_putstr (file, "\n");
3824e98e3e1Schristos       break;
3834e98e3e1Schristos     case is_function_variable:
3844e98e3e1Schristos     case is_function_declaration:
3854e98e3e1Schristos       lf_putstr (file, ";\n");
3864e98e3e1Schristos       break;
3874e98e3e1Schristos     }
3884e98e3e1Schristos }
3894e98e3e1Schristos 
3904e98e3e1Schristos 
3914e98e3e1Schristos void
3924e98e3e1Schristos gen_engine_h (lf *file,
3934b169a6bSchristos 	      const gen_table *gen,
3944b169a6bSchristos 	      const insn_table *isa,
3954b169a6bSchristos 	      cache_entry *cache_rules)
3964e98e3e1Schristos {
3974e98e3e1Schristos   gen_list *entry;
3984e98e3e1Schristos   for (entry = gen->tables; entry != NULL; entry = entry->next)
3994e98e3e1Schristos     {
4004e98e3e1Schristos       print_engine_run_function_header (file,
4014e98e3e1Schristos 					(options.gen.multi_sim
4024e98e3e1Schristos 					 ? entry->model->name
4034e98e3e1Schristos 					 : NULL), is_function_declaration);
4044e98e3e1Schristos     }
4054e98e3e1Schristos }
4064e98e3e1Schristos 
4074e98e3e1Schristos 
4084e98e3e1Schristos void
4094e98e3e1Schristos gen_engine_c (lf *file,
4104b169a6bSchristos 	      const gen_table *gen,
4114b169a6bSchristos 	      const insn_table *isa,
4124b169a6bSchristos 	      cache_entry *cache_rules)
4134e98e3e1Schristos {
4144b169a6bSchristos   const gen_list *entry;
4154e98e3e1Schristos   /* the intro */
4164e98e3e1Schristos   print_includes (file);
4174e98e3e1Schristos   print_include_inline (file, options.module.semantics);
4184e98e3e1Schristos   print_include (file, options.module.engine);
4194e98e3e1Schristos   lf_printf (file, "\n");
4204e98e3e1Schristos   lf_printf (file, "#include \"sim-assert.h\"\n");
4214e98e3e1Schristos   lf_printf (file, "\n");
4224e98e3e1Schristos   print_idecode_globals (file);
4234e98e3e1Schristos   lf_printf (file, "\n");
4244e98e3e1Schristos 
4254e98e3e1Schristos   for (entry = gen->tables; entry != NULL; entry = entry->next)
4264e98e3e1Schristos     {
4274e98e3e1Schristos       switch (options.gen.code)
4284e98e3e1Schristos 	{
4294e98e3e1Schristos 	case generate_calls:
4304e98e3e1Schristos 	  print_idecode_lookups (file, entry->table, cache_rules);
4314e98e3e1Schristos 
4324e98e3e1Schristos 	  /* output the main engine routine */
4334e98e3e1Schristos 	  print_engine_run_function_header (file,
4344e98e3e1Schristos 					    (options.gen.multi_sim
4354e98e3e1Schristos 					     ? entry->model->name
4364e98e3e1Schristos 					     : NULL), is_function_definition);
4374e98e3e1Schristos 	  print_run_body (file, entry->table);
4384e98e3e1Schristos 	  break;
4394e98e3e1Schristos 
4404e98e3e1Schristos 	case generate_jumps:
4414e98e3e1Schristos 	  ERROR ("Jumps currently unimplemented");
4424e98e3e1Schristos 	  break;
4434e98e3e1Schristos 	}
4444e98e3e1Schristos     }
4454e98e3e1Schristos }
446