Esempio n. 1
0
File: gen-icache.c Progetto: 5kg/gdb
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");
    }
}
Esempio n. 2
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");
}
Esempio n. 3
0
static void
itable_h_insn (lf *file,
	       insn_table *entry, insn_entry * instruction, void *data)
{
  int len;
  itable_info *info = data;
  lf_print__line_ref (file, instruction->line);
  lf_printf (file, "  ");
  print_function_name (file,
		       instruction->name,
		       instruction->format_name,
		       NULL, NULL, function_name_prefix_itable);
  lf_printf (file, ",\n");
  /* update summary info */
  len = strlen (instruction->format_name);
  if (info->sizeof_form <= len)
    info->sizeof_form = len + 1;
  len = strlen (instruction->name);
  if (info->sizeof_name <= len)
    info->sizeof_name = len + 1;
  len = strlen (filter_filename (instruction->line->file_name));
  if (info->sizeof_file <= len)
    info->sizeof_file = len + 1;
}
Esempio n. 4
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");
    }
}
Esempio n. 5
0
File: gen-icache.c Progetto: 5kg/gdb
static void
print_icache_extraction (lf *file,
			 const char *format_name,
			 cache_entry_type cache_type,
			 const char *entry_name,
			 const char *entry_type,
			 const char *entry_expression,
			 char *single_insn_field,
			 line_ref *line,
			 insn_field_entry *cur_field,
			 opcode_bits *expanded_bits,
			 icache_decl_type what_to_declare,
			 icache_body_type what_to_do)
{
  const char *expression;
  opcode_bits *bits;
  char *reason;
  ASSERT (format_name != NULL);
  ASSERT (entry_name != NULL);

  /* figure out exactly what should be going on here */
  switch (cache_type)
    {
    case scratch_value:
      if ((what_to_do & put_values_in_icache)
	  || what_to_do == do_not_use_icache)
	{
	  reason = "scratch";
	  what_to_do = do_not_use_icache;
	}
      else
	return;
      break;
    case compute_value:
      if ((what_to_do & get_values_from_icache)
	  || what_to_do == do_not_use_icache)
	{
	  reason = "compute";
	  what_to_do = do_not_use_icache;
	}
      else
	return;
      break;
    case cache_value:
      if ((what_to_declare != undef_variables)
	  || !(what_to_do & put_values_in_icache))
	{
	  reason = "cache";
	  what_to_declare = ((what_to_do & put_values_in_icache)
			     ? declare_variables : what_to_declare);
	}
      else
	return;
      break;
    default:
      abort ();			/* Bad switch.  */
    }

  /* For the type, default to a simple unsigned */
  if (entry_type == NULL || strlen (entry_type) == 0)
    entry_type = "unsigned";

  /* look through the set of expanded sub fields to see if this field
     has been given a constant value */
  for (bits = expanded_bits; bits != NULL; bits = bits->next)
    {
      if (bits->field == cur_field)
	break;
    }

  /* Define a storage area for the cache element */
  switch (what_to_declare)
    {
    case undef_variables:
      /* We've finished with the #define value - destory it */
      lf_indent_suppress (file);
      lf_printf (file, "#undef %s\n", entry_name);
      return;
    case define_variables:
      /* Using direct access for this entry, clear any prior
         definition, then define it */
      lf_indent_suppress (file);
      lf_printf (file, "#undef %s\n", entry_name);
      /* Don't type cast pointer types! */
      lf_indent_suppress (file);
      if (strchr (entry_type, '*') != NULL)
	lf_printf (file, "#define %s (", entry_name);
      else
	lf_printf (file, "#define %s ((%s) ", entry_name, entry_type);
      break;
    case declare_variables:
      /* using variables to define the value */
      if (line != NULL)
	lf_print__line_ref (file, line);
      lf_printf (file, "%s const %s UNUSED = ", entry_type, entry_name);
      break;
    }


  /* define a value for that storage area as determined by what is in
     the cache */
  if (bits != NULL
      && single_insn_field != NULL
      && strcmp (entry_name, single_insn_field) == 0
      && strcmp (entry_name, cur_field->val_string) == 0
      && ((bits->opcode->is_boolean && bits->value == 0)
	  || (!bits->opcode->is_boolean)))
    {
      /* The cache rule is specifying what to do with a simple
         instruction field.

         Because of instruction expansion, the field is either a
         constant value or equal to the specified constant (boolean
         comparison). (The latter indicated by bits->value == 0).

         The case of a field not being equal to the specified boolean
         value is handled later. */
      expression = "constant field";
      ASSERT (bits->field == cur_field);
      if (bits->opcode->is_boolean)
	{
	  ASSERT (bits->value == 0);
	  lf_printf (file, "%d", bits->opcode->boolean_constant);
	}
      else if (bits->opcode->last < bits->field->last)
	{
	  lf_printf (file, "%d",
		     bits->value << (bits->field->last - bits->opcode->last));
	}
      else
	{
	  lf_printf (file, "%d", bits->value);
	}
    }
  else if (bits != NULL
	   && single_insn_field != NULL
	   && strncmp (entry_name,
		       single_insn_field,
		       strlen (single_insn_field)) == 0
	   && strncmp (entry_name + strlen (single_insn_field),
		       "_is_",
		       strlen ("_is_")) == 0
	   && ((bits->opcode->is_boolean
		&& ((unsigned)
		    atol (entry_name + strlen (single_insn_field) +
			  strlen ("_is_")) == bits->opcode->boolean_constant))
	       || (!bits->opcode->is_boolean)))
    {
      /* The cache rule defines an entry for the comparison between a
         single instruction field and a constant.  The value of the
         comparison in someway matches that of the opcode field that
         was made constant through expansion. */
      expression = "constant compare";
      if (bits->opcode->is_boolean)
	{
	  lf_printf (file, "%d /* %s == %d */",
		     bits->value == 0,
		     single_insn_field, bits->opcode->boolean_constant);
	}
      else if (bits->opcode->last < bits->field->last)
	{
	  lf_printf (file, "%d /* %s == %d */",
		     (atol
		      (entry_name + strlen (single_insn_field) +
		       strlen ("_is_")) ==
		      (bits->
		       value << (bits->field->last - bits->opcode->last))),
		     single_insn_field,
		     (bits->
		      value << (bits->field->last - bits->opcode->last)));
	}
      else
	{
	  lf_printf (file, "%d /* %s == %d */",
		     (atol
		      (entry_name + strlen (single_insn_field) +
		       strlen ("_is_")) == bits->value), single_insn_field,
		     bits->value);
	}
    }
  else
    {
      /* put the field in the local variable, possibly also enter it
         into the cache */
      expression = "extraction";
      /* handle the cache */
      if ((what_to_do & get_values_from_icache)
	  || (what_to_do & put_values_in_icache))
	{
	  lf_printf (file, "cache_entry->crack.%s.%s",
		     format_name, entry_name);
	  if (what_to_do & put_values_in_icache)	/* also put it in the cache? */
	    {
	      lf_printf (file, " = ");
	    }
	}
      if ((what_to_do & put_values_in_icache)
	  || what_to_do == do_not_use_icache)
	{
	  if (cur_field != NULL)
	    {
	      if (entry_expression != NULL && strlen (entry_expression) > 0)
		error (line,
		       "Instruction field entry with nonempty expression\n");
	      if (cur_field->first == 0
		  && cur_field->last == options.insn_bit_size - 1)
		lf_printf (file, "(instruction_%d)", cur_field->word_nr);
	      else if (cur_field->last == options.insn_bit_size - 1)
		lf_printf (file, "MASKED%d (instruction_%d, %d, %d)",
			   options.insn_bit_size,
			   cur_field->word_nr,
			   i2target (options.hi_bit_nr, cur_field->first),
			   i2target (options.hi_bit_nr, cur_field->last));
	      else
		lf_printf (file, "EXTRACTED%d (instruction_%d, %d, %d)",
			   options.insn_bit_size,
			   cur_field->word_nr,
			   i2target (options.hi_bit_nr, cur_field->first),
			   i2target (options.hi_bit_nr, cur_field->last));
	    }
	  else
	    {
	      lf_printf (file, "%s", entry_expression);
	    }
	}
    }

  switch (what_to_declare)
    {
    case define_variables:
      lf_printf (file, ")");
      break;
    case undef_variables:
      break;
    case declare_variables:
      lf_printf (file, ";");
      break;
    }

  ASSERT (reason != NULL && expression != NULL);
  lf_printf (file, " /* %s - %s */\n", reason, expression);
}
Esempio n. 6
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");
}