Esempio n. 1
0
File: sparc.c Progetto: npe9/sprite
static void
s_common()
{
    register char *name;
    register char c;
    register char *p;
    register int temp;
    register symbolS *	symbolP;

    name = input_line_pointer;
    c = get_symbol_end();
    /* just after name is now '\0' */
    p = input_line_pointer;
    *p = c;
    SKIP_WHITESPACE();
    if ( * input_line_pointer != ',' ) {
	as_warn("Expected comma after symbol-name");
	ignore_rest_of_line();
	return;
    }
    input_line_pointer ++; /* skip ',' */
    if ( (temp = get_absolute_expression ()) < 0 ) {
	as_warn(".COMMon length (%d.) <0! Ignored.", temp);
	ignore_rest_of_line();
	return;
    }
    *p = 0;
    symbolP = symbol_find_or_make (name);
    *p = c;
    if (   (symbolP->sy_type & N_TYPE) != N_UNDF ||
        symbolP->sy_other != 0 || symbolP->sy_desc != 0) {
	as_warn( "Ignoring attempt to re-define symbol");
	ignore_rest_of_line();
	return;
    }
    if (symbolP->sy_value) {
	if (symbolP->sy_value != temp) {
	    as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
		symbolP->sy_name, symbolP->sy_value, temp);
	}
    } else {
	symbolP->sy_value = temp;
	symbolP->sy_type |= N_EXT;
    }
    know(symbolP->sy_frag == &zero_address_frag);
    if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
	p=input_line_pointer;
	while(*p && *p!='\n')
		p++;
	c= *p;
	*p='\0';
	as_warn("bad .common segment: `%s'", input_line_pointer);
	*p=c;
	return;
    }
    input_line_pointer += 6;
    demand_empty_rest_of_line();
    return;
}
Esempio n. 2
0
static int
parse_register_operand (char **ptr)
{
  int reg;
  char *s = *ptr;

  if (*s != '$')
    {
      as_bad (_("expecting register"));
      ignore_rest_of_line ();
      return -1;
    }
  if (s[1] == 'f' && s[2] == 'p')
    {
      *ptr += 3;
      return 0;
    }
  if (s[1] == 's' && s[2] == 'p')
    {
      *ptr += 3;
      return 1;
    }
  if (s[1] == 'r')
    {
      reg = s[2] - '0';
      if ((reg < 0) || (reg > 9))
	{
	  as_bad (_("illegal register number"));
	  ignore_rest_of_line ();
	  return -1;
	}
      if (reg == 1)
	{
	  int r2 = s[3] - '0';
	  if ((r2 >= 0) && (r2 <= 3))
	    {
	      reg = 10 + r2;
	      *ptr += 1;
	    }
	}
    }
  else
    {
      as_bad (_("illegal register number"));
      ignore_rest_of_line ();
      return -1;
    }

  *ptr += 3;

  return reg + 2;
}
Esempio n. 3
0
File: sparc.c Progetto: npe9/sprite
/*
 * sort of like s_lcomm
 *
 */
