static void
model_c_function(insn_table *table,
		 lf *file,
		 table_entry *function,
		 const char *prefix)
{
  if (function->fields[function_type] == NULL
      || function->fields[function_type][0] == '\0') {
    error("Model function return type not specified for %s", function->fields[function_name]);
  }
  else {
    lf_printf(file, "\n");
    lf_print_function_type(file, function->fields[function_type], prefix, "\n");
    lf_printf(file, "%s(%s)\n",
	      function->fields[function_name],
	      function->fields[function_param]);
  }
  table_entry_print_cpp_line_nr(file, function);
  lf_printf(file, "{\n");
  if (function->annex) {
    lf_indent(file, +2);
    lf_print__c_code(file, function->annex);
    lf_indent(file, -2);
  }
  lf_printf(file, "}\n");
  lf_print__internal_reference(file);
  lf_printf(file, "\n");
}
Exemple #2
0
static void
itable_c_insn (lf *file,
	       insn_table *isa, insn_entry * instruction, void *data)
{
  lf_printf (file, "{ ");
  lf_indent (file, +2);
  print_function_name (file,
		       instruction->name,
		       instruction->format_name,
		       NULL, NULL, function_name_prefix_itable);
  lf_printf (file, ",\n");
  lf_printf (file, "\"");
  print_insn_words (file, instruction);
  lf_printf (file, "\",\n");
  lf_printf (file, "\"%s\",\n", instruction->format_name);

  itable_print_set (file, isa->flags, instruction->flags);
  itable_print_set (file, isa->options, instruction->options);
  itable_print_set (file, isa->model->processors, instruction->processors);

  lf_printf (file, "\"%s\",\n", instruction->name);
  lf_printf (file, "\"%s\",\n",
	     filter_filename (instruction->line->file_name));
  lf_printf (file, "%d,\n", instruction->line->line_nr);
  lf_printf (file, "},\n");
  lf_indent (file, -2);
}
static void
print_semantic_function_header(lf *file,
			       const char *basename,
			       insn_bits *expanded_bits,
			       int is_function_definition)
{
  int indent;
  lf_printf(file, "\n");
  lf_print_function_type(file, SEMANTIC_FUNCTION_TYPE, "PSIM_EXTERN_SEMANTICS",
			 (is_function_definition ? "\n" : " "));
  indent = print_function_name(file,
			       basename,
			       expanded_bits,
			       function_name_prefix_semantics);
  if (is_function_definition)
    lf_indent(file, +indent);
  else
    lf_printf(file, "\n");
  lf_printf(file, "(%s)", SEMANTIC_FUNCTION_FORMAL);
  if (is_function_definition)
    lf_indent(file, -indent);
  else
    lf_printf(file, ";");
  lf_printf(file, "\n");
}
Exemple #4
0
static void
itable_print_enum (lf *file, filter *set, char *name)
{
  char *elem;
  lf_printf (file, "typedef enum {\n");
  lf_indent (file, +2);
  for (elem = filter_next (set, "");
       elem != NULL; elem = filter_next (set, elem))
    {
      lf_printf (file, "%sitable_%s_%s,\n",
		 options.module.itable.prefix.l, name, elem);
      if (strlen (options.module.itable.prefix.l) > 0)
	{
	  lf_indent_suppress (file);
	  lf_printf (file, "#define itable_%s_%s %sitable_%s_%s\n",
		     name, elem, options.module.itable.prefix.l, name, elem);
	}
    }
  lf_printf (file, "nr_%sitable_%ss,\n", options.module.itable.prefix.l,
	     name);

  lf_indent (file, -2);
  lf_printf (file, "} %sitable_%ss;\n", options.module.itable.prefix.l, name);
  if (strlen (options.module.itable.prefix.l) > 0)
    {
      lf_indent_suppress (file);
      lf_printf (file, "#define itable_%ss %sitable_%ss\n",
		 name, options.module.itable.prefix.l, name);
      lf_indent_suppress (file);
      lf_printf (file, "#define nr_itable_%ss nr_%sitable_%ss\n",
		 name, options.module.itable.prefix.l, name);
    }
}
Exemple #5
0
static void
print_support_function_name (lf *file,
			     function_entry * function,
			     int is_function_definition)
{
  if (function->is_internal)
    {
      lf_print__function_type_function (file, print_semantic_function_type,
					"INLINE_SUPPORT",
					(is_function_definition ? "\n" :
					 " "));
      print_function_name (file, function->name, NULL, NULL, NULL,
			   function_name_prefix_semantics);
      lf_printf (file, "\n(");
      lf_indent (file, +1);
      print_semantic_function_formal (file, 0);
      lf_indent (file, -1);
      lf_printf (file, ")");
      if (!is_function_definition)
	lf_printf (file, ";");
      lf_printf (file, "\n");
    }
  else
    {
      /* map the name onto a globally valid name */
      if (!is_function_definition
	  && strcmp (options.module.support.prefix.l, "") != 0)
	{
	  lf_indent_suppress (file);
	  lf_printf (file, "#define %s %s%s\n",
		     function->name,
		     options.module.support.prefix.l, function->name);
	}
      lf_print__function_type (file,
			       function->type,
			       "INLINE_SUPPORT",
			       (is_function_definition ? "\n" : " "));
      lf_printf (file, "%s%s\n(",
		 options.module.support.prefix.l, function->name);
      if (options.gen.smp)
	lf_printf (file,
		   "sim_cpu *cpu, %sinstruction_address cia, int MY_INDEX",
		   options.module.support.prefix.l);
      else
	lf_printf (file,
		   "SIM_DESC sd, %sinstruction_address cia, int MY_INDEX",
		   options.module.support.prefix.l);
      if (function->param != NULL && strlen (function->param) > 0)
	lf_printf (file, ", %s", function->param);
      lf_printf (file, ")%s", (is_function_definition ? "\n" : ";\n"));
    }
}
Exemple #6
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;
      }
    }
}
void
print_semantic_body(lf *file,
		    insn *instruction,
		    insn_bits *expanded_bits,
		    opcode_field *opcodes)
{
  print_itrace(file, instruction->file_entry, 0/*put_value_in_cache*/);

  /* validate the instruction, if a cache this has already been done */
  if (!(code & generate_with_icache))
    print_idecode_validate(file, instruction, opcodes);

  /* generate the profiling call - this is delayed until after the
     instruction has been verified */
  lf_printf(file, "\n");
  lf_printf(file, "/* monitoring: */\n");
  lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n");
  lf_printf(file, "  mon_issue(");
  print_function_name(file,
		      instruction->file_entry->fields[insn_name],
		      NULL,
		      function_name_prefix_itable);
  lf_printf(file, ", processor, cia);\n");
  lf_printf(file, "}\n");

  /* generate the code (or at least something */
  lf_printf(file, "\n");
  lf_printf(file, "/* semantics: */\n");
  lf_printf(file, "nia = cia + %d;\n", insn_bit_size / 8);
  if (instruction->file_entry->annex != NULL) {
    /* true code */
    table_entry_print_cpp_line_nr(file, instruction->file_entry);
    lf_printf(file, "{\n");
    lf_indent(file, +2);
    lf_print__c_code(file, instruction->file_entry->annex);
    lf_indent(file, -2);
    lf_printf(file, "}\n");
    lf_print__internal_reference(file);
  }
  else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
    lf_print__internal_reference(file);
  }
  else {
    /* abort so it is implemented now */
    table_entry_print_cpp_line_nr(file, instruction->file_entry);
    lf_putstr(file, "error(\"%s:%d:0x%08lx:%s unimplemented\\n\",\n");
    lf_printf(file, "      itable[MY_INDEX].file, itable[MY_INDEX].line_nr, (long)cia, itable[MY_INDEX].name);\n");
    lf_print__internal_reference(file);
  }
}
Exemple #8
0
static void
print_c_semantic (lf *file,
		  insn_entry * instruction,
		  opcode_bits *expanded_bits,
		  insn_opcodes *opcodes,
		  cache_entry *cache_rules, int nr_prefetched_words)
{

  lf_printf (file, "{\n");
  lf_indent (file, +2);

  print_my_defines (file,
		    instruction->name,
		    instruction->format_name, expanded_bits);
  lf_printf (file, "\n");
  print_icache_body (file,
		     instruction,
		     expanded_bits,
		     cache_rules,
		     (options.gen.direct_access
		      ? define_variables
		      : declare_variables),
		     (options.gen.icache
		      ? get_values_from_icache
		      : do_not_use_icache), nr_prefetched_words);

  lf_printf (file, "%sinstruction_address nia;\n",
	     options.module.global.prefix.l);
  print_semantic_body (file, instruction, expanded_bits, opcodes);
  lf_printf (file, "return nia;\n");

  /* generate something to clean up any #defines created for the cache */
  if (options.gen.direct_access)
    {
      print_icache_body (file,
			 instruction,
			 expanded_bits,
			 cache_rules,
			 undef_variables,
			 (options.gen.icache
			  ? get_values_from_icache
			  : do_not_use_icache), nr_prefetched_words);
    }

  lf_indent (file, -2);
  lf_printf (file, "}\n");
}
Exemple #9
0
static void
itable_print_names (lf *file, filter *set, char *name)
{
  char *elem;
  lf_printf (file, "const char *%sitable_%s_names[nr_%sitable_%ss + 1] = {\n",
	     options.module.itable.prefix.l, name,
	     options.module.itable.prefix.l, name);
  lf_indent (file, +2);
  for (elem = filter_next (set, "");
       elem != NULL; elem = filter_next (set, elem))
    {
      lf_printf (file, "\"%s\",\n", elem);
    }
  lf_printf (file, "0,\n");
  lf_indent (file, -2);
  lf_printf (file, "};\n");
}
static void
print_c_semantic(lf *file,
		 insn *instruction,
		 insn_bits *expanded_bits,
		 opcode_field *opcodes,
		 cache_table *cache_rules)
{

  lf_printf(file, "{\n");
  lf_indent(file, +2);

  print_my_defines(file, expanded_bits, instruction->file_entry);
  lf_printf(file, "\n");
  print_icache_body(file,
		    instruction,
		    expanded_bits,
		    cache_rules,
		    ((code & generate_with_direct_access)
		     ? define_variables
		     : declare_variables),
		    ((code & generate_with_icache)
		     ? get_values_from_icache
		     : do_not_use_icache));

  lf_printf(file, "unsigned_word nia;\n");
  print_semantic_body(file,
		      instruction,
		      expanded_bits,
		      opcodes);
  lf_printf(file, "return nia;\n");

  /* generate something to clean up any #defines created for the cache */
  if (code & generate_with_direct_access)
    print_icache_body(file,
		      instruction,
		      expanded_bits,
		      cache_rules,
		      undef_variables,
		      ((code & generate_with_icache)
		       ? get_values_from_icache
		       : do_not_use_icache));

  lf_indent(file, -2);
  lf_printf(file, "}\n");
}
Exemple #11
0
static void
print_semantic_function_header (lf *file,
				const char *basename,
				const char *format_name,
				opcode_bits *expanded_bits,
				int is_function_definition,
				int nr_prefetched_words)
{
  int indent;
  lf_printf (file, "\n");
  lf_print__function_type_function (file, print_semantic_function_type,
				    "EXTERN_SEMANTICS",
				    (is_function_definition ? "\n" : " "));
  indent = print_function_name (file,
				basename,
				format_name,
				NULL,
				expanded_bits,
				function_name_prefix_semantics);
  if (is_function_definition)
    {
      indent += lf_printf (file, " ");
      lf_indent (file, +indent);
    }
  else
    {
      lf_printf (file, "\n");
    }
  lf_printf (file, "(");
  lf_indent (file, +1);
  print_semantic_function_formal (file, nr_prefetched_words);
  lf_indent (file, -1);
  lf_printf (file, ")");
  if (is_function_definition)
    {
      lf_indent (file, -indent);
    }
  else
    {
      lf_printf (file, ";");
    }
  lf_printf (file, "\n");
}
Exemple #12
0
void
print_icache_internal_function_definition (lf *file,
					   function_entry * function,
					   void *data)
{
  ASSERT (options.gen.icache);
  if (function->is_internal)
    {
      lf_printf (file, "\n");
      lf_print__function_type_function (file, print_icache_function_type,
					"INLINE_ICACHE", "\n");
      print_function_name (file,
			   function->name,
			   NULL, NULL, NULL, function_name_prefix_icache);
      lf_printf (file, "\n(");
      print_icache_function_formal (file, 0);
      lf_printf (file, ")\n");
      lf_printf (file, "{\n");
      lf_indent (file, +2);
      lf_printf (file, "/* semantic routine */\n");
      if (options.gen.semantic_icache)
	{
	  lf_print__line_ref (file, function->code->line);
	  table_print_code (file, function->code);
	  lf_printf (file,
		     "error (\"Internal function must longjump\\n\");\n");
	  lf_printf (file, "return 0;\n");
	}
      else
	{
	  lf_printf (file, "return ");
	  print_function_name (file,
			       function->name,
			       NULL,
			       NULL, NULL, function_name_prefix_semantics);
	  lf_printf (file, ";\n");
	}

      lf_print__internal_ref (file);
      lf_indent (file, -2);
      lf_printf (file, "}\n");
    }
}
Exemple #13
0
static void
gen_semantics_h (lf *file,
		 insn_list *semantics,
		 int max_nr_words)
{
  int word_nr;
  insn_list *semantic;
  for (word_nr = -1; word_nr <= max_nr_words; word_nr++)
    {
      lf_printf (file, "typedef ");
      print_semantic_function_type (file);
      lf_printf (file, " %sidecode_semantic",
		 options.module.global.prefix.l);
      if (word_nr >= 0)
	lf_printf (file, "_%d", word_nr);
      lf_printf (file, "\n(");
      lf_indent (file, +1);
      print_semantic_function_formal (file, word_nr);
      lf_indent (file, -1);
      lf_printf (file, ");\n");
      lf_printf (file, "\n");
    }
  switch (options.gen.code)
    {
    case generate_calls:
      for (semantic = semantics; semantic != NULL; semantic = semantic->next)
	{
	  /* Ignore any special/internal instructions */
	  if (semantic->insn->nr_words == 0)
	    continue;
	  print_semantic_declaration (file,
				      semantic->insn,
				      semantic->expanded_bits,
				      semantic->opcodes,
				      semantic->nr_prefetched_words);
	}
      break;
    case generate_jumps:
      lf_print__this_file_is_empty (file, "generating jumps");
      break;
    }
}
Exemple #14
0
static int
print_itrace_prefix (lf *file)
{
  const char *prefix = "trace_prefix (";
  int indent = strlen (prefix);
  lf_printf (file, "%sSD, CPU, cia, CIA, TRACE_LINENUM_P (CPU), \\\n", prefix);
  lf_indent (file, +indent);
  lf_printf (file, "%sitable[MY_INDEX].file, \\\n", options.module.itable.prefix.l);
  lf_printf (file, "%sitable[MY_INDEX].line_nr, \\\n", options.module.itable.prefix.l);
  lf_printf (file, "\"");
  return indent;
}
Exemple #15
0
static void
support_c_function (lf *file, function_entry * function, void *data)
{
  ASSERT (function->type != NULL);
  print_support_function_name (file, function, 1 /*!is_definition */ );
  lf_printf (file, "{\n");
  lf_indent (file, +2);
  if (function->code == NULL)
    error (function->line, "Function without body (or null statement)");
  lf_print__line_ref (file, function->code->line);
  table_print_code (file, function->code);
  if (function->is_internal)
    {
      lf_printf (file,
		 "sim_engine_abort (SD, CPU, cia, \"Internal function must longjump\\n\");\n");
      lf_printf (file, "return cia;\n");
    }
  lf_indent (file, -2);
  lf_printf (file, "}\n");
  lf_print__internal_ref (file);
  lf_printf (file, "\n");
}
Exemple #16
0
void
print_icache_internal_function_definition(insn_table *table,
					  lf *file,
					  void *data,
					  table_entry *function)
{
  ASSERT((code & generate_with_icache) != 0);
  if (it_is("internal", function->fields[insn_flags])) {
    lf_printf(file, "\n");
    lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
			   "\n");
    print_function_name(file,
			function->fields[insn_name],
			NULL,
			function_name_prefix_icache);
    lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
    lf_printf(file, "{\n");
    lf_indent(file, +2);
    lf_printf(file, "/* semantic routine */\n");
    table_entry_print_cpp_line_nr(file, function);
    if ((code & generate_with_semantic_icache)) {
      lf_print__c_code(file, function->annex);
      lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
      lf_printf(file, "return 0;\n");
    }
    else {
      lf_printf(file, "return ");
      print_function_name(file,
			  function->fields[insn_name],
			  NULL,
			  function_name_prefix_semantics);
      lf_printf(file, ";\n");
    }
    
    lf_print__internal_reference(file);
    lf_indent(file, -2);
    lf_printf(file, "}\n");
  }
}
Exemple #17
0
static void
support_c_function(insn_table *table,
		   lf *file,
		   void *data,
		   table_entry *function)
{
  ASSERT(function->fields[function_type] != NULL);
  print_support_function_name(file,
			      function,
			      1/*!is_definition*/);
  table_entry_print_cpp_line_nr(file, function);
  lf_printf(file, "{\n");
  lf_indent(file, +2);
  lf_print__c_code(file, function->annex);
  if (it_is("internal", function->fields[insn_flags])) {
    lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
    lf_printf(file, "return 0;\n");
  }
  lf_indent(file, -2);
  lf_printf(file, "}\n");
  lf_print__internal_reference(file);
  lf_printf(file, "\n");
}
Exemple #18
0
static void
gen_run_c (lf *file,
	   gen_table *gen)
{
  gen_list *entry;
  lf_printf (file, "#include \"sim-main.h\"\n");
  lf_printf (file, "#include \"engine.h\"\n");
  lf_printf (file, "#include \"idecode.h\"\n");
  lf_printf (file, "#include \"bfd.h\"\n");
  lf_printf (file, "\n");

  if (options.gen.multi_sim)
    {
      print_idecode_issue_function_header (file, NULL, is_function_variable, 1);
      lf_printf (file, "\n");
      print_engine_run_function_header (file, NULL, is_function_variable);
      lf_printf (file, "\n");
    }
  
  lf_printf (file, "void\n");
  lf_printf (file, "sim_engine_run (SIM_DESC sd,\n");
  lf_printf (file, "                int next_cpu_nr,\n");
  lf_printf (file, "                int nr_cpus,\n");
  lf_printf (file, "                int siggnal)\n");
  lf_printf (file, "{\n");
  lf_indent (file, +2);
  if (options.gen.multi_sim)
    {
      lf_printf (file, "int mach;\n");
      lf_printf (file, "if (STATE_ARCHITECTURE (sd) == NULL)\n");
      lf_printf (file, "  mach = 0;\n");
      lf_printf (file, "else\n");
      lf_printf (file, "  mach = STATE_ARCHITECTURE (sd)->mach;\n");
      lf_printf (file, "switch (mach)\n");
      lf_printf (file, "  {\n");
      lf_indent (file, +2);
      for (entry = gen->tables; entry != NULL; entry = entry->next)
	{
	  if (options.gen.default_model != NULL
	      && (strcmp (entry->model->name, options.gen.default_model) == 0
		  || strcmp (entry->model->full_name, options.gen.default_model) == 0))
	    lf_printf (file, "default:\n");
	  lf_printf (file, "case bfd_mach_%s:\n", entry->model->full_name);
	  lf_indent (file, +2);
	  print_function_name (file,
			       "issue",
			       NULL, /* format name */
			       NULL, /* NO processor */
			       NULL, /* expanded bits */
			       function_name_prefix_idecode);
	  lf_printf (file, " = ");
	  print_function_name (file,
			       "issue",
			       NULL, /* format name */
			       entry->model->name,
			       NULL, /* expanded bits */
			       function_name_prefix_idecode);
	  lf_printf (file, ";\n");
	  print_function_name (file,
			       "run",
			       NULL, /* format name */
			       NULL, /* NO processor */
			       NULL, /* expanded bits */
			       function_name_prefix_engine);
	  lf_printf (file, " = ");
	  print_function_name (file,
			       "run",
			       NULL, /* format name */
			       entry->model->name,
			       NULL, /* expanded bits */
			       function_name_prefix_engine);
	  lf_printf (file, ";\n");
	  lf_printf (file, "break;\n");
	  lf_indent (file, -2);
	}
      if (options.gen.default_model == NULL)
	{
	  lf_printf (file, "default:\n");
	  lf_indent (file, +2);
	  lf_printf (file, "sim_engine_abort (sd, NULL, NULL_CIA,\n");
	  lf_printf (file, "                  \"sim_engine_run - unknown machine\");\n");
	  lf_printf (file, "break;\n");
	  lf_indent (file, -2);
	}
      lf_indent (file, -2);
      lf_printf (file, "  }\n");
    }
  print_function_name (file,
		       "run",
		       NULL, /* format name */
		       NULL, /* NO processor */
		       NULL, /* expanded bits */
		       function_name_prefix_engine);
  lf_printf (file, " (sd, next_cpu_nr, nr_cpus, siggnal);\n");
  lf_indent (file, -2);
  lf_printf (file, "}\n");
}
Exemple #19
0
static void
print_icache_function(lf *file,
		      insn *instruction,
		      insn_bits *expanded_bits,
		      opcode_field *opcodes,
		      cache_table *cache_rules)
{
  int indent;

  /* generate code to enter decoded instruction into the icache */
  lf_printf(file, "\n");
  lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
  indent = print_function_name(file,
			       instruction->file_entry->fields[insn_name],
			       expanded_bits,
			       function_name_prefix_icache);
  lf_indent(file, +indent);
  lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
  lf_indent(file, -indent);
  
  /* function header */
  lf_printf(file, "{\n");
  lf_indent(file, +2);
  
  print_my_defines(file, expanded_bits, instruction->file_entry);
  print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
  
  print_idecode_validate(file, instruction, opcodes);
  
  lf_printf(file, "\n");
  lf_printf(file, "{\n");
  lf_indent(file, +2);
  if ((code & generate_with_semantic_icache))
    lf_printf(file, "unsigned_word nia;\n");
  print_icache_body(file,
		    instruction,
		    expanded_bits,
		    cache_rules,
		    ((code & generate_with_direct_access)
		     ? define_variables
		     : declare_variables),
		    ((code & generate_with_semantic_icache)
		     ? both_values_and_icache
		     : put_values_in_icache));
  
  lf_printf(file, "\n");
  lf_printf(file, "cache_entry->address = cia;\n");
  lf_printf(file, "cache_entry->semantic = ");
  print_function_name(file,
		      instruction->file_entry->fields[insn_name],
		      expanded_bits,
		      function_name_prefix_semantics);
  lf_printf(file, ";\n");
  lf_printf(file, "\n");

  if ((code & generate_with_semantic_icache)) {
    lf_printf(file, "/* semantic routine */\n");
    print_semantic_body(file,
			instruction,
			expanded_bits,
			opcodes);
    lf_printf(file, "return nia;\n");
  }
  
  if (!(code & generate_with_semantic_icache)) {
    lf_printf(file, "/* return the function proper */\n");
    lf_printf(file, "return ");
    print_function_name(file,
			instruction->file_entry->fields[insn_name],
			expanded_bits,
			function_name_prefix_semantics);
    lf_printf(file, ";\n");
  }
  
  if ((code & generate_with_direct_access))
    print_icache_body(file,
		      instruction,
		      expanded_bits,
		      cache_rules,
		      undef_variables,
		      ((code & generate_with_semantic_icache)
		       ? both_values_and_icache
		       : put_values_in_icache));

  lf_indent(file, -2);
  lf_printf(file, "}\n");
  lf_indent(file, -2);
  lf_printf(file, "}\n");
}
Exemple #20
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");
    }
