예제 #1
0
static void
out_inc_line_addr (int line_delta, addressT addr_delta)
{
  int len = size_inc_line_addr (line_delta, addr_delta);
  emit_inc_line_addr (line_delta, addr_delta, frag_more (len), len);
}
예제 #2
0
static void
out_debug_aranges (segT aranges_seg, segT info_seg)
{
  unsigned int addr_size = sizeof_address;
  addressT size, skip;
  struct line_seg *s;
  expressionS expr;
  char *p;

  size = 4 + 2 + 4 + 1 + 1;

  skip = 2 * addr_size - (size & (2 * addr_size - 1));
  if (skip == 2 * addr_size)
    skip = 0;
  size += skip;

  for (s = all_segs; s; s = s->next)
    size += 2 * addr_size;

  size += 2 * addr_size;

  subseg_set (aranges_seg, 0);

  /* Length of the compilation unit.  */
  out_four (size - 4);

  /* Version.  */
  out_two (2);

  /* Offset to .debug_info.  */
  /* ??? sizeof_offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), 4);

  /* Size of an address (offset portion).  */
  out_byte (addr_size);

  /* Size of a segment descriptor.  */
  out_byte (0);

  /* Align the header.  */
  if (skip)
    frag_align (ffs (2 * addr_size) - 1, 0, 0);

  for (s = all_segs; s; s = s->next)
    {
      fragS *frag;
      symbolS *beg, *end;

      frag = first_frag_for_seg (s->seg);
      beg = symbol_temp_new (s->seg, 0, frag);
      s->text_start = beg;

      frag = last_frag_for_seg (s->seg);
      end = symbol_temp_new (s->seg, get_frag_fix (frag), frag);
      s->text_end = end;

      expr.X_op = O_symbol;
      expr.X_add_symbol = beg;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);

      expr.X_op = O_subtract;
      expr.X_add_symbol = end;
      expr.X_op_symbol = beg;
      expr.X_add_number = 0;
      emit_expr (&expr, addr_size);
    }

  p = frag_more (2 * addr_size);
  md_number_to_chars (p, 0, addr_size);
  md_number_to_chars (p + addr_size, 0, addr_size);
}
예제 #3
0
static inline void
out_four (int data)
{
  md_number_to_chars (frag_more (4), data, 4);
}
예제 #4
0
static void
out_sleb128 (addressT value)
{
  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
}
예제 #5
0
static void
out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
{
  char producer[128];
  char *comp_dir;
  expressionS expr;
  symbolS *info_start;
  symbolS *info_end;
  char *p;
  int len;
  enum dwarf2_format d2f;
  int sizeof_offset;

  subseg_set (info_seg, 0);

  info_start = symbol_temp_new_now ();
  info_end = symbol_temp_make ();

  /* Compilation Unit length.  */
  expr.X_op = O_subtract;
  expr.X_add_symbol = info_end;
  expr.X_op_symbol = info_start;

  d2f = DWARF2_FORMAT ();
  if (d2f == dwarf2_format_32bit)
    {
      expr.X_add_number = -4;
      emit_expr (&expr, 4);
      sizeof_offset = 4;
    }
  else if (d2f == dwarf2_format_64bit)
    {
      expr.X_add_number = -12;
      out_four (-1);
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else if (d2f == dwarf2_format_64bit_irix)
    {
      expr.X_add_number = -8;
      emit_expr (&expr, 8);
      sizeof_offset = 8;
    }
  else
    {
      as_fatal (_("internal error: unknown dwarf2 format"));
    }

  /* DWARF version.  */
  out_two (2);

  /* .debug_abbrev offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);

  /* Target address size.  */
  out_byte (sizeof_address);

  /* DW_TAG_compile_unit DIE abbrev */
  out_uleb128 (1);

  /* DW_AT_stmt_list */
  /* ??? sizeof_offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (line_seg), 4);

  /* These two attributes are emitted if all of the code is contiguous.  */
  if (all_segs->next == NULL)
    {
      /* DW_AT_low_pc */
      expr.X_op = O_symbol;
      expr.X_add_symbol = all_segs->text_start;
      expr.X_add_number = 0;
      emit_expr (&expr, sizeof_address);

      /* DW_AT_high_pc */
      expr.X_op = O_symbol;
      expr.X_add_symbol = all_segs->text_end;
      expr.X_add_number = 0;
      emit_expr (&expr, sizeof_address);
    }
  else
    {
      /* This attribute is emitted if the code is disjoint.  */
      /* DW_AT_ranges.  */
      TC_DWARF2_EMIT_OFFSET (section_symbol (ranges_seg), sizeof_offset);
    }

  /* DW_AT_name.  We don't have the actual file name that was present
     on the command line, so assume files[1] is the main input file.
     We're not supposed to get called unless at least one line number
     entry was emitted, so this should always be defined.  */
  if (!files || files_in_use < 1)
    abort ();
  if (files[1].dir)
    {
      len = strlen (dirs[files[1].dir]);
      p = frag_more (len + 1);
      memcpy (p, dirs[files[1].dir], len);
      INSERT_DIR_SEPARATOR (p, len);
    }
  len = strlen (files[1].filename) + 1;
  p = frag_more (len);
  memcpy (p, files[1].filename, len);

  /* DW_AT_comp_dir */
  comp_dir = getpwd ();
  len = strlen (comp_dir) + 1;
  p = frag_more (len);
  memcpy (p, comp_dir, len);

  /* DW_AT_producer */
  sprintf (producer, "GNU AS %s", VERSION);
  len = strlen (producer) + 1;
  p = frag_more (len);
  memcpy (p, producer, len);

  /* DW_AT_language.  Yes, this is probably not really MIPS, but the
     dwarf2 draft has no standard code for assembler.  */
  out_two (DW_LANG_Mips_Assembler);

  symbol_set_value_now (info_end);
}
예제 #6
0
static inline void
out_two (int data)
{
  md_number_to_chars (frag_more (2), data, 2);
}
예제 #7
0
static void
out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg)
{
  char producer[128];
  const char *comp_dir;
  const char *dirname;
  expressionS exp;
  symbolS *info_end;
  char *p;
  int len;
  int sizeof_offset;

  sizeof_offset = out_header (info_seg, &exp);
  info_end = exp.X_add_symbol;

  /* DWARF version.  */
  out_two (2);

  /* .debug_abbrev offset */
  TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset);

  /* Target address size.  */
  out_byte (sizeof_address);

  /* DW_TAG_compile_unit DIE abbrev */
  out_uleb128 (1);

  /* DW_AT_stmt_list */
  TC_DWARF2_EMIT_OFFSET (section_symbol (line_seg),
			 (DWARF2_FORMAT (line_seg) == dwarf2_format_32bit
			  ? 4 : 8));

  /* These two attributes are emitted if all of the code is contiguous.  */
  if (all_segs->next == NULL)
    {
      /* DW_AT_low_pc */
      exp.X_op = O_symbol;
      exp.X_add_symbol = all_segs->text_start;
      exp.X_add_number = 0;
      emit_expr (&exp, sizeof_address);

      /* DW_AT_high_pc */
      exp.X_op = O_symbol;
      exp.X_add_symbol = all_segs->text_end;
      exp.X_add_number = 0;
      emit_expr (&exp, sizeof_address);
    }
  else
    {
      /* This attribute is emitted if the code is disjoint.  */
      /* DW_AT_ranges.  */
      TC_DWARF2_EMIT_OFFSET (section_symbol (ranges_seg), sizeof_offset);
    }

  /* DW_AT_name.  We don't have the actual file name that was present
     on the command line, so assume files[1] is the main input file.
     We're not supposed to get called unless at least one line number
     entry was emitted, so this should always be defined.  */
  if (files_in_use == 0)
    abort ();
  if (files[1].dir)
    {
      dirname = remap_debug_filename (dirs[files[1].dir]);
      len = strlen (dirname);
#ifdef TE_VMS
      /* Already has trailing slash.  */
      p = frag_more (len);
      memcpy (p, dirname, len);
#else
      p = frag_more (len + 1);
      memcpy (p, dirname, len);
      INSERT_DIR_SEPARATOR (p, len);
#endif
    }
  len = strlen (files[1].filename) + 1;
  p = frag_more (len);
  memcpy (p, files[1].filename, len);

  /* DW_AT_comp_dir */
  comp_dir = remap_debug_filename (getpwd ());
  len = strlen (comp_dir) + 1;
  p = frag_more (len);
  memcpy (p, comp_dir, len);

  /* DW_AT_producer */
  sprintf (producer, "GNU AS %s", VERSION);
  len = strlen (producer) + 1;
  p = frag_more (len);
  memcpy (p, producer, len);

  /* DW_AT_language.  Yes, this is probably not really MIPS, but the
     dwarf2 draft has no standard code for assembler.  */
  out_two (DW_LANG_Mips_Assembler);

  symbol_set_value_now (info_end);
}
예제 #8
0
파일: tc-moxie.c 프로젝트: ChrisG0x20/gdb
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;
    default:
      abort ();
    }

  md_number_to_chars (p, iword, 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"));
}
예제 #9
0
/* Convert the instructions into frags and bytes */
void
md_assemble(char *str)
{
  char *op_start;
  char *op_end;
  char op_name[10];
  const bexkat1_opc_info_t *opcode;
  char *p;
  char pend;
  unsigned int iword;
  int nlen = 0;
  int regnum;
  expressionS arg;
  int offset;

  while (*str == ' ')
    str++;
  
  // mark opcode
  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;
  strncpy(op_name, op_start, 10);
  *op_end = pend;

  if (nlen == 0)
    as_bad(_("can't find opcode "));
  
  while (ISSPACE(*op_end))
    op_end++;
  
  opcode = (bexkat1_opc_info_t *) hash_find(opcode_hash_control, op_name);
  if (opcode == NULL) {
    as_bad(_("unknown opcode %s"), op_name);
    return;
  }

  iword = (opcode->type << 28) | (opcode->opcode << 24) | opcode->size;

  p = frag_more(4);

  switch (opcode->type) {
  case BEXKAT1_INH:
    if (opcode->args == 0) {
      md_number_to_chars(p, iword, 4);
    }
    if (opcode->args == 1) {
      op_end = parse_exp_save_ilp(op_end, &arg);
      if (opcode->size) {
	md_number_to_chars(p, iword, 4);
	p = frag_more(4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_32);
      } else {
	if (arg.X_op != O_constant) {
	  as_bad(_("offset is not a constant expression"));
	  ignore_rest_of_line();
	  return;
	}
	offset = arg.X_add_number;
	if (offset < -16384 || offset > 16383) {
	  as_bad(_("offset is out of range: %d\n"), offset);
	  ignore_rest_of_line();
	  return;
	}
	
	md_number_to_chars(p, iword, 4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_BEXKAT1_15);
      }
    }
    break;
  case BEXKAT1_PUSH:
    if (opcode->args == 1 && opcode->opcode == 2) // bsr
      goto branch;
    if (opcode->args == 1) {
      if (opcode->size) {
	op_end = parse_exp_save_ilp(op_end, &arg);
	md_number_to_chars(p, iword, 4);
	p = frag_more(4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_32);
      } else {
	regnum = parse_regnum(&op_end);
	if (regnum == -1)
	  return; 
	while (ISSPACE(*op_end))
	  op_end++;
	iword |= (regnum & 0xf) << 20; // A
	md_number_to_chars(p, iword, 4);
      }
    }
    if (opcode->args == 2) {
      if (*op_end != '(')
	op_end = parse_exp_save_ilp(op_end, &arg);
      else { // Implicit 0 offset to allow for indirect
	arg.X_op = O_constant;
	arg.X_add_number = 0;
      }
      
      if (*op_end != '(') {
	as_bad(_("missing open paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++; // burn paren
      while (ISSPACE(*op_end))
	op_end++;
      
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 20; // A
      
      if (*op_end != ')') {
	as_bad(_("missing close paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++;
      
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset < -16384 || offset > 16383) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  case BEXKAT1_POP:
    if (opcode->args == 0) {
      md_number_to_chars(p, iword, 4);
    }
    if (opcode->args == 1) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 20; // A
      md_number_to_chars(p, iword, 4);
    }
    break;
  case BEXKAT1_MOV:
    if (opcode->opcode == 0) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
        return; 
      while (ISSPACE(*op_end))
        op_end++;
      iword |= (regnum & 0xf) << 20; // A
      md_number_to_chars(p, iword, 4);
      break;
    }
    /* __attribute__((fallthrough)); */
  case BEXKAT1_CMP:
  case BEXKAT1_FPU:
  case BEXKAT1_FP:
  case BEXKAT1_ALU:
  case BEXKAT1_INT:
  case BEXKAT1_INTU:
    if (opcode->args > 1) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
        return; 
      while (ISSPACE(*op_end))
        op_end++;
      iword |= (regnum & 0xf) << 20; // A

      if (*op_end != ',') {
        as_bad(_("missing comma: %s"), op_end);
        return;
      }
      op_end++;
      while (ISSPACE(*op_end))
        op_end++;
    
    }

    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 16; // B

    if (opcode->args > 2) {

      if (*op_end != ',') {
	as_bad(_("missing comma: %s"), op_end);
	return;
      }
      op_end++;
      while (ISSPACE(*op_end))
	op_end++;
      
      if (opcode->opcode < 8) {
	regnum = parse_regnum(&op_end);
	if (regnum == -1)
	  return; 
	while (ISSPACE(*op_end))
	  op_end++;
	iword |= (regnum & 0xf) << 12; // C
	md_number_to_chars(p, iword, 4);
      } else {
	op_end = parse_exp_save_ilp(op_end, &arg);
	if (arg.X_op != O_constant) {
	  as_bad(_("offset is not a constant expression"));
	  ignore_rest_of_line();
	  return;
	}
	offset = arg.X_add_number;
	if (offset < -16384 || offset > 16383) {
	  as_bad(_("offset is out of range: %d\n"), offset);
	  ignore_rest_of_line();
	  return;
	}
	md_number_to_chars(p, iword, 4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_BEXKAT1_15);
      }
    } else {
      md_number_to_chars(p, iword, 4);
    }
    break;
branch:
  case BEXKAT1_BRANCH:
    md_number_to_chars(p, iword, 4);
    op_end = parse_exp_save_ilp(op_end, &arg);
    if (target_big_endian)
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  TRUE,
		  BFD_RELOC_BEXKAT1_15_PCREL);
    else
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  TRUE,
		  BFD_RELOC_BEXKAT1_15_PCREL);
    break;
  case BEXKAT1_LOAD:
  case BEXKAT1_STORE:
    // A, 
    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 20; // A
    
    if (*op_end != ',') {
      as_bad(_("missing comma: %s"), op_end);
      return;
    }
    op_end++;
    while (ISSPACE(*op_end))
      op_end++;
    /* __attribute__((fallthrough)); */
  case BEXKAT1_JUMP:
    if (opcode->size) { // big address
      md_number_to_chars(p, iword, 4);
      op_end = parse_exp_save_ilp(op_end, &arg);
      p = frag_more(4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_32);
    } else { // exp(B)
      if (*op_end != '(')
	op_end = parse_exp_save_ilp(op_end, &arg);
      else { // Implicit 0 offset to allow for indirect
	arg.X_op = O_constant;
	arg.X_add_number = 0;
      }
      
      if (*op_end != '(') {
	as_bad(_("missing open paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++; // burn paren
      while (ISSPACE(*op_end))
	op_end++;
      
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 16; // B
      
      if (*op_end != ')') {
	as_bad(_("missing close paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++;
      
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset < -16384 || offset > 16383) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  case BEXKAT1_LDI:
    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 20; // A
    
    if (*op_end != ',') {
      as_bad(_("missing comma: %s"), op_end);
      return;
    }
    op_end++;
    while (ISSPACE(*op_end))
      op_end++;
    op_end = parse_exp_save_ilp(op_end, &arg);
    if (opcode->size) {
      md_number_to_chars(p, iword, 4);
      p = frag_more(4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_32);
    } else {
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset >= 32768) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  }

  while (ISSPACE(*op_end))
    op_end++;
  if (*op_end != 0)
    as_warn("extra stuff on line ignored %s %c", op_start, *op_end);
  if (pending_reloc)
    as_bad("Something forgot to clean up\n");
  return;
}
예제 #10
0
    case O_R32:
      return BFD_RELOC_PJ_CODE_REL32;
    case O_32:
      return BFD_RELOC_PJ_CODE_DIR32;
    }
  abort ();
  return 0;
}

/* Handler for the ipush fake opcode,
   turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>.  */

static void
ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str)
{
  char *b = frag_more (6);
  expressionS arg;

  b[0] = 0x11;
  b[3] = 0xed;
  parse_exp_save_ilp (str + 1, &arg);
  if (pending_reloc)
    {
      as_bad (_("can't have relocation for ipush"));
      pending_reloc = 0;
    }

  fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
	       &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
  fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
	       &arg, 0, BFD_RELOC_PJ_CODE_HI16);
예제 #11
0
static void
output_cfi_insn (struct cfi_insn_data *insn)
{
  offsetT offset;
  unsigned int regno;

  switch (insn->insn)
    {
    case DW_CFA_advance_loc:
      {
	symbolS *from = insn->u.ll.lab1;
	symbolS *to = insn->u.ll.lab2;

	if (symbol_get_frag (to) == symbol_get_frag (from))
	  {
	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;

	    if (scaled <= 0x3F)
	      out_one (DW_CFA_advance_loc + scaled);
	    else if (scaled <= 0xFF)
	      {
		out_one (DW_CFA_advance_loc1);
		out_one (scaled);
	      }
	    else if (scaled <= 0xFFFF)
	      {
		out_one (DW_CFA_advance_loc2);
		out_two (scaled);
	      }
	    else
	      {
		out_one (DW_CFA_advance_loc4);
		out_four (scaled);
	      }
	  }
	else
	  {
	    expressionS exp;

	    exp.X_op = O_subtract;
	    exp.X_add_symbol = to;
	    exp.X_op_symbol = from;
	    exp.X_add_number = 0;

	    /* The code in ehopt.c expects that one byte of the encoding
	       is already allocated to the frag.  This comes from the way
	       that it scans the .eh_frame section looking first for the
	       .byte DW_CFA_advance_loc4.  */
	    *frag_more (1) = DW_CFA_advance_loc4;

	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
		      make_expr_symbol (&exp), frag_now_fix () - 1,
		      (char *) frag_now);
	  }
      }
      break;

    case DW_CFA_def_cfa:
      offset = insn->u.ri.offset;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_sf);
	  out_uleb128 (insn->u.ri.reg);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa);
	  out_uleb128 (insn->u.ri.reg);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_undefined:
    case DW_CFA_same_value:
      out_one (insn->insn);
      out_uleb128 (insn->u.r);
      break;

    case DW_CFA_def_cfa_offset:
      offset = insn->u.i;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_offset_sf);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa_offset);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_restore:
      regno = insn->u.r;
      if (regno <= 0x3F)
	{
	  out_one (DW_CFA_restore + regno);
	}
      else
	{
	  out_one (DW_CFA_restore_extended);
	  out_uleb128 (regno);
	}
      break;

    case DW_CFA_offset:
      regno = insn->u.ri.reg;
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
      if (offset < 0)
	{
	  out_one (DW_CFA_offset_extended_sf);
	  out_uleb128 (regno);
	  out_sleb128 (offset);
	}
      else if (regno <= 0x3F)
	{
	  out_one (DW_CFA_offset + regno);
	  out_uleb128 (offset);
	}
      else
	{
	  out_one (DW_CFA_offset_extended);
	  out_uleb128 (regno);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_register:
      out_one (DW_CFA_register);
      out_uleb128 (insn->u.rr.reg1);
      out_uleb128 (insn->u.rr.reg2);
      break;

    case DW_CFA_remember_state:
    case DW_CFA_restore_state:
      out_one (insn->insn);
      break;

    case DW_CFA_GNU_window_save:
      out_one (DW_CFA_GNU_window_save);
      break;

    case CFI_escape:
      {
	struct cfi_escape_data *e;
	for (e = insn->u.esc; e ; e = e->next)
	  emit_expr (&e->exp, 1);
	break;
      }

    case CFI_val_encoded_addr:
      {
        unsigned encoding = insn->u.ea.encoding;
        offsetT encoding_size;

	if (encoding == DW_EH_PE_omit)
	  break;
	out_one (DW_CFA_val_expression);
	out_uleb128 (insn->u.ea.reg);

        switch (encoding & 0x7)
	  {
	  case DW_EH_PE_absptr:
	    encoding_size = DWARF2_ADDR_SIZE (stdoutput);
	    break;
	  case DW_EH_PE_udata2:
	    encoding_size = 2;
	    break;
	  case DW_EH_PE_udata4:
	    encoding_size = 4;
	    break;
	  case DW_EH_PE_udata8:
	    encoding_size = 8;
	    break;
	  default:
	    abort ();
	  }

	/* If the user has requested absolute encoding,
	   then use the smaller DW_OP_addr encoding.  */
	if (insn->u.ea.encoding == DW_EH_PE_absptr)
	  {
	    out_uleb128 (1 + encoding_size);
	    out_one (DW_OP_addr);
	  }
	else
	  {
	    out_uleb128 (1 + 1 + encoding_size);
	    out_one (DW_OP_GNU_encoded_addr);
	    out_one (encoding);

	    if ((encoding & 0x70) == DW_EH_PE_pcrel)
	      {
#if CFI_DIFF_EXPR_OK
		insn->u.ea.exp.X_op = O_subtract;
		insn->u.ea.exp.X_op_symbol = symbol_temp_new_now ();
#elif defined (tc_cfi_emit_pcrel_expr)
		tc_cfi_emit_pcrel_expr (&insn->u.ea.exp, encoding_size);
		break;
#else
		abort ();
#endif
	      }
	  }
	emit_expr (&insn->u.ea.exp, encoding_size);
      }
      break;

    default:
      abort ();
    }
}
예제 #12
0
static void
out_sleb128 (offsetT value)
{
  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
}
예제 #13
0
static void
output_cfi_insn (struct cfi_insn_data *insn)
{
  offsetT offset;
  unsigned int regno;

  switch (insn->insn)
    {
    case DW_CFA_advance_loc:
      {
	symbolS *from = insn->u.ll.lab1;
	symbolS *to = insn->u.ll.lab2;

	if (symbol_get_frag (to) == symbol_get_frag (from))
	  {
	    addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
	    addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;

	    if (scaled <= 0x3F)
	      out_one (DW_CFA_advance_loc + scaled);
	    else if (delta <= 0xFF)
	      {
	        out_one (DW_CFA_advance_loc1);
	        out_one (delta);
	      }
	    else if (delta <= 0xFFFF)
	      {
	        out_one (DW_CFA_advance_loc2);
	        out_two (delta);
	      }
	    else
	      {
	        out_one (DW_CFA_advance_loc4);
	        out_four (delta);
	      }
	  }
	else
	  {
	    expressionS exp;

	    exp.X_op = O_subtract;
	    exp.X_add_symbol = to;
	    exp.X_op_symbol = from;
	    exp.X_add_number = 0;

	    /* The code in ehopt.c expects that one byte of the encoding
	       is already allocated to the frag.  This comes from the way
	       that it scans the .eh_frame section looking first for the
	       .byte DW_CFA_advance_loc4.  */
	    frag_more (1);

	    frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
		      make_expr_symbol (&exp), frag_now_fix () - 1,
		      (char *) frag_now);
	  }
      }
      break;

    case DW_CFA_def_cfa:
      offset = insn->u.ri.offset;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_sf);
	  out_uleb128 (insn->u.ri.reg);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa);
	  out_uleb128 (insn->u.ri.reg);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_undefined:
    case DW_CFA_same_value:
      out_one (insn->insn);
      out_uleb128 (insn->u.r);
      break;

    case DW_CFA_def_cfa_offset:
      offset = insn->u.i;
      if (offset < 0)
	{
	  out_one (DW_CFA_def_cfa_offset_sf);
	  out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
	}
      else
	{
	  out_one (DW_CFA_def_cfa_offset);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_restore:
      regno = insn->u.r;
      if (regno <= 0x3F)
	{
	  out_one (DW_CFA_restore + regno);
	}
      else
	{
	  out_one (DW_CFA_restore_extended);
	  out_uleb128 (regno);
	}
      break;

    case DW_CFA_offset:
      regno = insn->u.ri.reg;
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
      if (offset < 0)
	{
	  out_one (DW_CFA_offset_extended_sf);
	  out_uleb128 (regno);
	  out_sleb128 (offset);
	}
      else if (regno <= 0x3F)
	{
	  out_one (DW_CFA_offset + regno);
	  out_uleb128 (offset);
	}
      else
	{
	  out_one (DW_CFA_offset_extended);
	  out_uleb128 (regno);
	  out_uleb128 (offset);
	}
      break;

    case DW_CFA_register:
      out_one (DW_CFA_register);
      out_uleb128 (insn->u.rr.reg1);
      out_uleb128 (insn->u.rr.reg2);
      break;

    case DW_CFA_remember_state:
    case DW_CFA_restore_state:
      out_one (insn->insn);
      break;

    case DW_CFA_GNU_window_save:
      out_one (DW_CFA_GNU_window_save);
      break;

    case CFI_escape:
      {
	struct cfi_escape_data *e;
	for (e = insn->u.esc; e ; e = e->next)
	  emit_expr (&e->exp, 1);
	break;
      }

    default:
      abort ();
    }
}