static void
s_reserve()
{
    char *name;
    char c;
    char *p;
    int temp;
    symbolS *symbolP;

    name = input_line_pointer;
    c = get_symbol_end();
    p = input_line_pointer;
    *p = c;
    SKIP_WHITESPACE();
    if ( * input_line_pointer != ',' ) {
	as_warn("Expected comma after name");
	ignore_rest_of_line();
	return;
    }
    input_line_pointer ++;
    if ((temp = get_absolute_expression()) < 0) {
	as_warn("BSS length (%d.) <0! Ignored.", temp);
	ignore_rest_of_line();
	return;
    }
    *p = 0;
    symbolP = symbol_find_or_make(name);
    *p = c;
    if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
	as_warn("bad .reserve segment: `%s'", input_line_pointer);
	return;
    }
    input_line_pointer += 6;
    if (symbolP->sy_other == 0 
        && symbolP->sy_desc  == 0
	&& ((symbolP->sy_type  == N_BSS
	&& symbolP->sy_value == local_bss_counter)
	|| ((symbolP->sy_type & N_TYPE) == N_UNDF
	&& symbolP->sy_value == 0))) {
	    symbolP->sy_value = local_bss_counter;
	    symbolP->sy_type  = N_BSS;
	    symbolP->sy_frag  = & bss_address_frag;
	    local_bss_counter += temp;
    } else {
	as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
	    symbolP->sy_value, local_bss_counter );
    }
    demand_empty_rest_of_line();
    return;
}
Esempio n. 4
0
static int
parse_regnum(char **ptr)
{
  int reg;
  char *s = *ptr;

  if (*s != '%') {
    as_bad(_("not a register: %s"), s);
    return -1;
  }
  s++;

  // %fp alias for %14
  if (s[0] == 'f' && s[1] == 'p') {
    *ptr += 3;
    return 14;
  }

  // %sp alias for %15
  if (s[0] == 's' && s[1] == 'p') {
    *ptr += 3;
    return 15;
  }

  reg = *s - '0';
  if ((reg < 0) || (reg > 9)) {
    as_bad(_("illegal register number 1 %s"), s);
    ignore_rest_of_line();
    return -1;
  }
  s++;

  if ((reg > 0) || (reg < 4)) {
    int r2 = *s - '0';
    if ((r2 >= 0) && (r2 <= 9)) {
      reg = reg*10 + r2;
      if (reg > 31) {
	as_bad(_("illegal register number %d"), reg);
	ignore_rest_of_line();
	return -1;
      }
      *ptr += 1;
    }
  } 
  
  *ptr += 2;
  return reg;
}
Esempio n. 5
0
    void read_vertex () {
        int number;
        is >> number;

        // vertex number is terminated by colon
        is >> std::ws;
        int colon;
        if ((colon = is.get ()) != ':')
            format_error ("expected colon, got %c", colon);

        // coords
        double x, y, z;
        is >> x >> y >> z;

        // rest of record (i.e. attributes) is ignored for now
        ignore_rest_of_line ();

        // z coordinate is ignored
        int vert_id = b->insert_vertex (vec_t (x, y));

        // saved for later reference
        if ((int)vertex_map.size () <= number) {
            vertex_map.resize (number + 1, Boundary::INVALID_VERTEX);
        }
        vertex_map[number] = vert_id;
    }
