示例#1
0
extern int
print_function_name(lf *file,
		    const char *basename,
		    insn_bits *expanded_bits,
		    lf_function_name_prefixes prefix)
{
  int nr = 0;
  /* the prefix */
  switch (prefix) {
  case function_name_prefix_semantics:
    nr += lf_putstr(file, "semantic_");
    break;
  case function_name_prefix_idecode:
    nr += lf_printf(file, "idecode_");
    break;
  case function_name_prefix_itable:
    nr += lf_putstr(file, "itable_");
    break;
  case function_name_prefix_icache:
    nr += lf_putstr(file, "icache_");
    break;
  default:
    break;
  }

  /* the function name */
  {
    const char *pos;
    for (pos = basename;
	 *pos != '\0';
	 pos++) {
      switch (*pos) {
      case '/':
      case '-':
      case '(':
      case ')':
	break;
      case ' ':
	nr += lf_putchr(file, '_');
	break;
      default:
	nr += lf_putchr(file, *pos);
	break;
      }
    }
  }

  /* the suffix */
  if (generate_expanded_instructions)
    nr += print_insn_bits(file, expanded_bits);

  return nr;
}
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);
  }
}
示例#3
0
int
lf_printf (lf *file, const char *fmt, ...)
{
  int nr = 0;
  char buf[1024];
  va_list ap;

  va_start (ap, fmt);
  vsprintf (buf, fmt, ap);
  /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
  ASSERT (strlen (buf) < sizeof (buf));
  nr += lf_putstr (file, buf);
  va_end (ap);
  return nr;
}
示例#4
0
static int
print_insn_bits(lf *file, insn_bits *bits)
{
  int nr = 0;
  if (bits == NULL)
    return nr;
  nr += print_insn_bits(file, bits->last);
  nr += lf_putchr(file, '_');
  nr += lf_putstr(file, bits->field->val_string);
  if (bits->opcode->is_boolean && bits->value == 0)
    nr += lf_putint(file, bits->opcode->boolean_constant);
  else if (!bits->opcode->is_boolean) {
    if (bits->opcode->last < bits->field->last)
      nr += lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
    else
      nr += lf_putint(file, bits->value);
  }
  return nr;
}
示例#5
0
int
lf_print__external_ref (lf *file, int line_nr, const char *file_name)
{
  int nr = 0;
  switch (file->references)
    {
    case lf_include_references:
      lf_indent_suppress (file);
      nr += lf_putstr (file, "#line ");
      nr += lf_putint (file, line_nr);
      nr += lf_putstr (file, " \"");
      nr += lf_putstr (file, file_name);
      nr += lf_putstr (file, "\"\n");
      break;
    case lf_omit_references:
      nr += lf_putstr (file, "/* ");
      nr += lf_putstr (file, file_name);
      nr += lf_putstr (file, ":");
      nr += lf_putint (file, line_nr);
      nr += lf_putstr (file, "*/\n");
      break;
    }
  return nr;
}
示例#6
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");
    }