Beispiel #1
0
void
md_assemble (char *str)
{
  char *op_start;
  char *op_end;

  moxie_opc_info_t *opcode;
  char *p;
  char pend;

  unsigned short iword = 0;

  int nlen = 0;

  /* Drop leading whitespace.  */
  while (*str == ' ')
    str++;

  /* Find the op code end.  */
  op_start = str;
  for (op_end = str;
       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
       op_end++)
    nlen++;

  pend = *op_end;
  *op_end = 0;

  if (nlen == 0)
    as_bad (_("can't find opcode "));
  opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start);
  *op_end = pend;

  if (opcode == NULL)
    {
      as_bad (_("unknown opcode %s"), op_start);
      return;
    }

  p = frag_more (2);

  switch (opcode->itype)
    {
    case MOXIE_F2_A8V:
      iword = (1<<15) | (opcode->opcode << 12);
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	int reg;
	reg = parse_register_operand (&op_end);
	iword += (reg << 8);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	op_end = parse_exp_save_ilp (op_end, &arg);
	fix_new_exp (frag_now,
		     ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
		     1,
		     &arg,
		     0,
		     BFD_RELOC_8);
      }
      break;
    case MOXIE_F1_AB:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int dest, src;
	dest = parse_register_operand (&op_end);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	src  = parse_register_operand (&op_end);
	iword += (dest << 4) + src;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_A4:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;
	int regnum;

 	regnum = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	iword += (regnum << 4);

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);
      }
      break;
    case MOXIE_F1_M:
    case MOXIE_F1_4:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);
      }
      break;
    case MOXIE_F1_NARG:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      if (*op_end != 0)
	as_warn (_("extra stuff on line ignored"));
      break;
    case MOXIE_F1_A:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int reg;
	reg = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
	iword += (reg << 4);
      }
      break;
    case MOXIE_F1_ABi:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int a, b;
	a = parse_register_operand (&op_end);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rA)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	b = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	iword += (a << 4) + b;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_AiB:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int a, b;
	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rA)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	a = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	b = parse_register_operand (&op_end);
	iword += (a << 4) + b;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_4A:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;
	int a;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

 	a = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4);
      }
      break;
    case MOXIE_F1_ABi2:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *offset;
	int a, b;

 	a = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	op_end = parse_exp_save_ilp (op_end, &arg);
	offset = frag_more (2);
	fix_new_exp (frag_now,
		     (offset - frag_now->fr_literal),
		     2,
		     &arg,
		     0,
		     BFD_RELOC_16);

	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rX)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	b = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4) + b;
      }
      break;
    case MOXIE_F1_AiB2:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *offset;
	int a, b;

	op_end = parse_exp_save_ilp (op_end, &arg);
	offset = frag_more (2);
	fix_new_exp (frag_now,
		     (offset - frag_now->fr_literal),
		     2,
		     &arg,
		     0,
		     BFD_RELOC_16);

	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rX)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	a = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

 	b = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4) + b;
      }
      break;
    case MOXIE_F2_NARG:
      iword = opcode->opcode << 12;
      while (ISSPACE (*op_end))
	op_end++;
      if (*op_end != 0)
	as_warn (_("extra stuff on line ignored"));
      break;
    case MOXIE_F3_PCREL:
      iword = (3<<14) | (opcode->opcode << 10);
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;

	op_end = parse_exp_save_ilp (op_end, &arg);
	fix_new_exp (frag_now,
		     (p - frag_now->fr_literal),
		     2,
		     &arg,
		     TRUE,
		     BFD_RELOC_MOXIE_10_PCREL);
      }
      break;
    case MOXIE_BAD:
      iword = 0;
      while (ISSPACE (*op_end))
	op_end++;
      if (*op_end != 0)
	as_warn (_("extra stuff on line ignored"));
      break;
    default:
      abort ();
    }

  md_number_to_chars (p, iword, 2);
  dwarf2_emit_insn (2);

  while (ISSPACE (*op_end))
    op_end++;

  if (*op_end != 0)
    as_warn (_("extra stuff on line ignored"));

  if (pending_reloc)
    as_bad (_("Something forgot to clean up\n"));
}
Beispiel #2
0
void
dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
{
  offsetT filenum, line;

  /* If we see two .loc directives in a row, force the first one to be
     output now.  */
  if (dwarf2_loc_directive_seen)
    dwarf2_emit_insn (0);

  filenum = get_absolute_expression ();
  SKIP_WHITESPACE ();
  line = get_absolute_expression ();

  if (filenum < 1)
    {
      as_bad (_("file number less than one"));
      return;
    }
  if (filenum >= (int) files_in_use || files[filenum].filename == 0)
    {
      as_bad (_("unassigned file number %ld"), (long) filenum);
      return;
    }

  current.filenum = filenum;
  current.line = line;
  current.discriminator = 0;

#ifndef NO_LISTING
  if (listing)
    {
      if (files[filenum].dir)
	{
	  size_t dir_len = strlen (dirs[files[filenum].dir]);
	  size_t file_len = strlen (files[filenum].filename);
	  char *cp = (char *) alloca (dir_len + 1 + file_len + 1);

	  memcpy (cp, dirs[files[filenum].dir], dir_len);
	  INSERT_DIR_SEPARATOR (cp, dir_len);
	  memcpy (cp + dir_len + 1, files[filenum].filename, file_len);
	  cp[dir_len + file_len + 1] = '\0';
	  listing_source_file (cp);
	}
      else
	listing_source_file (files[filenum].filename);
      listing_source_line (line);
    }
#endif

  SKIP_WHITESPACE ();
  if (ISDIGIT (*input_line_pointer))
    {
      current.column = get_absolute_expression ();
      SKIP_WHITESPACE ();
    }

  while (ISALPHA (*input_line_pointer))
    {
      char *p, c;
      offsetT value;

      p = input_line_pointer;
      c = get_symbol_end ();

      if (strcmp (p, "basic_block") == 0)
	{
	  current.flags |= DWARF2_FLAG_BASIC_BLOCK;
	  *input_line_pointer = c;
	}
      else if (strcmp (p, "prologue_end") == 0)
	{
	  current.flags |= DWARF2_FLAG_PROLOGUE_END;
	  *input_line_pointer = c;
	}
      else if (strcmp (p, "epilogue_begin") == 0)
	{
	  current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
	  *input_line_pointer = c;
	}
      else if (strcmp (p, "is_stmt") == 0)
	{
	  *input_line_pointer = c;
	  value = get_absolute_expression ();
	  if (value == 0)
	    current.flags &= ~DWARF2_FLAG_IS_STMT;
	  else if (value == 1)
	    current.flags |= DWARF2_FLAG_IS_STMT;
	  else
	    {
	      as_bad (_("is_stmt value not 0 or 1"));
	      return;
	    }
	}
      else if (strcmp (p, "isa") == 0)
	{
	  *input_line_pointer = c;
	  value = get_absolute_expression ();
	  if (value >= 0)
	    current.isa = value;
	  else
	    {
	      as_bad (_("isa number less than zero"));
	      return;
	    }
	}
      else if (strcmp (p, "discriminator") == 0)
	{
	  *input_line_pointer = c;
	  value = get_absolute_expression ();
	  if (value >= 0)
	    current.discriminator = value;
	  else
	    {
	      as_bad (_("discriminator less than zero"));
	      return;
	    }
	}
      else
	{
	  as_bad (_("unknown .loc sub-directive `%s'"), p);
	  *input_line_pointer = c;
	  return;
	}

      SKIP_WHITESPACE ();
    }

  demand_empty_rest_of_line ();
  dwarf2_loc_directive_seen = TRUE;
  debug_type = DEBUG_NONE;
}
Beispiel #3
0
void
md_assemble (char * str)
{
  static long delayed_load_register = 0;
  static long prev_delayed_load_register = 0;
  static int last_insn_had_delay_slot = 0;
  static int last_insn_in_noncond_delay_slot = 0;
  static int last_insn_has_load_delay = 0;
  static int last_insn_was_memory_access = 0;
  static int last_insn_was_io_insn = 0;
  static int last_insn_was_arithmetic_or_logic = 0;
  static int last_insn_was_branch_insn = 0;
  static int last_insn_was_conditional_branch_insn = 0;

  mt_insn insn;
  char * errmsg;

  /* Initialize GAS's cgen interface for a new instruction.  */
  gas_cgen_init_parse ();

  insn.insn = mt_cgen_assemble_insn
      (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);

  if (!insn.insn)
    {
      as_bad ("%s", errmsg);
      return;
    }

  /* Doesn't really matter what we pass for RELAX_P here.  */
  gas_cgen_finish_insn (insn.insn, insn.buffer,
			CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);


  /* Handle Scheduling Restrictions.  */
  if (!no_scheduling_restrictions)
    {
      /* Detect consecutive Memory Accesses.  */
      if (last_insn_was_memory_access
	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS)
	  && mt_mach == ms1_64_001)
	as_warn (_("instruction %s may not follow another memory access instruction."),
		 CGEN_INSN_NAME (insn.insn));

      /* Detect consecutive I/O Instructions.  */
      else if (last_insn_was_io_insn
	       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN))
	as_warn (_("instruction %s may not follow another I/O instruction."),
		 CGEN_INSN_NAME (insn.insn));

      /* Detect consecutive branch instructions.  */
      else if (last_insn_was_branch_insn
	       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN))
	as_warn (_("%s may not occupy the delay slot of another branch insn."),
		 CGEN_INSN_NAME (insn.insn));

      /* Detect data dependencies on delayed loads: memory and input insns.  */
      if (last_insn_has_load_delay && delayed_load_register)
	{
	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
	      && insn.fields.f_sr1 == delayed_load_register)
	    as_warn (_("operand references R%ld of previous load."),
		     insn.fields.f_sr1);

	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
	      && insn.fields.f_sr2 == delayed_load_register)
	    as_warn (_("operand references R%ld of previous load."),
		     insn.fields.f_sr2);
	}

      /* Detect JAL/RETI hazard */
      if (mt_mach == ms2
	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_JAL_HAZARD))
	{
	  if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
	       && insn.fields.f_sr1 == delayed_load_register)
	      || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
		  && insn.fields.f_sr2 == delayed_load_register))
	    as_warn (_("operand references R%ld of previous instruction."),
		     delayed_load_register);
	  else if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
		    && insn.fields.f_sr1 == prev_delayed_load_register)
		   || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
		       && insn.fields.f_sr2 == prev_delayed_load_register))
	    as_warn (_("operand references R%ld of instruction before previous."),
		     prev_delayed_load_register);
	}

      /* Detect data dependency between conditional branch instruction
         and an immediately preceding arithmetic or logical instruction.  */
      if (last_insn_was_arithmetic_or_logic
	  && !last_insn_in_noncond_delay_slot
	  && (delayed_load_register != 0)
	  && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
	  && mt_arch == ms1_64_001)
	{
	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
	      && insn.fields.f_sr1 == delayed_load_register)
	    as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
		     insn.fields.f_sr1);

	  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
	      && insn.fields.f_sr2 == delayed_load_register)
	    as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
		     insn.fields.f_sr2);
	}
    }

  /* Keep track of details of this insn for processing next insn.  */
  last_insn_in_noncond_delay_slot = last_insn_was_branch_insn
    && !last_insn_was_conditional_branch_insn;

  last_insn_had_delay_slot =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
  (void) last_insn_had_delay_slot;

  last_insn_has_load_delay =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);

  last_insn_was_memory_access =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS);

  last_insn_was_io_insn =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN);

  last_insn_was_arithmetic_or_logic =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_AL_INSN);

  last_insn_was_branch_insn =
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN);

  last_insn_was_conditional_branch_insn =
  CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
    && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2);

  prev_delayed_load_register = delayed_load_register;

  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDR))
     delayed_load_register = insn.fields.f_dr;
  else if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDRRR))
     delayed_load_register = insn.fields.f_drrr;
  else  /* Insns has no destination register.  */
     delayed_load_register = 0;

  /* Generate dwarf2 line numbers.  */
  dwarf2_emit_insn (4);
}