Esempio n. 6
0
File: cond.c Progetto: great90/gcl
void
s_ifdef (int test_defined)
{
  /* Points to name of symbol.  */
  char *name;
  /* Points to symbol.  */
  symbolS *symbolP;
  struct conditional_frame cframe;
  char c;

  /* Leading whitespace is part of operand.  */
  SKIP_WHITESPACE ();
  name = input_line_pointer;

  if (!is_name_beginner (*name))
    {
      as_bad (_("invalid identifier for \".ifdef\""));
      obstack_1grow (&cond_obstack, 0);
      ignore_rest_of_line ();
      return;
    }

  c = get_symbol_end ();
  symbolP = symbol_find (name);
  *input_line_pointer = c;

  initialize_cframe (&cframe);
  
  if (cframe.dead_tree)
    cframe.ignoring = 1;
  else
    {
      int is_defined;

      /* Use the same definition of 'defined' as .equiv so that a symbol
	 which has been referenced but not yet given a value/address is
	 considered to be undefined.  */
      is_defined =
	symbolP != NULL
	&& S_IS_DEFINED (symbolP)
	&& S_GET_SEGMENT (symbolP) != reg_section;

      cframe.ignoring = ! (test_defined ^ is_defined);
    }

  current_cframe = ((struct conditional_frame *)
		    obstack_copy (&cond_obstack, &cframe,
				  sizeof (cframe)));

  if (LISTING_SKIP_COND ()
      && cframe.ignoring
      && (cframe.previous_cframe == NULL
	  || ! cframe.previous_cframe->ignoring))
    listing_list (2);

  demand_empty_rest_of_line ();
}
static void
dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
{
    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    cfi_end_fde (symbol_temp_new_now ());

    demand_empty_rest_of_line ();
}
Esempio n. 8
0
void
obj_som_version (int unused ATTRIBUTE_UNUSED)
{
  char *version, c;

  if (version_seen)
    {
      as_bad (_("Only one .version pseudo-op per file!"));
      ignore_rest_of_line ();
      return;
    }

  SKIP_WHITESPACE ();
  if (*input_line_pointer == '\"')
    {
      version = input_line_pointer;
      ++input_line_pointer;
      while (is_a_char (next_char_of_string ()))
	;
      c = *input_line_pointer;
      *input_line_pointer = '\000';
    }
  else
    {
      as_bad (_("Expected quoted string"));
      ignore_rest_of_line ();
      return;
    }

  version_seen = 1;
  if (!bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version))
    as_fatal (_("attaching version header %s: %s"),
	      stdoutput->filename, bfd_errmsg (bfd_get_error ()));

  *input_line_pointer = c;
  demand_empty_rest_of_line ();
}
Esempio n. 9
0
void
obj_som_copyright (int unused ATTRIBUTE_UNUSED)
{
  char *copyright, c;

  if (copyright_seen)
    {
      as_bad (_("Only one .copyright pseudo-op per file!"));
      ignore_rest_of_line ();
      return;
    }

  SKIP_WHITESPACE ();
  if (*input_line_pointer == '\"')
    {
      copyright = input_line_pointer;
      ++input_line_pointer;
      while (is_a_char (next_char_of_string ()))
	;
      c = *input_line_pointer;
      *input_line_pointer = '\000';
    }
  else
    {
      as_bad (_("Expected quoted string"));
      ignore_rest_of_line ();
      return;
    }

  copyright_seen = 1;
  if (!bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright))
    as_fatal (_("attaching copyright header %s: %s"),
	      stdoutput->filename, bfd_errmsg (bfd_get_error ()));

  *input_line_pointer = c;
  demand_empty_rest_of_line ();
}
Esempio n. 10
0
    void read_poly () {
        int number;
        is >> number;

        // poly number is terminated by colon
        is >> std::ws;
        int colon;
        if ((colon = is.get ()) != ':')
            format_error ("PolyFileReader::read_poly: expected colon, got %c", colon);

        // first two vertices
        int initial_vertex;
        is >> initial_vertex;
        // translate POLY vertices into Boundary vertices
        initial_vertex = lookup_vertex (initial_vertex);
        int prev_vertex;
        is >> prev_vertex >> std::ws;
        prev_vertex = lookup_vertex (prev_vertex);

        int initial_edge = b->insert_edge (Boundary::INVALID_EDGE,
                                    initial_vertex, prev_vertex,
                                    Boundary::INVALID_EDGE);

        int prev_edge = initial_edge;
        while (is_digit (is.peek ())) {
            int vertex;
            is >> vertex >> std::ws;
            // translate POLY vertices into Boundary vertices
            vertex = lookup_vertex (vertex);

            int edge = b->insert_edge (prev_edge, prev_vertex,
                                       vertex, Boundary::INVALID_EDGE);
            prev_vertex = vertex;
            prev_edge = edge;
        }

        is >> std::ws;
        int closed_indic = is.peek ();
        if (closed_indic == '<') {
            // extract '<' character
            is.get ();
            // close contour
            b->insert_edge (prev_edge, prev_vertex, initial_vertex, initial_edge);
        } else {
            std::cerr << "WARNING: non-closed contour " << number << ". this is probably not what you want.\n";
        }

        ignore_rest_of_line ();
    }