Exemple #21
0
void
print_itrace (lf *file,
	      insn_entry *insn,
	      int idecode)
{
  /* NB: Here we escape each EOLN. This is so that the the compiler
     treats a trace function call as a single line.  Consequently any
     errors in the line are refered back to the same igen assembler
     source line */
  const char *phase = (idecode) ? "DECODE" : "INSN";
  lf_printf (file, "\n");
  lf_indent_suppress (file);
  lf_printf (file, "#if defined (WITH_TRACE)\n");
  lf_printf (file, "/* generate a trace prefix if any tracing enabled */\n");
  lf_printf (file, "if (TRACE_ANY_P (CPU))\n");
  lf_printf (file, "  {\n");
  lf_indent (file, +4);
  {
    if (insn->mnemonics != NULL)
      {
	insn_mnemonic_entry *assembler = insn->mnemonics;
	int is_first = 1;
	do
	  {
	    if (assembler->condition != NULL)
	      {
		int indent;
		lf_printf (file, "%sif (%s)\n",
			   is_first ? "" : "else ",
			   assembler->condition);
		lf_indent (file, +2);
		lf_print__line_ref (file, assembler->line);
		indent = print_itrace_prefix (file);
		print_itrace_format (file, assembler);
		lf_print__internal_ref (file);
		lf_indent (file, -indent);
		lf_indent (file, -2);
		if (assembler->next == NULL)
		  error (assembler->line, "Missing final unconditional assembler\n");
	      }
	    else
	      {
		int indent;
		if (!is_first)
		  {
		    lf_printf (file, "else\n");
		    lf_indent (file, +2);
		  }
		lf_print__line_ref (file, assembler->line);
		indent = print_itrace_prefix (file);
		print_itrace_format (file, assembler);
		lf_print__internal_ref (file);
		lf_indent (file, -indent);
		if (!is_first)
		  lf_indent (file, -2);
		if (assembler->next != NULL)
		  error (assembler->line, "Unconditional assembler is not last\n");
	      }
	    is_first = 0;
	    assembler = assembler->next;
	  }
	while (assembler != NULL);
      }
    else
      {
	int indent;
	lf_indent (file, +2);
	lf_print__line_ref (file, insn->line);
	indent = print_itrace_prefix (file);
	lf_printf (file, "%%s\", \\\n");
	lf_printf (file, "itable[MY_INDEX].name);\n");
	lf_print__internal_ref (file);
	lf_indent (file, -indent);
	lf_indent (file, -2);
      }
    lf_printf (file, "/* trace the instruction execution if enabled */\n");
    lf_printf (file, "if (TRACE_%s_P (CPU))\n", phase);
    lf_printf (file, "  trace_generic (SD, CPU, TRACE_%s_IDX, \" %%s\", itable[MY_INDEX].name);\n", phase);
  }
  lf_indent (file, -4);
  lf_printf (file, "  }\n");
  lf_indent_suppress (file);
  lf_printf (file, "#endif\n");
}
Exemple #22
0
void
print_semantic_body (lf *file,
		     insn_entry * instruction,
		     opcode_bits *expanded_bits, insn_opcodes *opcodes)
{
  /* validate the instruction, if a cache this has already been done */
  if (!options.gen.icache)
    {
      print_idecode_validate (file, instruction, opcodes);
    }

  print_itrace (file, instruction, 0 /*put_value_in_cache */ );

  /* generate the instruction profile call - this is delayed until
     after the instruction has been verified.  The count macro
     generated is prefixed by ITABLE_PREFIX */
  {
    lf_printf (file, "\n");
    lf_indent_suppress (file);
    lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n",
	       options.module.itable.prefix.u);
    lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n",
	       options.module.itable.prefix.u);
    lf_indent_suppress (file);
    lf_printf (file, "#endif\n");
  }

  /* generate the model call - this is delayed until after the
     instruction has been verified */
  {
    lf_printf (file, "\n");
    lf_indent_suppress (file);
    lf_printf (file, "#if defined (WITH_MON)\n");
    lf_printf (file, "/* monitoring: */\n");
    lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n");
    lf_printf (file, "  mon_issue (");
    print_function_name (file,
			 instruction->name,
			 instruction->format_name,
			 NULL, NULL, function_name_prefix_itable);
    lf_printf (file, ", cpu, cia);\n");
    lf_indent_suppress (file);
    lf_printf (file, "#endif\n");
    lf_printf (file, "\n");
  }

  /* determine the new instruction address */
  {
    lf_printf (file, "/* keep the next instruction address handy */\n");
    if (options.gen.nia == nia_is_invalid)
      {
	lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n",
		   options.module.global.prefix.u);
      }
    else
      {
	int nr_immeds = instruction->nr_words - 1;
	if (options.gen.delayed_branch)
	  {
	    if (nr_immeds > 0)
	      {
		lf_printf (file, "cia.dp += %d * %d; %s\n",
			   options.insn_bit_size / 8, nr_immeds,
			   "/* skip dp immeds */");
	      }
	    lf_printf (file, "nia.ip = cia.dp; %s\n",
		       "/* instruction pointer */");
	    lf_printf (file, "nia.dp = cia.dp + %d; %s\n",
		       options.insn_bit_size / 8,
		       "/* delayed-slot pointer */");
	  }
	else
	  {
	    if (nr_immeds > 0)
	      {
		lf_printf (file, "nia = cia + %d * (%d + 1); %s\n",
			   options.insn_bit_size / 8, nr_immeds,
			   "/* skip immeds as well */");

	      }
	    else
	      {
		lf_printf (file, "nia = cia + %d;\n",
			   options.insn_bit_size / 8);
	      }
	  }
      }
  }

  /* if conditional, generate code to verify that the instruction
     should be issued */
  if (filter_is_member (instruction->options, "c")
      || options.gen.conditional_issue)
    {
      lf_printf (file, "\n");
      lf_printf (file, "/* execute only if conditional passes */\n");
      lf_printf (file, "if (IS_CONDITION_OK)\n");
      lf_printf (file, "  {\n");
      lf_indent (file, +4);
      /* FIXME - need to log a conditional failure */
    }

  /* Architecture expects a REG to be zero.  Instead of having to
     check every read to see if it is refering to that REG just zap it
     at the start of every instruction */
  if (options.gen.zero_reg)
    {
      lf_printf (file, "\n");
      lf_printf (file, "/* Architecture expects REG to be zero */\n");
      lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
    }

  /* generate the code (or at least something */
  lf_printf (file, "\n");
  lf_printf (file, "/* semantics: */\n");
  if (instruction->code != NULL)
    {
      /* true code */
      lf_printf (file, "{\n");
      lf_indent (file, +2);
      lf_print__line_ref (file, instruction->code->line);
      table_print_code (file, instruction->code);
      lf_indent (file, -2);
      lf_printf (file, "}\n");
      lf_print__internal_ref (file);
    }
  else if (filter_is_member (instruction->options, "nop"))
    {
      lf_print__internal_ref (file);
    }
  else
    {
      const char *prefix = "sim_engine_abort (";
      int indent = strlen (prefix);
      /* abort so it is implemented now */
      lf_print__line_ref (file, instruction->line);
      lf_printf (file, "%sSD, CPU, cia, \\\n", prefix);
      lf_indent (file, +indent);
      lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n",
		 filter_filename (instruction->line->file_name),
		 instruction->line->line_nr);
      lf_printf (file, "(long) CIA, \\\n");
      lf_printf (file, "%sitable[MY_INDEX].name);\n",
		 options.module.itable.prefix.l);
      lf_indent (file, -indent);
      lf_print__internal_ref (file);
    }

  /* Close off the conditional execution */
  if (filter_is_member (instruction->options, "c")
      || options.gen.conditional_issue)
    {
      lf_indent (file, -4);
      lf_printf (file, "  }\n");
    }
}
Exemple #23
0
static void
print_icache_function (lf *file,
		       insn_entry * instruction,
		       opcode_bits *expanded_bits,
		       insn_opcodes *opcodes,
		       cache_entry *cache_rules, int nr_prefetched_words)
{
  int indent;

  /* generate code to enter decoded instruction into the icache */
  lf_printf (file, "\n");
  lf_print__function_type_function (file, print_icache_function_type,
				    "EXTERN_ICACHE", "\n");
  indent = print_function_name (file,
				instruction->name,
				instruction->format_name,
				NULL,
				expanded_bits, function_name_prefix_icache);
  indent += lf_printf (file, " ");
  lf_indent (file, +indent);
  lf_printf (file, "(");
  print_icache_function_formal (file, nr_prefetched_words);
  lf_printf (file, ")\n");
  lf_indent (file, -indent);

  /* function header */
  lf_printf (file, "{\n");
  lf_indent (file, +2);

  print_my_defines (file,
		    instruction->name,
		    instruction->format_name, expanded_bits);
  print_itrace (file, instruction, 1 /*putting-value-in-cache */ );

  print_idecode_validate (file, instruction, opcodes);

  lf_printf (file, "\n");
  lf_printf (file, "{\n");
  lf_indent (file, +2);
  if (options.gen.semantic_icache)
    lf_printf (file, "unsigned_word nia;\n");
  print_icache_body (file,
		     instruction,
		     expanded_bits,
		     cache_rules,
		     (options.gen.direct_access
		      ? define_variables
		      : declare_variables),
		     (options.gen.semantic_icache
		      ? both_values_and_icache
		      : put_values_in_icache), nr_prefetched_words);

  lf_printf (file, "\n");
  lf_printf (file, "cache_entry->address = cia;\n");
  lf_printf (file, "cache_entry->semantic = ");
  print_function_name (file,
		       instruction->name,
		       instruction->format_name,
		       NULL, expanded_bits, function_name_prefix_semantics);
  lf_printf (file, ";\n");
  lf_printf (file, "\n");

  if (options.gen.semantic_icache)
    {
      lf_printf (file, "/* semantic routine */\n");
      print_semantic_body (file, instruction, expanded_bits, opcodes);
      lf_printf (file, "return nia;\n");
    }

  if (!options.gen.semantic_icache)
    {
      lf_printf (file, "/* return the function proper */\n");
      lf_printf (file, "return ");
      print_function_name (file,
			   instruction->name,
			   instruction->format_name,
			   NULL,
			   expanded_bits, function_name_prefix_semantics);
      lf_printf (file, ";\n");
    }

  if (options.gen.direct_access)
    {
      print_icache_body (file,
			 instruction,
			 expanded_bits,
			 cache_rules,
			 undef_variables,
			 (options.gen.semantic_icache
			  ? both_values_and_icache
			  : put_values_in_icache), nr_prefetched_words);
    }

  lf_indent (file, -2);
  lf_printf (file, "}\n");
  lf_indent (file, -2);
  lf_printf (file, "}\n");
}
Exemple #24
0
extern void
print_icache_struct (lf *file, insn_table *isa, cache_entry *cache_rules)
{
  /* Create a list of all the different instruction formats with their
     corresponding field names. */
  form_fields *formats = insn_table_cache_fields (isa);

  lf_printf (file, "\n");
  lf_printf (file, "#define WITH_%sIDECODE_CACHE_SIZE %d\n",
	     options.module.global.prefix.u,
	     (options.gen.icache ? options.gen.icache_size : 0));
  lf_printf (file, "\n");

  /* create an instruction cache if being used */
  if (options.gen.icache)
    {
      lf_printf (file, "typedef struct _%sidecode_cache {\n",
		 options.module.global.prefix.l);
      lf_indent (file, +2);
      {
	form_fields *format;
	lf_printf (file, "unsigned_word address;\n");
	lf_printf (file, "void *semantic;\n");
	lf_printf (file, "union {\n");
	lf_indent (file, +2);
	for (format = formats; format != NULL; format = format->next)
	  {
	    lf_printf (file, "struct {\n");
	    lf_indent (file, +2);
	    {
	      cache_entry *cache_rule;
	      char *field;
	      /* space for any instruction words */
	      if (options.gen.insn_in_icache)
		lf_printf (file, "instruction_word insn[%d];\n",
			   isa->max_nr_words);
	      /* define an entry for any applicable cache rules */
	      for (cache_rule = cache_rules;
		   cache_rule != NULL; cache_rule = cache_rule->next)
		{
		  /* nb - sort of correct - should really check against
		     individual instructions */
		  if (filter_is_subset
		      (format->fields, cache_rule->original_fields))
		    {
		      char *memb;
		      lf_printf (file, "%s %s;",
				 (cache_rule->type == NULL
				  ? "unsigned"
				  : cache_rule->type), cache_rule->name);
		      lf_printf (file, " /*");
		      for (memb =
			   filter_next (cache_rule->original_fields, "");
			   memb != NULL;
			   memb =
			   filter_next (cache_rule->original_fields, memb))
			{
			  lf_printf (file, " %s", memb);
			}
		      lf_printf (file, " */\n");
		    }
		}
	      /* define an entry for any fields not covered by a cache rule */
	      for (field = filter_next (format->fields, "");
		   field != NULL; field = filter_next (format->fields, field))
		{
		  cache_entry *cache_rule;
		  int found_rule = 0;
		  for (cache_rule = cache_rules;
		       cache_rule != NULL; cache_rule = cache_rule->next)
		    {
		      if (strcmp (cache_rule->name, field) == 0)
			{
			  found_rule = 1;
			  break;
			}
		    }
		  if (!found_rule)
		    lf_printf (file, "unsigned %s; /* default */\n", field);
		}
	    }
	    lf_indent (file, -2);
	    lf_printf (file, "} %s;\n", format->name);
	  }
	lf_indent (file, -2);
	lf_printf (file, "} crack;\n");
      }
      lf_indent (file, -2);
      lf_printf (file, "} %sidecode_cache;\n",
		 options.module.global.prefix.l);
    }
  else
    {
      /* alernativly, since no cache, emit a dummy definition for
         idecode_cache so that code refering to the type can still compile */
      lf_printf (file, "typedef void %sidecode_cache;\n",
		 options.module.global.prefix.l);
    }
  lf_printf (file, "\n");
}