Ejemplo n.º 1
0
static void
gen_idecode_c (lf *file,
	       gen_table *gen,
	       insn_table *isa,
	       cache_entry *cache_rules)
{
  /* the intro */
  print_includes (file);
  print_include_inline (file, options.module.semantics);
  lf_printf (file, "\n");

  print_idecode_globals (file);
  lf_printf (file, "\n");
  
  switch (options.gen.code)
    {
    case generate_calls:
      {
	gen_list *entry;
	for (entry = gen->tables; entry != NULL; entry = entry->next)
	  {
	    print_idecode_lookups (file, entry->table, cache_rules);
	
	    /* output the main idecode routine */
	    if (!options.gen.icache)
	      {
		print_idecode_issue_function_header (file,
						     (options.gen.multi_sim
						      ? entry->model->name
						      : NULL),
						     1/*is definition*/,
						     1/*ALWAYS ONE WORD*/);
		lf_printf (file, "{\n");
		lf_indent (file, +2);
		lf_printf (file, "%sinstruction_address nia;\n",
			   options.module.global.prefix.l);
		print_idecode_body (file, entry->table, "nia =");
		lf_printf (file, "return nia;");
		lf_indent (file, -2);
		lf_printf (file, "}\n");
	      }
	  }
	break;
      }
    case generate_jumps:
      {
	lf_print__this_file_is_empty (file, "generating a jump engine");
	break;
      }
    }
}
Ejemplo n.º 2
0
static void
print_run_body (lf *file, gen_entry *table)
{
  /* Output the function to execute real code:

     Unfortunatly, there are multiple cases to consider vis:

     <icache> X <smp>

     Consequently this function is written in multiple different ways */

  lf_printf (file, "{\n");
  lf_indent (file, +2);
  if (!options.gen.smp)
    {
      lf_printf (file, "%sinstruction_address cia;\n",
		 options.module.global.prefix.l);
    }
  lf_printf (file, "int current_cpu = next_cpu_nr;\n");

  if (options.gen.icache)
    {
      lf_printf (file, "/* flush the icache of a possible break insn */\n");
      lf_printf (file, "{\n");
      lf_printf (file, "  int cpu_nr;\n");
      lf_printf (file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
      lf_printf (file, "    cpu_flush_icache (STATE_CPU (sd, cpu_nr));\n");
      lf_printf (file, "}\n");
    }

  if (!options.gen.smp)
    {

      lf_putstr (file, "\
/* CASE 1: NO SMP (with or with out instruction cache).\n\
\n\
In this case, we can take advantage of the fact that the current\n\
instruction address (CIA) does not need to be read from / written to\n\
the CPU object after the execution of an instruction.\n\
\n\
Instead, CIA is only saved when the main loop exits.  This occures\n\
when either sim_engine_halt or sim_engine_restart is called.  Both of\n\
these functions save the current instruction address before halting /\n\
restarting the simulator.\n\
\n\
As a variation, there may also be support for an instruction cracking\n\
cache. */\n\
\n\
");

      lf_putstr (file, "\n");
      lf_putstr (file, "/* prime the main loop */\n");
      lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
      lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
      lf_putstr (file, "cia = CPU_PC_GET (CPU);\n");

      lf_putstr (file, "\n");
      lf_putstr (file, "while (1)\n");
      lf_putstr (file, "  {\n");
      lf_indent (file, +4);

      lf_printf (file, "%sinstruction_address nia;\n",
		 options.module.global.prefix.l);

      lf_printf (file, "\n");
      if (!options.gen.icache)
	{
	  lf_printf (file,
		     "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
		     options.module.global.prefix.l, options.insn_bit_size);
	  print_engine_issue_prefix_hook (file);
	  print_idecode_body (file, table, "nia = ");
	  print_engine_issue_postfix_hook (file);
	}
      else
	{
	  lf_putstr (file, "idecode_cache *cache_entry =\n");
	  lf_putstr (file, "  cpu_icache_entry (cpu, cia);\n");
	  lf_putstr (file, "if (cache_entry->address == cia)\n");
	  lf_putstr (file, "  {\n");
	  lf_indent (file, -4);
	  lf_putstr (file, "/* cache hit */\n");
	  lf_putstr (file,
		     "idecode_semantic *const semantic = cache_entry->semantic;\n");
	  lf_putstr (file, "cia = semantic (cpu, cache_entry, cia);\n");
	  /* tail */
	  lf_indent (file, -4);
	  lf_putstr (file, "  }\n");
	  lf_putstr (file, "else\n");
	  lf_putstr (file, "  {\n");
	  lf_indent (file, +4);
	  lf_putstr (file, "/* cache miss */\n");
	  if (!options.gen.semantic_icache)
	    {
	      lf_putstr (file, "idecode_semantic *semantic;\n");
	    }
	  lf_printf (file, "instruction_word instruction = IMEM%d (cia);\n",
		     options.insn_bit_size);
	  lf_putstr (file, "if (WITH_MON != 0)\n");
	  lf_putstr (file,
		     "  mon_event (mon_event_icache_miss, cpu, cia);\n");
	  if (options.gen.semantic_icache)
	    {
	      lf_putstr (file, "{\n");
	      lf_indent (file, +2);
	      print_engine_issue_prefix_hook (file);
	      print_idecode_body (file, table, "nia =");
	      print_engine_issue_postfix_hook (file);
	      lf_indent (file, -2);
	      lf_putstr (file, "}\n");
	    }
	  else
	    {
	      print_engine_issue_prefix_hook (file);
	      print_idecode_body (file, table, "semantic =");
	      lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
	      print_engine_issue_postfix_hook (file);
	    }
	  lf_indent (file, -4);
	  lf_putstr (file, "  }\n");
	}

      /* update the cpu if necessary */
      switch (options.gen.nia)
	{
	case nia_is_cia_plus_one:
	  lf_printf (file, "\n");
	  lf_printf (file, "/* Update the instruction address */\n");
	  lf_printf (file, "cia = nia;\n");
	  break;
	case nia_is_void:
	case nia_is_invalid:
	  ERROR ("engine gen when NIA complex");
	}

      /* events */
      lf_putstr (file, "\n");
      lf_putstr (file, "/* process any events */\n");
      lf_putstr (file, "if (sim_events_tick (sd))\n");
      lf_putstr (file, "  {\n");
      lf_putstr (file, "    CPU_PC_SET (CPU, cia);\n");
      lf_putstr (file, "    sim_events_process (sd);\n");
      lf_putstr (file, "    cia = CPU_PC_GET (CPU);\n");
      lf_putstr (file, "  }\n");

      lf_indent (file, -4);
      lf_printf (file, "  }\n");
    }