Esempio n. 11
0
void
dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
{
  offsetT value = get_absolute_expression ();

  if (value != 0 && value != 1)
    {
      as_bad (_("expected 0 or 1"));
      ignore_rest_of_line ();
    }
  else
    {
      dwarf2_loc_mark_labels = value != 0;
      demand_empty_rest_of_line ();
    }
}
Esempio n. 12
0
static void
dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
{
  struct fde_entry *fde;

  if (frchain_now->frch_cfi_data == NULL)
    {
      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
      ignore_rest_of_line ();
      return;
    }

  fde = frchain_now->frch_cfi_data->cur_fde_data;

  cfi_end_fde (symbol_temp_new_now ());

  demand_empty_rest_of_line ();

  if ((cfi_sections & CFI_EMIT_target) != 0)
    tc_cfi_endproc (fde);
}
Esempio n. 13
0
static void
dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
{
  int simple = 0;

  if (frchain_now->frch_cfi_data != NULL)
    {
      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
      ignore_rest_of_line ();
      return;
    }

  cfi_new_fde (symbol_temp_new_now ());

  SKIP_WHITESPACE ();
  if (is_name_beginner (*input_line_pointer))
    {
      char *name, c;

      name = input_line_pointer;
      c = get_symbol_end ();

      if (strcmp (name, "simple") == 0)
	{
	  simple = 1;
	  *input_line_pointer = c;
	}
      else
	input_line_pointer = name;
    }
  demand_empty_rest_of_line ();

  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
  if (!simple)
    tc_cfi_frame_initial_instructions ();

  if ((cfi_sections & CFI_EMIT_target) != 0)
    tc_cfi_startproc ();
}
Esempio n. 14
0
File: cond.c Progetto: great90/gcl
void
s_ifeqs (int arg)
{
  char *s1, *s2;
  int len1, len2;
  int res;
  struct conditional_frame cframe;

  s1 = demand_copy_C_string (&len1);

  SKIP_WHITESPACE ();
  if (*input_line_pointer != ',')
    {
      as_bad (_(".ifeqs syntax error"));
      ignore_rest_of_line ();
      return;
    }

  ++input_line_pointer;

  s2 = demand_copy_C_string (&len2);

  res = len1 == len2 && strncmp (s1, s2, len1) == 0;

  initialize_cframe (&cframe);
  cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
  current_cframe = ((struct conditional_frame *)
		    obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));

  if (LISTING_SKIP_COND ()
      && cframe.ignoring
      && (cframe.previous_cframe == NULL
	  || ! cframe.previous_cframe->ignoring))
    listing_list (2);

  demand_empty_rest_of_line ();
}
Esempio n. 15
0
static void
dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
{
    struct cfi_escape_data *head, **tail, *e;
    struct cfi_insn_data *insn;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    /* If the last address was not at the current PC, advance to current.  */
    if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
            || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
            != frag_now_fix ())
        cfi_add_advance_loc (symbol_temp_new_now ());

    tail = &head;
    do
    {
        e = xmalloc (sizeof (*e));
        do_parse_cons_expression (&e->exp, 1);
        *tail = e;
        tail = &e->next;
    }
    while (*input_line_pointer++ == ',');
    *tail = NULL;

    insn = alloc_cfi_insn_data ();
    insn->insn = CFI_escape;
    insn->u.esc = head;

    --input_line_pointer;
    demand_empty_rest_of_line ();
}
Esempio n. 16
0
static void
obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
{
  char *name;
  int c;
  symbolS *symbolP;

  do
    {
      name = input_line_pointer;
      c = get_symbol_end ();
      if (*name == 0)
	{
	  as_warn (_("badly formed .weak directive ignored"));
	  ignore_rest_of_line ();
	  return;
	}
      c = 0;
      symbolP = symbol_find_or_make (name);
      *input_line_pointer = c;
      SKIP_WHITESPACE ();
      S_SET_WEAK (symbolP);

      if (c == ',')
	{
	  input_line_pointer++;
	  SKIP_WHITESPACE ();
	  if (*input_line_pointer == '\n')
	    c = '\n';
	}

    }
  while (c == ',');

  demand_empty_rest_of_line ();
}
Esempio n. 17
0
static void
dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
{
    struct fde_entry *fde;
    offsetT encoding;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    fde = frchain_now->frch_cfi_data->cur_fde_data;
    encoding = get_absolute_expression ();
    if (encoding == DW_EH_PE_omit)
    {
        demand_empty_rest_of_line ();
        fde->lsda_encoding = encoding;
        return;
    }

    if ((encoding & 0xff) != encoding
            || ((encoding & 0x70) != 0
#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
                && (encoding & 0x70) != DW_EH_PE_pcrel
#endif
               )
            /* leb128 can be handled, but does something actually need it?  */
            || (encoding & 7) == DW_EH_PE_uleb128
            || (encoding & 7) > DW_EH_PE_udata8)
    {
        as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
        ignore_rest_of_line ();
        return;
    }

    if (*input_line_pointer++ != ',')
    {
        as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
        ignore_rest_of_line ();
        return;
    }

    fde->lsda_encoding = encoding;

    expression_and_evaluate (&fde->lsda);
    switch (fde->lsda.X_op)
    {
    case O_symbol:
        break;
    case O_constant:
        if ((encoding & 0x70) == DW_EH_PE_pcrel)
            encoding = DW_EH_PE_omit;
        break;
    default:
        encoding = DW_EH_PE_omit;
        break;
    }

    fde->lsda_encoding = encoding;

    if (encoding == DW_EH_PE_omit)
    {
        as_bad (_("wrong second argument to .cfi_lsda"));
        ignore_rest_of_line ();
        return;
    }

    demand_empty_rest_of_line ();
}
Esempio n. 18
0
static void
dot_cfi (int arg)
{
    offsetT offset;
    unsigned reg1, reg2;

    if (frchain_now->frch_cfi_data == NULL)
    {
        as_bad (_("CFI instruction used without previous .cfi_startproc"));
        ignore_rest_of_line ();
        return;
    }

    /* If the last address was not at the current PC, advance to current.  */
    if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
            || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
            != frag_now_fix ())
        cfi_add_advance_loc (symbol_temp_new_now ());

    switch (arg)
    {
    case DW_CFA_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1, offset);
        break;

    case CFI_rel_offset:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_offset (reg1,
                            offset - frchain_now->frch_cfi_data->cur_cfa_offset);
        break;

    case DW_CFA_def_cfa:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa (reg1, offset);
        break;

    case DW_CFA_register:
        reg1 = cfi_parse_reg ();
        cfi_parse_separator ();
        reg2 = cfi_parse_reg ();
        cfi_add_CFA_register (reg1, reg2);
        break;

    case DW_CFA_def_cfa_register:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_def_cfa_register (reg1);
        break;

    case DW_CFA_def_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (offset);
        break;

    case CFI_adjust_cfa_offset:
        offset = cfi_parse_const ();
        cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
                                    + offset);
        break;

    case DW_CFA_restore:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_restore (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_undefined:
        for (;;)
        {
            reg1 = cfi_parse_reg ();
            cfi_add_CFA_undefined (reg1);
            SKIP_WHITESPACE ();
            if (*input_line_pointer != ',')
                break;
            ++input_line_pointer;
        }
        break;

    case DW_CFA_same_value:
        reg1 = cfi_parse_reg ();
        cfi_add_CFA_same_value (reg1);
        break;

    case CFI_return_column:
        reg1 = cfi_parse_reg ();
        cfi_set_return_column (reg1);
        break;

    case DW_CFA_remember_state:
        cfi_add_CFA_remember_state ();
        break;

    case DW_CFA_restore_state:
        cfi_add_CFA_restore_state ();
        break;

    case DW_CFA_GNU_window_save:
        cfi_add_CFA_insn (DW_CFA_GNU_window_save);
        break;

    case CFI_signal_frame:
        frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
        break;

    default:
        abort ();
    }

    demand_empty_rest_of_line ();
}
Esempio n. 19
0
static void nemaweaver_s_lcomm (int xxx ATTRIBUTE_UNUSED)
{
    char *name;
    char c;
    char *p;
    offsetT size;
    symbolS *symbolP;
    offsetT align;
    char *pfrag;
    int align2;
    segT    current_seg    = now_seg;
    subsegT current_subseg = now_subseg;

    name = input_line_pointer;
    c = get_symbol_end ();

    /* Just after name is now '\0'.  */
    p = input_line_pointer;
    *p = c;
    SKIP_WHITESPACE ();
    if (*input_line_pointer != ',')
    {
	as_bad (_("Expected comma after symbol-name: rest of line ignored."));
	ignore_rest_of_line ();
	return;
    }

    input_line_pointer++;		/* skip ',' */
    if ((size = get_absolute_expression ()) < 0)
    {
	as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
	ignore_rest_of_line ();
	return;
    }

    /* The third argument to .lcomm is the alignment.  */
    if (*input_line_pointer != ',')
	align = 8;
    else
    {
	++input_line_pointer;
	align = get_absolute_expression ();
	if (align <= 0)
	{
	    as_warn (_("ignoring bad alignment"));
	    align = 8;
	}
    }

    *p = 0;
    symbolP = symbol_find_or_make (name);
    *p = c;

    if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
    {
	as_bad (_("Ignoring attempt to re-define symbol `%s'."),
		S_GET_NAME (symbolP));
	ignore_rest_of_line ();
	return;
    }

    if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
    {
	as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
		S_GET_NAME (symbolP),
		(long) S_GET_VALUE (symbolP),
		(long) size);

	ignore_rest_of_line ();
	return;
    }

    /* Allocate_bss.  */
    if (align)
    {
	/* Convert to a power of 2 alignment.  */
	for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
	if (align != 1)
	{
	    as_bad (_("Common alignment not a power of 2"));
	    ignore_rest_of_line ();
	    return;
	}
    }
    else
