Esempio n. 1
0
void
print_my_defines(lf *file,
		 insn_bits *expanded_bits,
		 table_entry *file_entry)
{
  /* #define MY_INDEX xxxxx */
  lf_indent_suppress(file);
  lf_printf(file, "#undef MY_INDEX\n");
  lf_indent_suppress(file);
  lf_printf(file, "#define MY_INDEX ");
  print_function_name(file,
                      file_entry->fields[insn_name],
                      NULL,
                      function_name_prefix_itable);
  lf_printf(file, "\n");
  /* #define MY_PREFIX xxxxxx */
  lf_indent_suppress(file);
  lf_printf(file, "#undef MY_PREFIX\n");
  lf_indent_suppress(file);
  lf_printf(file, "#define MY_PREFIX ");
  print_function_name(file,
		      file_entry->fields[insn_name],
		      expanded_bits,
		      function_name_prefix_none);
  lf_printf(file, "\n");
}
Esempio n. 2
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);
    }
}
Esempio n. 3
0
static void
print_engine_issue_postfix_hook (lf *file)
{
  lf_printf (file, "\n");
  lf_indent_suppress (file);
  lf_printf (file, "#if defined (ENGINE_ISSUE_POSTFIX_HOOK)\n");
  lf_printf (file, "ENGINE_ISSUE_POSTFIX_HOOK();\n");
  lf_indent_suppress (file);
  lf_printf (file, "#endif\n");
  lf_printf (file, "\n");
}
Esempio n. 4
0
static void
gen_idecode_h (lf *file,
	       gen_table *gen,
	       insn_table *insns,
	       cache_entry *cache_rules)
{
  lf_printf (file, "typedef unsigned%d %sinstruction_word;\n",
	     options.insn_bit_size, options.module.global.prefix.l);
  if (options.gen.delayed_branch)
    {
      lf_printf (file, "typedef struct _%sinstruction_address {\n",
		 options.module.global.prefix.l);
      lf_printf (file, "  address_word ip; /* instruction pointer */\n");
      lf_printf (file, "  address_word dp; /* delayed-slot pointer */\n");
      lf_printf (file, "} %sinstruction_address;\n", options.module.global.prefix.l);
    }
  else
    {
      lf_printf (file, "typedef address_word %sinstruction_address;\n",
		 options.module.global.prefix.l);
      
    }
  if (options.gen.nia == nia_is_invalid
      && strlen (options.module.global.prefix.u) > 0)
    {
      lf_indent_suppress (file);
      lf_printf (file, "#define %sINVALID_INSTRUCTION_ADDRESS ",
		 options.module.global.prefix.u);
      lf_printf (file, "INVALID_INSTRUCTION_ADDRESS\n");
    }
  lf_printf (file, "\n");
  print_icache_struct (file, insns, cache_rules);
  lf_printf (file, "\n");
  if (options.gen.icache)
    {
      ERROR ("FIXME - idecode with icache suffering from bit-rot");
    }
  else
    {
      gen_list *entry;
      for (entry = gen->tables; entry != NULL; entry = entry->next)
	{
	  print_idecode_issue_function_header (file,
					       (options.gen.multi_sim
						? entry->model->name
						: NULL),
					       is_function_declaration,
					       1/*ALWAYS ONE WORD*/);
	}
      if (options.gen.multi_sim)
	{
	  print_idecode_issue_function_header (file,
					       NULL,
					       is_function_variable,
					       1/*ALWAYS ONE WORD*/);
	}
    }
}
Esempio n. 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"));
    }
}
Esempio n. 6
0
void
print_my_defines (lf *file,
		  const char *basename,
		  const char *format_name,
		  opcode_bits *expanded_bits)
{
  /* #define MY_INDEX xxxxx */
  lf_indent_suppress (file);
  lf_printf (file, "#undef MY_INDEX\n");
  lf_indent_suppress (file);
  lf_printf (file, "#define MY_INDEX ");
  print_function_name (file,
		       basename, format_name, NULL,
		       NULL,
		       function_name_prefix_itable);
  lf_printf (file, "\n");
  /* #define MY_PREFIX xxxxxx */
  lf_indent_suppress (file);
  lf_printf (file, "#undef ");
  print_function_name (file,
		       basename, format_name, NULL,
		       expanded_bits,
		       function_name_prefix_none);
  lf_printf (file, "\n");
  lf_indent_suppress (file);
  lf_printf (file, "#undef MY_PREFIX\n");
  lf_indent_suppress (file);
  lf_printf (file, "#define MY_PREFIX ");
  print_function_name (file,
		       basename, format_name, NULL,
		       expanded_bits,
		       function_name_prefix_none);
  lf_printf (file, "\n");
  /* #define MY_NAME xxxxxx */
  lf_indent_suppress (file);
  lf_indent_suppress (file);
  lf_printf (file, "#undef MY_NAME\n");
  lf_indent_suppress (file);
  lf_printf (file, "#define MY_NAME \"");
  print_function_name (file,
		       basename, format_name, NULL,
		       expanded_bits,
		       function_name_prefix_none);
  lf_printf (file, "\"\n");
}
Esempio n. 7
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;
}
Esempio n. 8
0
extern void
gen_itable_h (lf *file, insn_table *isa)
{
  itable_info *info = ZALLOC (itable_info);

  /* output an enumerated type for each instruction */
  lf_printf (file, "typedef enum {\n");
  insn_table_traverse_insn (file, isa, itable_h_insn, info);
  lf_printf (file, "  nr_%sitable_entries,\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "} %sitable_index;\n", options.module.itable.prefix.l);
  lf_printf (file, "\n");

  /* output an enumeration type for each flag */
  itable_print_enum (file, isa->flags, "flag");
  lf_printf (file, "extern const char *%sitable_flag_names[];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "\n");

  /* output an enumeration of all the possible options */
  itable_print_enum (file, isa->options, "option");
  lf_printf (file, "extern const char *%sitable_option_names[];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "\n");

  /* output an enumeration of all the processor models */
  itable_print_enum (file, isa->model->processors, "processor");
  lf_printf (file, "extern const char *%sitable_processor_names[];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "\n");

  /* output the table that contains the actual instruction info */
  lf_printf (file, "typedef struct _%sitable_instruction_info {\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "  %sitable_index nr;\n", options.module.itable.prefix.l);
  lf_printf (file, "  char *format;\n");
  lf_printf (file, "  char *form;\n");
  lf_printf (file, "  char *flags;\n");

  /* nr_itable_* may be zero, so we add 1 to avoid an
     illegal zero-sized array. */
  lf_printf (file, "  char flag[nr_%sitable_flags + 1];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "  char *options;\n");
  lf_printf (file, "  char option[nr_%sitable_options + 1];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "  char *processors;\n");
  lf_printf (file, "  char processor[nr_%sitable_processors + 1];\n",
	     options.module.itable.prefix.l);
  lf_printf (file, "  char *name;\n");
  lf_printf (file, "  char *file;\n");
  lf_printf (file, "  int line_nr;\n");
  lf_printf (file, "} %sitable_info;\n", options.module.itable.prefix.l);
  lf_printf (file, "\n");
  lf_printf (file, "extern %sitable_info %sitable[nr_%sitable_entries];\n",
	     options.module.itable.prefix.l, options.module.itable.prefix.l,
	     options.module.itable.prefix.l);
  if (strlen (options.module.itable.prefix.l) > 0)
    {
      lf_indent_suppress (file);
      lf_printf (file, "#define itable %sitable\n",
		 options.module.itable.prefix.l);
    }
  lf_printf (file, "\n");

  /* output an enum defining the max size of various itable members */
  lf_printf (file, "enum {\n");
  lf_printf (file, "  sizeof_%sitable_form = %d,\n",
	     options.module.itable.prefix.l, info->sizeof_form);
  lf_printf (file, "  sizeof_%sitable_name = %d,\n",
	     options.module.itable.prefix.l, info->sizeof_name);
  lf_printf (file, "  sizeof_%sitable_file = %d,\n",
	     options.module.itable.prefix.l, info->sizeof_file);
  lf_printf (file, "};\n");
}
Esempio n. 9
0
extern void
gen_support_h (lf *file, insn_table *table)
{
  /* output the definition of `SD_' */
  if (options.gen.smp)
    {
      lf_printf (file, "#define SD CPU_STATE (cpu)\n");
      lf_printf (file, "#define CPU cpu\n");
      lf_printf (file, "#define CPU_ cpu\n");
    }
  else
    {
      lf_printf (file, "#define SD sd\n");
      lf_printf (file, "#define CPU (STATE_CPU (sd, 0))\n");
      lf_printf (file, "#define CPU_ sd\n");
    }

  lf_printf (file, "#define CIA_ cia\n");
  if (options.gen.delayed_branch)
    {
      lf_printf (file, "#define CIA cia.ip\n");
      lf_printf (file,
		 "/* #define NIA nia.dp -- do not define, ambigious */\n");
    }
  else
    {
      lf_printf (file, "#define CIA cia\n");
      lf_printf (file, "#define NIA nia\n");
    }
  lf_printf (file, "\n");

  lf_printf (file, "#define SD_ CPU_, CIA_, MY_INDEX\n");
  lf_printf (file, "#define _SD SD_ /* deprecated */\n");
  lf_printf (file, "\n");

  /* Map <PREFIX>_xxxx onto the shorter xxxx for the following names:

     instruction_word
     idecode_issue
     semantic_illegal

     Map defined here as name space problems are created when the name is
     defined in idecode.h  */
  if (strcmp (options.module.idecode.prefix.l, "") != 0)
    {
      lf_indent_suppress (file);
      lf_printf (file, "#define %s %s%s\n",
		 "instruction_word",
		 options.module.idecode.prefix.l, "instruction_word");
      lf_printf (file, "\n");
      lf_indent_suppress (file);
      lf_printf (file, "#define %s %s%s\n",
		 "idecode_issue",
		 options.module.idecode.prefix.l, "idecode_issue");
      lf_printf (file, "\n");
      lf_indent_suppress (file);
      lf_printf (file, "#define %s %s%s\n",
		 "semantic_illegal",
		 options.module.idecode.prefix.l, "semantic_illegal");
      lf_printf (file, "\n");
    }

  /* output a declaration for all functions */
  function_entry_traverse (file, table->functions, support_h_function, NULL);
  lf_printf (file, "\n");
  lf_printf (file, "#if defined(SUPPORT_INLINE)\n");
  lf_printf (file, "# if ((SUPPORT_INLINE & INCLUDE_MODULE)\\\n");
  lf_printf (file, "      && (SUPPORT_INLINE & INCLUDED_BY_MODULE))\n");
  lf_printf (file, "#  include \"%ssupport.c\"\n",
	     options.module.support.prefix.l);
  lf_printf (file, "# endif\n");
  lf_printf (file, "#endif\n");
}
Esempio n. 10
0
static void
print_icache_extraction(lf *file,
			insn *instruction,
			const char *entry_name,
			const char *entry_type,
			const char *entry_expression,
			const char *original_name,
			const char *file_name,
			int line_nr,
			insn_field *cur_field,
			insn_bits *bits,
			icache_decl_type what_to_declare,
			icache_body_type what_to_do,
			const char *reason)
{
  const char *expression;
  ASSERT(entry_name != NULL);

  /* Define a storage area for the cache element */
  if (what_to_declare == undef_variables) {
    /* We've finished with the value - destory it */
    lf_indent_suppress(file);
    lf_printf(file, "#undef %s\n", entry_name);
    return;
  }
  else if (what_to_declare == define_variables) {
    lf_indent_suppress(file);
    lf_printf(file, "#define %s ", entry_name);
  }
  else {
    if (file_name != NULL)
      lf_print__external_reference(file, line_nr, file_name);
    lf_printf(file, "%s const %s UNUSED = ",
	      entry_type == NULL ? "unsigned" : entry_type,
	      entry_name);
  }

  /* define a value for that storage area as determined by what is in
     the cache */
  if (bits != NULL
      && strcmp(entry_name, cur_field->val_string) == 0
      && ((bits->opcode->is_boolean && bits->value == 0)
	  || (!bits->opcode->is_boolean))) {
    /* The simple field has been made constant (as a result of
       expanding instructions or similar).  Remember that for a
       boolean field, value is either 0 (implying the required
       boolean_constant) or nonzero (implying some other value and
       handled later below) - Define the variable accordingly */
    expression = "constant field";
    ASSERT(bits->field == cur_field);
    ASSERT(entry_type == NULL);
    if (bits->opcode->is_boolean)
      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
	   && original_name != NULL
	   && strncmp(entry_name,
		      original_name, strlen(original_name)) == 0
	   && strncmp(entry_name + strlen(original_name),
		      "_is_", strlen("_is_")) == 0
	   && ((bits->opcode->is_boolean
		&& (atol(entry_name + strlen(original_name) + strlen("_is_"))
		    == bits->opcode->boolean_constant))
	       || (!bits->opcode->is_boolean))) {
    expression = "constant compare";
    /* An entry, derived from ORIGINAL_NAME, is testing to see of the
       ORIGINAL_NAME has a specific constant value.  That value
       matching a boolean or constant field */
    if (bits->opcode->is_boolean)
      lf_printf(file, "%d /* %s == %d */",
		bits->value == 0,
		original_name,
		bits->opcode->boolean_constant);
    else if (bits->opcode->last < bits->field->last)
      lf_printf(file, "%d /* %s == %d */",
		(atol(entry_name + strlen(original_name) + strlen("_is_"))
		 == (bits->value << (bits->field->last - bits->opcode->last))),
		original_name,
		(bits->value << (bits->field->last - bits->opcode->last)));
    else
      lf_printf(file, "%d /* %s == %d */",
		(atol(entry_name + strlen(original_name) + strlen("_is_"))
		 == bits->value),
		original_name,
		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",
		instruction->file_entry->fields[insn_form],
		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 && strcmp(entry_name, cur_field->val_string) == 0)
	lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
		  i2target(hi_bit_nr, cur_field->first),
		  i2target(hi_bit_nr, cur_field->last));
      else if (entry_expression != NULL)
	lf_printf(file, "%s", entry_expression);
      else
	lf_printf(file, "eval_%s", entry_name);
    }
  }

  if (!((what_to_declare == define_variables)
	|| (what_to_declare == undef_variables)))
    lf_printf(file, ";");
  if (reason != NULL)
    lf_printf(file, " /* %s - %s */", reason, expression);
  lf_printf(file, "\n");
}
Esempio n. 11
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. 12
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. 13
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");
}