Esempio n. 20
0
void
obj_som_compiler (int unused ATTRIBUTE_UNUSED)
{
  char *buf;
  char c;
  char *filename;
  char *language_name;
  char *p;
  char *version_id;

  if (compiler_seen)
    {
      as_bad (_("Only one .compiler pseudo-op per file!"));
      ignore_rest_of_line ();
      return;
    }

  SKIP_WHITESPACE ();
  if (*input_line_pointer == '\"')
    {
      buf = input_line_pointer;
      ++input_line_pointer;
      while (is_a_char (next_char_of_string ()))
	;
      c = *input_line_pointer;
      *input_line_pointer = '\000';
    }
  else
    {
      as_bad (_("Expected quoted string"));
      ignore_rest_of_line ();
      return;
    }

  /* Parse the quoted string into its component parts.  Skip the
     quote.  */
  filename = buf + 1;
  p = filename;
  while (*p != ' ' && *p != '\000')
    p++;
  if (*p == '\000')
    {
      as_bad (_(".compiler directive missing language and version"));
      return;
    }
  *p = '\000';

  language_name = ++p;
  while (*p != ' ' && *p != '\000')
    p++;
  if (*p == '\000')
    {
      as_bad (_(".compiler directive missing version"));
      return;
    }
  *p = '\000';

  version_id = ++p;
  while (*p != '\000')
    p++;
  /* Remove the trailing quote.  */
  *(--p) = '\000';

  compiler_seen = 1;
  if (! bfd_som_attach_compilation_unit (stdoutput, filename, language_name,
					 "GNU Tools", version_id))
    {
      bfd_perror (stdoutput->filename);
      as_fatal (_("FATAL: Attaching compiler header %s"), stdoutput->filename);
    }
  *input_line_pointer = c;
  demand_empty_rest_of_line ();
}
Esempio n. 21
0
static void
dot_cfi_dummy (int ignored ATTRIBUTE_UNUSED)
{
  as_bad (_("CFI is not supported for this target"));
  ignore_rest_of_line ();
}
Esempio n. 22
0
static void
dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED)
{
  struct cfi_insn_data *insn_ptr;
  offsetT encoding;

  if (frchain_now->frch_cfi_data == NULL)
    {
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
      ignore_rest_of_line ();
      return;
    }

  /* If the last address was not at the current PC, advance to current.  */
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
      || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
	 != frag_now_fix ())
    cfi_add_advance_loc (symbol_temp_new_now ());

  insn_ptr = alloc_cfi_insn_data ();
  insn_ptr->insn = CFI_val_encoded_addr;

  insn_ptr->u.ea.reg = cfi_parse_reg ();

  cfi_parse_separator ();
  encoding = cfi_parse_const ();
  if ((encoding & 0xff) != encoding
      || ((encoding & 0x70) != 0
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
	  && (encoding & 0x70) != DW_EH_PE_pcrel
#endif
	  )
	 /* leb128 can be handled, but does something actually need it?  */
      || (encoding & 7) == DW_EH_PE_uleb128
      || (encoding & 7) > DW_EH_PE_udata8)
    {
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
      encoding = DW_EH_PE_omit;
    }

  cfi_parse_separator ();
  expression_and_evaluate (&insn_ptr->u.ea.exp);
  switch (insn_ptr->u.ea.exp.X_op)
    {
    case O_symbol:
      break;
    case O_constant:
      if ((encoding & 0x70) != DW_EH_PE_pcrel)
        break;
    default:
      encoding = DW_EH_PE_omit;
      break;
    }

  insn_ptr->u.ea.encoding = encoding;
  if (encoding == DW_EH_PE_omit)
    {
      as_bad (_("wrong third argument to .cfi_val_encoded_addr"));
      ignore_rest_of_line ();
      return;
    }

  demand_empty_rest_of_line ();
}
Esempio n. 23
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;
}
Esempio n. 24
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;
    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"));
}